SANS Holiday Hack Challenge 2019 Postmortem — Part 1
Recently, my colleague Kee Hock and I participated in the SANS Holiday Hack Challenge 2019 and obtained a Super Honorable Mention (our submission can be found here). In this article, I’d like to share one of our more interesting challenges when we decided to manually exploit it instead of using automated tools.
Reconnaissance
The only information given about the challenge is provided by the challenge prompt:
Gain access to the data on the Student Portal server and retrieve the paper scraps hosted there. What is the name of Santa’s cutting-edge sleigh guidance system?
For hints on achieving this objective, please visit the dorm and talk with Pepper Minstix.
Pepper Minstix helpfully informs us that that we can use a tool called sqlmap
to help with SQL injections. Based on this hint, it is reasonable to assume that SQL injection might be required to gain access to the data we want. We’re not going to use the tool though.
Exploring the Student Portal website, we can see that it contains 2 pages with forms, the application form and the application status form.
The application status form is simpler so let’s study it. There is some basic input sanitisation in the input
box that is currently preventing us from submitting any value we want. This is due to the input box specifying type="email"
which attempts to ensure that the value is a properly formatted email address. This, though, can easily be bypassed within the browser itself. Using the browser’s Devtools, we can edit the type
from email
to text
.
Let’s try to trigger a trivial SQL injection.
Fantastic, the application helpfully gives us an error message. This tells us what the original SQL query is, which will be useful in crafting our exploit. We also note that the URL bar contains a token
parameter: https://studentportal.elfu.org/application-check.php?elfmail='&token=MTAx…
, but more on that later. Let’s try to exploit this vulnerability with our own script.
Writing an error based SQLi script
Here is the original SQL query in full from the error message:
SELECT status FROM applications WHERE elfmail = '{INJECTION}';
To inject the WHERE
clause, we can simply do something like 1' AND (SELECT user());-- -
and replace the SELECT user()
with a query we want to run.
SELECT status FROM applications WHERE elfmail = '1' AND (SELECT user());-- -';
As we can see, 1'
closes the quote, allowing us to place our own SQL query after the AND
. To deal with the ';
in the original query, we can add --
to the end of our injection, turning the rest of the statement into a comment. With the two steps above, the statement is now valid SQL.
However, simply executing valid SQL is not sufficient as we need to be able to retrieve the results of the SQL query. Since there’s an error message, lets see if we can use that to our advantage. We can try to provide our SQL query as an invalid input to a database function; doing so can cause the application to error out and return the results of our query as an error message. One method to do this is via the UpdateXML()
function in MySQL.
1' AND (UpdateXML(1, concat(0x7e, (SELECT user())), 0));-- -
The second argument of the UpdateXML()
function expects a valid XPath. Since concat(0x7e, (SELECT user()))
does not return one, we instead see the error message above with the output of our query.
Another thing that we have to note is the token
parameter in the URL, commonly known as a CSRF token. The token is a unique value that cannot be repeated or reused. If we attempt to request the data without the token or attempt to reuse an old token, we’d simply get an error message. This prevents an attacker from trying to request from the URL directly as they would need to acquire a valid token first. We can see where this token
variable is generated from by taking a look at the network tab of our browser’s console.
GET
request on application-check.php
We now have all the pieces to create a simple python script:
Success! In less than 10 requests to application-check.php
, we’ve now obtained a list of URLs to help us get the answer to the challenge prompt and complete this challenge.
/krampus/0f5f510e.png
/krampus/1cc7e121.png
/krampus/439f15e6.png
/krampus/667d6896.png
/krampus/adb798ca.png
/krampus/ba417715.png