Blackboard is a web application that teachers and students use to deliver and evaluate assignments, manage courses and exchange files.
According to their website they currently serve over 16,000 schools and universities across 90 countries reaching 100 million users.
Eirik Fosse, Sondre Hjetland and Michael McMillan discovered three vulnerabilities that enabled us to hijack our teacher's account and change our grades.
No. The vulnerabilities were immediately reported to Blackboard and the NTNU Security Operations Center on the 9th of February 2018. They were confirmed patched 61 days later.
Below is a timeline of the most important events.
Blackboard stopped responding to our e-mails 05/28.
How did it work?
A student (attacker) submits an assignment to his professor (victim). The professor clicks the link and evaluates the assignment. The student has now gained access to the professor's account – unbeknownst to the professor – and has full access to whatever the professor is authorized to do on Blackboard; change grades, download files not intended for students, e-mail other users and so on.
So what made this possible? Let's walk through it.
Like most learning platforms, Blackboard allows its users to upload files. This feature is primarily used by students to upload assignments and by professors to upload slides. But unlike the other platforms, Blackboard serves the uploaded files on the same origin as the application itself.
Needless to say, this is disastrous from a security perspective and in violation of one of the fundamental tenets of software security: Never trust user input. Consequently, this means that a user uploaded file on Blackboard is indistinguishable from Blackboard's application. An unsuspecting user who views an uploaded file on Blackboard automatically grants it access to perform actions on his behalf.
It turns out that Blackboard had anticipated that user uploaded files could abuse the same-origin policy by including malicious code. Their solution? Filter out anything that looks malicious. If your alarm bell didn't go off at the previous section, it's hopefully making a lot of noise now.
After a lot of trial and error we found two ways of fooling the cross-site scripting filter.
Blackboard let's users upload files using the WebDAV protocol – a true 20th century Frankenstein brought to life by Microsoft. With some technical acrobatics we discovered that the cross-site scripting filter tripped up when we uploaded a file with a null byte through WebDAV.
For some inexplainable reason a different set of filters were applied when uploading files that contained a leading null byte.
However, the null byte was no silver bullet – it only opened the door to a cleverly crafted exploit as certain characters re-activated the original filters. The malicious code in the uploaded file could therefore only consist of a small subset of harmless-looking characters.
To our surprise we discovered that with only 6 characters ([, ], (, ), !, +) one can craft perverse, yet valid JavaScript. Coincidentally, these characters did not trigger the filter after fooling it with the null byte. This meant that an attacker could simply encode his malicious code and smuggle it right past the filter, as demonstrated below.
$ hexdump -C null-byte.html 00000000 00 3c 69 6d 67 20 73 72 63 3d 2e 20 6f 6e 65 72 .<img src=. oner 00000010 72 6f 72 3d 5b 5d 5b 28 21 5b 5d 2b 5b 5d 29 5b ror=[][(![]+[])[ 00000020 2b 5b 5d 5d 2b 28 5b 21 5b 5d 5d 2b 5b 5d 5b 5b +[]]+([![]]+[][[ 00000030 5d 5d 29 5b 2b 21 2b 5b 5d 2b 5b 2b 5b 5d 5d 5d ]])[+!+[]+[+[]]] [...]
When omitting the null byte the filter correctly disarms the onerror attribute by replacing it with xx.
$ hexdump -C without-null-byte.html 00000000 3c 69 6d 67 20 73 72 63 3d 2e 20 78 78 3d 5b 5d <img src=. xx=[] 00000010 5b 28 21 5b 5d 2b 5b 5d 29 5b 2b 5b 5d 5d 2b 28 [(![]+[])[+[]]+( 00000020 5b 21 5b 5d 5d 2b 5b 5d 5b 5b 5d 5d 29 5b 2b 21 [![]]+[][[]])[+! 00000030 2b 5b 5d 2b 5b 2b 5b 5d 5d 5d 2b 28 21 5b 5d 2b +[]+[+[]]]+(![]+
A more trivial way of bypassing the cross-site script filter was to upload an XML or SVG file that referenced the HTML namespace. This blindspot allowed us to drop straight into a script element and run whatever JavaScript we pleased.
$ cat malicious.xml <html> <head></head> <body> <ouch:script xmlns:ouch="http://www.w3.org/1999/xhtml"> alert('