P.W.N University: web 200 - H!pster Startup writeup

This weekend the P.W.N. university CTF took place and I took a 30 min break from studying to solve the web 200 challenge H!pster Startup.

As usual, I played with the ENOFLAG aka LEGOFAN team.

The description did not directly give away how to solve it:

Our on-campus start-up was hacked.
The hacker somehow deleted the only admin user... Can you login to the admin interface and revert it?

After firing up burp suite and requesting the url http://cyberai.uni.hctf.fun/ I discovered a pointer to an admin panel in the source code:


Requesting /admin lead to a login form, apparently for the admin whose credentials were deleted.


After trying some common crendentials like admin/admin, admin/password or simply admin/123, I was curious if we would need an authentication bypass to access the admin dashboard. As we probably do not want to brute force the right password, maybe an SQL injection can help us to return some valid credentials?

Appending a ' to either of the parameters user and passwd lead to an verbose error message complaining about a malformed SQL query. Yay, SQL injection!?!

Googling for AQL syntax error showed results about a NoSQL database called ArangoDB:


Not having done anything with ArangoDB yet, I started to read through the documentation to get a feeling for this DBMS.

I found a passage stating that a returned document can be updated 'in-place', but apparently the database access was limited to read-only:


Submitting valid credentials or a query that resulted in the equivalent of true = true, redirected to a page which said that `the user's role is not admin':


Reading further up on the details how the ArangoDB works and what the RETURN statement is capable to do, I came across a feature that allows us to use { ... } to return a whole new document with additional attributes, i.e. a projection if I recall correctly. Trying to return {u: u, role: 'admin'}, however, still resulted in an error message:


I had no idea why the query returned 0 instead of a valid document, so I started looking for an explanation. Googling for Try setting rawResults to True lead me to the source code of ArangoDB on GitHub:


The exception is caused by a KeyError which apparently gets thrown if the docJson does not contain an _id key.

Extending the injection we used before by an additional attribute _id: "users/a" finally returned the flag:


Overall, a well done challenge and I enjoyed solving it! And with only 25 minutes from reading the description until I had the flag - my fastest solve so far, I believe.