OverTheWire Natas Level 25 Walkthrough
Only 10 levels left of Natas from OverTheWire! This level was a fun challenge, involving two different vulnerabilities to get the flag.
This blog post is a walkthrough of source code analysis, and step-by-step instructions for each of the two checks.
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 25 flag found in level 24 to begin this walkthrough. As before, make sure you keep notes and write down the passwords as you find them!
Level 25 ➔ 26
Rather than a continuation of the password challenges, level 25 goes in a different direction. Open up http://natas25.natas.labs.overthewire.org/
(username natas25
and password GHF6X7YwACaYYssHVY05cFq83hRktl4c
from the previous level):

If we change the language in the dropdown, a different text is displayed. And we see that the lang
parameter in the URL is updated to http://natas25.natas.labs.overthewire.org/?lang=de
.
Source code analysis
We’re given the source code, so let’s check that out next. When the page loads, each file in the languages/
directory is iterated through, and echoed as an option. For us, this means en
and de
for English and German, respectively.

Then the session is started, setLanguage()
is called, then the appropriate greeting, message, and footer values are displayed. The listFiles()
function will get all the files in the given directory. So if the directory is language/en
, it will return the file in that directory, which is what was displayed to us when we opened up the web app.
setLanguage()
The setLanguage()
function gets the language out of the request (lang
) and checks it against the safeinclude()
function. If no language is requested, it defaults to English.

The safeinclude()
function looks like this:

First, it prevents (or tries to prevent) directory traversal attacks with this section:
if(strstr($filename,"../")){
logRequest("Directory traversal attempt! fixing request.");
$filename=str_replace("../","",$filename);
}
This is meant to prevent someone from inputting ../../../../etc/passwd
, for example, to access files outside of the webserver directory.
The safeinclude()
function also prevents natas_webpass
from being included in the request.
if(strstr($filename,"natas_webpass")){
logRequest("Illegal file access detected! Aborting!");
exit(-1);
}
That means we can’t access /etc/natas_webpass/natas26
directly, which is where the password (probably) is. This assumption is based on previous levels, where the password was stored in /etc/natas_webpass/natasXX
, where XX
is the next level.
In the two checks above, the inclusion of ../
results in logging, whereas natas_webpass
aborts the request entirely.
Logging
The last part of the source code that we haven’t covered yet is the logRequest()
function, which is called when we violate one of the checks that we just covered.

This function will create a date()
object, get the HTTP user agent from our request, the message generated by the safeinclude()
check, and then write all of that to a log file available at /var/www/natas/natas25/logs/natas25_oursessionIDhere.log
.
Bypassing the ../ check
We have to bypass two restrictions. First is the ../
check. Later, we’ll need a way to access the /etc/natas_webpass/natas26
location.
Looking again at the source code, the webserver checks for the existence of ../
in the request, and then replaces it if it is found.

After searching for a bypass, I found this writeup. The important part is this:
Even if thestr_replace('../', '', $lang)
instruction is used, the path traversal vulnerability is still present and can be abused using....//
instead of../
.
In other words, if we have an input that includes:
....//
The code will find ../
within that string, and remove it. This leaves us with:
../
Which is exactly what we wanted in the first place.
Let’s see if this works by requesting http://natas25.natas.labs.overthewire.org/?lang=....//
. As you can see, we get an error message because no files are found.

To make sure we’re on the right path, let’s add another layer of ....//
and see if the warning goes up a directory (i.e. from Warning: include(/var/www/natas/natas25/language
): to Warning: include(/var/www/natas/)
):

It does!
Navigating to /etc/
Now that we’ve got a proof of concept working, let’s expand it and see if we can read in a valid file from another location, like /etc/passwd
at http://natas25.natas.labs.overthewire.org/?lang=....//....//....//....//....//etc/passwd
.

As it turns out, this step was unnecessary, but still fun. 🙂
Bypassing the natas_webpass check
Next, we need to get around the other check to view the flag. I searched for different ways to bypass this, including base64-encoding the included lang
request. But I didn’t have any luck.
Now’s the time to revisit the logging functionality:

We don’t have control over any of these variables in a useful way, other than the HTTP User Agent
. Let’s see what our logging file looks like so far by using our path traversal trick:

This screenshot is from visiting http://natas25.natas.labs.overthewire.org/?lang=....//....//....//....//....//var/www/natas/natas25/logs/natas25_28kiqm52cu4jsgeea6chdtb8g5.log
where 28kiqm52cu4jsgeea6chdtb8g5
was my PHPSESSID
. You can see that the user agent is recorded, along with PHP output and errors.
Using Burp Suite, I repeated this request, right-clicked it, and sent it to the Repeater functionality. There, I changed the User Agent from my Firefox user agent to the following PHP code:
<?php echo shell_exec("cat /etc/natas_webpass/natas26"); ?>

In other words, we’ve used command injection in the HTTP user agent header to print sensitive data into the log file, which we have access to, via a directory traversal bug.

Natas Level 25 Solution
The code is shown in the request above, but to summarize:
- Use
....//
to bypass the directory traversal check and view the log file that corresponds to yourPHPSESSID
. - Use Burp Suite to modify this request and set the HTTP user agent header to valid PHP code that prints up the flag.
- Send the request, which will inject your command into the log file, then show you the updated log file.

And there’s our flag: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T
.
Takeaway: look for areas where your inputs can be injected as code, and string together vulnerabilities to get the flag.