Last week, InnovHacktion participated in the great InsomniHack CTF. It’s easily one of the hardest CTFs I’ve been to so far, and I can’t wait to try it again next year. We placed 76th out of 1000, but out of those 1000 teams only about 350 scored anything at all. So 76/350 if you want to count that way. We were also 11th in France!
Shobot was an odd challenge which included an SQL injection, but the impossibility to use SQLmap due to a “trust” system, on a weird site where you buy sex robots for tens of thousands of dollars. This challenge was worth 200 points, and was only validated by 83 teams.
No, I’m not kidding.
The website itself seems straightforward: You can buy sexy robots on their online shop, but when you try checking out, the server informs you that it has gained self-awareness and refuses to sell you robots. I guess I’ll have to keep using my hand, unless I can get control of the server back…
A look at the home page source code shows us a few interesting things:
Little-known fact: This is how real hackers browse the internet.
At the top, there’s weird “trust” variables with “movement” and “newTrust” fields. Weird… We’ll get back to it later. There’s also a commented-out admin page. Upon visiting it, we’re asked to give a login and password, and the Server then basically tells us that it has changed the admin’s password so he can’t access the site either. Ok, cool.
So we start poking around, and find out a few interesting things. Everytime we try to SQLi anything, the website tells us we aren’t “trusted” enough. We make the connection with the trust parameters in the source code and start experimenting. We soon found out that:
-
The website uses a trust system to see which users are “trustworthy”. You gain trust by buying items (3 trust for putting something in your cart, 10 for checking out your cart).
-
Trustworthy users are allowed to do weird things with URLs, which lets us test things. But this costs a lot, if the website detects that we’re doing an SQL injection for example, we lose 75 points.
The message you get if you try anything weird
So we can’t do anything without trust. But we know how to get trust, so let’s code up a small script to get infinite trust! We soon found out that we were capped at 150 or so trust, and found the most efficient way to fill that up quickly. Note that we use a trick where you can add a non-existing item to your cart, but just once (id=0 here):
Using our session ID, we’re able to run this script and get enough trust to poke at the site and start breaking things, our favorite part of any challenge. We quickly find a parameter that acts odd: the “artid” (article id) parameter on the online store. There are only 3 articles, 1 to 3. If we enter values like 0 or 1337, the site doesn’t 404, it just displays a product page with nothing in it, which already tells us this is probably using a database of some sort:
Yes, you can add it to cart.
However, I ended up figuring out that one character behaves differently: an apostrophe. One apostrophe displays an empty page, which tells me there was an internal error and the server just stopped rendering the page there. It’s probably crying, too. The fact that entering a number and then letters, like “artid=2 I like pancakes” doesn’t break and instead displays the page for artid=2 also tells us that this is a MySQL server, which will matter later (MySQL likes to cast things to other things, and in this case, casts strings to ints by removing everything after the first number it finds).
This is what a sad server looks like.
So after poking at it a bit more, we find that the request expects 5 parameters returned, so our UNION’d SELECT should be something like:
artid=0' UNION SELECT 1,1,1,1,1; --%20
Which gives us:
This is the page displaying image 1, title 1, price 1 and description 1, because of our crafty SQL request! nyeh nyeh nyeh
Now we can replace a 1 by what we want to get. We know it’s a MySQL database, so we know how to get table names and the likes, and if we didn’t we could go to this great cheat sheet and pretend we knew it all along. After lots of blind poking around, we find that the user table is called shbt_user
. After a bit more poking around, we find the column names and so the final injection looks like:
artid=0' UNION SELECT 1,1,shbt_username,1,shbt_userpassword FROM shbt_user; --%20
And that gives us:
And that’s it, we get access to the admin panel and get the flag! And that’s how I bought my sex robot.