Mar. 22, 2018
I helped organize ångstromCTF this past week, and it was a huge success with over 1,500 scoring teams. Here are the challenges I wrote:
- Sequel, 50 points
- Weird Message, 100 points
- File Storer, 160 points
- The Best Website, 230 points
- ssh, 150 points (co-wrote with defund, check his writeup repository)
This was a simple SQL injection challenge. One of many ways to solve it is using
' or 1# as the username. If you don’t know why this works, w3schools has a nice overview.
This challenge gave a single text file, containing a message. From the hint
xn--, it could be determined that this was punycode. Punycode can be decoded in Python with:
When you do this, you find that the part of the message after the last dash has been removed, and the one before it has changed. Since punycode appends a dash each time a string is encoded, you know that this was probably encoded many times. Trying to decode again, however, gives an error because of unicode characters. Upon further inspection, the end of the string now has homoglyphs. Replacing these with the similar ASCII characters, the string can be decoded again. However, since there are about 200 dashes, the string was probably encoded 200 times. Decoding by hand would take a very long time. Luckily, this is not too hard to automate. You can either build up a mapping of homoglyphs to regular characters manually, or use a prebuilt list like I did.
After decoding fully, you get the flag.
You are given a link to a (incredibly ugly) website where you can create accounts and upload files. However, if you try a common name like
test for a file, it says the file already exists! This means all files are stored in the same place. Going a step further, the files may be stored in the same place as the rest of the website. Trying to access
files/index.py (it can be determined it is Flask from the 404 page) gives a special message, so there are protections against reading it, but it is confirmed it is reading from the root directory of the website. Through the hint or just knowledge of common web vulnerabilities, one decides to try to access
files/.git, and, luckily enough, it says the directory exists.
However, git can not be downloaded the normal way since there is no directory listing. For this, you can either manually reconstruct git from known files or use a pre-made script to do that. Once you have .git, you can checkout the files and see the source of the website.
Looking at index.py, you see a “beta feature” that uses getattr to get information about a user. The
user class has two attributes:
__password. Accessing username works just fine, but the password does not! Why could this be? This is the fault of name-mangling. If you instead access
_user__password for admin, you get the flag.
There were also a few unintended solutions involving accessing various files.
The Best Website
You are provided with a seemingly useless website. Upon further inspection, it is a legitimately useless website. However, in the source of index.html you see a comment directing developers to record their changes in
log.txt, you see that a super secret flag was added to the database, and there is a timestamp. This will be important later.
Continuing your inspection of the website, you see it makes a network request to
/boxes?ids=<id1>,<id2>,<id3>. From either the hint or previous knowledge, you can determine that these are MongoDB object ids. Googling what makes up a MongoDB object id, you find how it is made. The machine and process ID are shared, the counter can just be incremented by one, and the timestamp can be gotten through this useful website (be careful of time zones though).
After reconstructing the object id, substituting it for one of the current ids gives the flag.