Natas Level 15 → Level 16

The page contain a username for you to check if the user exist. Looking at the source code, we can see there is a very similar attack to use from our sql injection from previous level


CREATE TABLE `users` ( 
  `username` varchar(64) DEFAULT NULL, 
  `password` varchar(64) DEFAULT NULL 

if(array_key_exists("username", $_REQUEST)) { 
    $link = mysql_connect('localhost', 'natas15', '<censored>'); 
    mysql_select_db('natas15', $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>"; 

} else { 

Notice that this time, it only check for the username and return only two response, either the user exists or not. However, from our last sql injection, we can see that this code is still not sanitizing the double quote which mean we can input what in the first line below into the user input form to include the criteria for password (see the previous level) and create query like the second line

X" and password = "X
SELECT * from users where username = "X" and password = "X"
However, the response is only the user exist or not. Therefore, we need to find the username and then find out what the password. From our previous levels, we know this time we are looking for user natas16 password. If we just try that username, the user exist! Next, if you remember, all of the password for each level are 32 characters. One way to find out if this is true is to use the sql LIKE and wildcard to check the user still exist if we put the following input.
natas16" and password like "________________________________
Indeed, we put 32 “_” characters and the user still exist but not with 33 because “_” is a wildcard for a single character. Now, instead of putting 32 “_”, we put a% at the end where % is wildcard for any number of any character, we can check to see if the first character start with a. If you try this up to w, it will produce the user exist response but W also works. The reason is that upper and lower case are not distinguish. Therefore, after “like”, we put “binary” before W%” to make sure this is case sensitive. Obviously, doing this 32 times is a bit too much. So I got a python script to do exactly that. After we run our program for a while, the next password is shown at the end.

Beside using like, regexp is also possible to use in sql. However, the wildcard characters are different. Finally, Burp, the tool that we have been using to intercept our traffic has a function call Intruder where you can set your payload to brute forcer and do exactly the python script does for each characters.

Additional resources: