HomeThe Stash

Lab 06 — Natas 6 to 10: LFI, decoding, and command injection

LabSeptember 17, 2026

IntermediateTime ~50 minTarget OverTheWire NatasLevels 6 → 10Needs a browser

0 / 5 steps

The goal

Natas 0 to 5 taught you to look. Natas 6 to 10 teaches you to reach in — pulling out a file the page only meant to include, walking the server's filesystem through a URL, unwinding a stack of encodings, and getting a search box to run commands it was never meant to run. Five levels, browser only, and this is where web security stops being about what a page shows you and starts being about what it will do if you ask the wrong way.

No passwords here, by their rules and mine. OverTheWire ask content creators not to publish game credentials, and Natas rotates them anyway. You get the technique for each level; you find the password yourself, which is the only way any of it sticks. Everything below happens only on OverTheWire's own Natas server, which they built for exactly this — it starts at overthewire.org.

Where you are picking up. This continues straight from Natas 0–5. You log in at http://natasN.natas.labs.overthewire.org, the username for a level is always natasN, and each password is what you pulled out of the level before. Keep your notes file open. Developer tools (F12) and “View Source” are still the two things you reach for first on every level.

One idea runs through all five. The server trusts something the visitor controls — a form value, a filename in the URL, the text you type into a box — and hands it more power than it should. Naming that trust each time is the whole skill; the specific commands are just how you exercise it.

Steps

06The include the page didn't mean to show you

Level 6 gives you a form asking for a secret and nothing else. The secret is not on the page — but the code that checks it is, if you read the source, and it tells you exactly where the secret lives.

View the source. You are looking for a PHP include line that pulls in a file from somewhere under the site — something shaped like includes/secret.inc. The page runs that file server-side to get the secret it compares against. But nothing stops you asking the web server for that same file directly — put the include's path in your address bar, on the same host:

http://natas6.natas.labs.overthewire.org/includes/secret.inc

If the file has no PHP inside it — just a value — the server sends it back as plain text and the secret is right there. Put that secret in the form, submit, and it hands you the level 7 password.

Why this matters. An include is server-side glue, but the files it points at usually sit in the public web root beside everything else. Anything reachable by a URL is reachable by anyone with that URL, PHP or not. Real credentials leak this exact way — a config or .inc file that was only ever meant to be included, sitting one guessed path away from the open internet.

07Walking out of the folder: local file inclusion

Level 7 is a little site with a Home and an About link. Click between them and watch the address bar: the page loads through a parameter like index.php?page=home. The server is taking that value and using it as a filename to include. It does not check what you put there.

Read the source too — there is a comment telling you where the next password is kept on disk. On this server that path is /etc/natas_webpass/natas8. If the page will include any file you name, name that one. Swap the page value in the URL for a path to the password file instead:

index.php?page=/etc/natas_webpass/natas8

An absolute path starting at / often works straight away here. If a level ever strips the leading slash, the ../../../../ climb does the same job — each ../ is one folder up, and a few too many are harmless because you cannot go higher than root.

Why this matters. This is local file inclusion, and it is one of the highest-value bugs on the web. A parameter that becomes a filename, with no check that it stays inside the intended folder, lets a visitor read anything the web server can — source code, config, password hashes, keys. The fix is never a blocklist of bad strings; it is refusing to build a path out of user input at all.

08Unwinding a stack of encodings

Level 8 shows you its whole hand. The source holds the secret already, but stored through a chain of reversible steps, and it prints the code that built it. Your job is to read that chain and run it backwards — the same “identify the transform, then reverse it” move from the Bandit compression lab, now in a web page.

The secret is typically encoded three ways, stacked: the raw text is base64-encoded, that is turned into hexadecimal, and the whole string is then reversed end to end. To undo it you apply the inverses in the opposite order: reverse the string, decode the hex back to text, then base64-decode. Read the source to confirm the exact order — do not assume mine, confirm theirs. Then run it on your own machine:

$ echo 'ENCODED' | rev | xxd -r -p | base64 -d

Paste the encoded value from the source in place of ENCODED. rev flips the characters, xxd -r -p turns the hex pairs back into bytes, and base64 -d finishes it. If the order in the source differs, reorder these three — each one is its own inverse or has a plain decode flag.

Why this matters. Encoding is not encryption, no matter how many layers you stack. base64, hex and a reversal are all public, keyless and reversible by anyone who can read them — and here the server literally publishes the recipe. When you find a “secret” that was only ever encoded, treat it as plaintext with extra steps.

09When a search box runs shell commands

Level 9 is a keyword search over a word list. Read the source and you will see it building a shell command — something like grep -i <your input> dictionary.txt — and running it, dropping whatever you typed straight into that command line with no cleaning at all.

That is command injection. Because your text becomes part of a real shell command, a ; ends the grep and starts a second command of your choosing, and a trailing # comments out the rest of the original line so it does not break. Type this into the search box on the page — not a terminal:

; cat /etc/natas_webpass/natas10 #

The search page prints the output of whatever ran, so the level 10 password comes back on the page. Mind the spaces exactly as shown.

Why this matters. Passing user input into a shell is one of the oldest and most dangerous mistakes in web software — it hands a stranger the ability to run commands as your server. The lesson underneath the trick is that data should never be able to become a command. Real fixes pass arguments to programs directly, never by pasting them into a shell string.

10The same bug, now with a filter

Level 10 is the search box again — but this time the source shows a filter that rejects your input if it contains ;, | or &. The step-4 trick of starting a second command is dead. So do not start a second command. Turn the first one against itself.

The command is still grep -i <your input> dictionary.txt. Whatever you type sits between the pattern and the file grep searches. If you supply a pattern that matches anything plus a second filename, grep happily searches both files — and one of them can be the password file. Into the search box, a match-anything pattern followed by a second file for grep to read:

.* /etc/natas_webpass/natas11

The .* matches every line, so grep prints the whole of each file it is given — including the password file you appended. No banned character anywhere in that input, so the filter waves it through.

Why this matters. A character blocklist feels like a fix and almost never is. Here the dangerous thing was never the ; — it was that untrusted input reached a command with real power at all. Block the obvious metacharacters and an attacker just uses the command's own legitimate features against you. Filtering symptoms leaves the disease; the cure is keeping user data out of commands entirely.

Lab complete

You pulled a file the page only meant to include, walked the server's filesystem through a URL, unwound a stack of encodings, and turned a search box into a shell — twice, once around a filter. Every one was the same root cause wearing a different coat: the server trusted input it should have treated as hostile. That single sentence is most of application security.

Before you leave — prove it

Without scrolling up: one, why can you read an .inc file the code only ever meant to include? Two, in the level 7 URL, what is the ../ climb actually doing? Three, level 9 and level 10 are the same bug — what changed, and why did the fix fail?

If your third answer is “they filtered characters instead of keeping input out of the command”, you have understood the whole lab.

What you learned

  • Source disclosure — a web-root file is public whether or not it holds PHP
  • Local file inclusion — a parameter that becomes a filename reads anything on disk
  • Directory traversal../ and absolute paths climb out of the intended folder
  • Layered encoding — base64, hex and a reversal are keyless and undo in reverse order
  • Command injection — user input that reaches a shell can become a command
  • Filter bypass — blocking metacharacters fails; use the command's own features

NextMore labs, and the ranges worth your weekend

Go deeper

Original walkthrough. The wargame belongs to the OverTheWire community; this page reproduces none of their level text and none of their passwords, in line with their rules for content creators. Techniques were checked against the live level pages and public references — but Natas changes, so if a step here no longer matches what you see, tell me and I will fix it.