How We Hacked Our Way to Free 4.0s and Took Over a uWaterloo & UofT Grading Tool

xtra11 pts0 comments

How We Hacked Our Way to Free 4.0s and Took Over a uWaterloo & UofT Grading Tool | xtra

Overview

introduction<br>what is MarkUs?<br>why we went after MarkUs<br>viewing any student’s submission<br>exploiting grades: from 0 to 100<br>pivoting to remote code execution !!!<br>other findings<br>YAML billion laughs denial of service<br>Zip bomb denial of service<br>timeline<br>CVEs

How We Hacked Our Way to Free 4.0s and Took Over a uWaterloo & UofT Grading Tool<br>xtra

May 17, 2026<br>11 min read

Table of Contentsintroduction<br>what is MarkUs?<br>why we went after MarkUs<br>viewing any student’s submission<br>exploiting grades: from 0 to 100<br>pivoting to remote code execution !!!<br>other findings<br>YAML billion laughs denial of service<br>Zip bomb denial of service<br>timeline<br>CVEs

First, I’ll explain what MarkUs is and why we went after it. Then I’ll walk through how a student account could view other students’ submissions, how we could get 100s on assignments/tests, and finally how we escalated to RCE. I’ll also cover a few other vulnerabilities we found along the way.

Important note : We responsibly disclosed these issues to the MarkUs team and did not use them for academic or personal gain or to affect anyone’s grades.

introduction

what is MarkUs?

MarkUs is a web app used for submitting and grading assignments. It helps students submit work, join groups, and view feedback, while TAs and instructors can grade, comment, manage groups, and release marks. It is used for almost all computer science courses at the University of Toronto and the University of Waterloo .

why we went after MarkUs

After a year of doing CTFs with UofTCTF, two friends (Jacky & Ibrahim) and I wanted to move from solving challenges to testing real-world targets. We wanted to apply what we had learned, find actual vulnerabilities, and report them responsibly. MarkUs felt like the perfect target: it is used in almost every UofT CS course, and since we had used it in many of our own courses as UofT CS majors, we already knew how it worked.

viewing any student’s submission

This was the first real bug I found, and it is what made me start looking deeper.

I was clicking around MarkUs with DevTools open, looking at how submissions were loaded. When I opened a submitted file from the grading page, one request stood out:

download_file?select_file_id=5299&show_in_browser=true&preview=true

That select_file_id looked way too direct. So I changed the number and tried the same preview route again. Instead of blocking me, MarkUs rendered a different submitted file.

The code made it pretty clear why this worked. The preview route trusted the id directly:

def html_content

if params[:select_file_id]

file = SubmissionFile.find(params[:select_file_id])

file_contents = file.retrieve_file

grouping = file.submission.grouping

assignment = grouping.assignment

# ...

end

end

That SubmissionFile.find(...) was the issue. It looked up the file globally instead of checking that the file belonged to the student, group, or result I was actually allowed to view.

The policy around the route did not really help either:

alias_rule :download?, :downloads?, :populate_file_manager?, :update_files?, :html_content?, to: :view_files?

def view_files?

true

end

The first request went through download_file, but the browser preview eventually rendered through html_content, which accepted the same select_file_id. After that preview step, the dangerous URL looked like this:

/courses/1/assignments/2/submissions/html_content?select_file_id=5301

The boxed select_file_id was the whole trick. Change that number, and the preview returned a different submitted file.<br>Because the lookup was global, that link could render a submitted file just because the id existed. The course and assignment in the URL did not really limit what came back. In simple words, the file id became the access control.

In other words, this was not limited to one class page or one assignment page. A student could keep changing that boxed number and walk through submissions from other groups, other assignments, and even courses they were not enrolled in on the same MarkUs instance.

That was already bad by itself, but the preview route had another problem: it did not only show plain submitted files. It also rendered notebook and RMarkdown submissions as HTML.

So if the selected file was a malicious .ipynb or .rmd, the same kind of preview link could become an XSS link. A student could submit a malicious notebook, grab its file id, and send the preview link to an instructor. When the instructor opened it, the script ran in the instructor’s MarkUs session.

The same preview route also triggered XSS when the selected file was a malicious notebook.<br>exploiting grades: from 0 to 100

The previous bug COULD be used to exploit grades and other stuff through XSS (we confirmed it), but it still needed an instructor to open a weird preview link. This vuln was different: the instructor did not need to open some random-looking link. They just had to go...

markus file preview student select_file_id after

Related Articles