Snoopy HTB
Snoopy HTB Box Overview Snoopy is a hard-difficulty Linux machine that combines web exploitation, network enumeration, credential theft, and multiple privilege escalation techniques. The attack begins by abusing a misconfigured DNS server that allows a zone transfer, revealing several internal subdomains. Further web enumeration uncovers a Local File Inclusion (LFI) vulnerability that can be leveraged to read arbitrary files from the server. Using the LFI, sensitive configuration files are extracted, exposing mail server credentials and enabling an SSH Man-in-the-Middle (SSH-MITM) attack to capture valid user credentials. After gaining an initial shell, a vulnerable sudo configuration combined with CVE-2023-23946 allows privilege escalation to another user by abusing Git's symlink handling to inject an SSH public key. Finally, another sudo misconfiguration involving ClamAV is exploited through CVE-2023-20052, allowing an XXE attack against the DMG parser to leak the root user's private SSH key, resulting in full system compromise. Attack Summary The attack began with a DNS zone transfer, which disclosed several internal subdomains and significantly expanded the attack surface. During web enumeration, a Local File Inclusion (LFI) vulnerability was identified in the file download functionality. By abusing this vulnerability, arbitrary files could be read from the server, eventually exposing sensitive configuration files containing mail server credentials. With valid mail credentials in hand, an SSH Man-in-the-Middle (SSH-MITM) attack was performed to capture the SSH password of the cbrown user. Using these credentials, an initial shell was obtained on the target system. Post-exploitation enumeration revealed that cbrown could execute git apply as the sbrown user via sudo. Since the installed Git version was vulnerable to CVE-2023-23946, a malicious patch and symbolic link were used to write an attacker-controlled SSH public key into sbrown's authorized_keys file, providing passwordless SSH access as sbrown. Further enumeration showed that sbrown could execute ClamAV as root. The installed version was vulnerable to CVE-2023-20052, an XXE vulnerability in the DMG parser. A specially crafted DMG file was generated and scanned with clamscan --debug, causing ClamAV to disclose the contents of /root/.ssh/id_rsa. Using the leaked private SSH key, a direct SSH connection as the root user was established, completing the compromise of the machine. Enumeration Nmap Scanning As always, I started by performing a full Nmap scan against the target to identify the exposed services and understand the available attack surface. Nmap Scan Analysis The scan reveals only three exposed services: 22 → SSH 53 → DNS (BIND) 80 → HTTP (Nginx) With DNS publicly accessible, it immediately became one of the more interesting services to investigate since misconfigured DNS servers often expose additional information such as internal hostnames or even entire DNS zones. Before diving into DNS though, I started by taking a look at the web application running on port 80. Port 80 Enumeration Browsing to the website presents a simple landing page. Screenshot 2026-07-09 at 01-02-02 While exploring the page, hovering over the Release Package link revealed that it redirects to the hostname: Since this virtual host isn't resolvable locally, it needs to be added to /etc/hosts. With the hostname configured, I moved on to enumerate the exposed DNS service. DNS Enumeration The first step was performing a normal DNS lookup. The zone transfer succeeds and reveals several additional hostnames: mattermost.snoopy.htb mm.snoopy.htb postgres.snoopy.htb provisions.snoopy.htb These are all useful enumeration targets, so add them to /etc/hosts. Further Web Enumeration Returning to the website, I continued browsing each section looking for additional information. The homepage contains a link to download a Press Package archive. Screenshot 2026-07-09 at 01-20-26 Clicking on Announcements downloads the exact same archive. Screenshot 2026-07-09 at 01-21-37 The Team page exposes several employee names that could become useful later for username enumeration or password attacks. The Contact page provides another small but useful clue. Screenshot 2026-07-09 at 01-22-14 A notification mentions that the organization's mail server is currently offline, revealing another hostname: Although the service isn't currently available, it's still worth adding the hostname to /etc/hosts. Discovering the LFI The download functionality immediately stood out because it retrieves files based on a user-supplied parameter. The normal request looks like this: Whenever an application accepts filenames directly from user input, it's always worth checking for a Local File Inclusion (LFI) vulnerability. The first attempt uses the classic directory traversal payload. Screenshot 2026-07-09 at 01-26-58 The request is blocked, indicating that the application filters the standard ../ traversal sequence. A common bypass for weak filters is replacing each ../ with ....//, so I tried the following payload instead. Screenshot 2026-07-09 at 01-28-31 Success. Instead of returning the requested file directly, the application packages it inside a ZIP archive before sending it back to the client. To make extraction easier, I downloaded the response using curl. Extracting the archive reveals the requested file. Reading the extracted passwd file confirms that the traversal vulnerability is working as expected. This confirms an arbitrary file disclosure vulnerability through path traversal. Automating the LFI Since manually crafting traversal payloads and extracting ZIP archives for every request would quickly become tedious, I wrote a small Python script to automate the entire process. The script sends the request, extracts the returned ZIP archive directly in memory, and prints the contents of the requested file. Save the script as lfi.py. To verify everything is working correctly, retrieve a simple file such as /etc/hostname. Perfect. The script works exactly as intended and will make the rest of the enumeration much faster. Mattermost Enumeration Earlier during the DNS zone transfer, one of the discovered subdomains was mm.snoopy.htb. After adding all the discovered hostnames to /etc/hosts, I started browsing each one individually. image Most of the subdomains simply redirected back to the main website. However, mm.snoopy.htb was different—it hosted a Mattermost instance with a login page. One feature that immediately stood out was the Forgot Password functionality. image Earlier, the Team page on the website exposed several employee usernames, making this functionality worth investigating. Submitting a valid username results in the following response: Failed to send password reset email successfully. image However, submitting a random username does not produce the same message. image This difference confirms that the application is performing username enumeration, allowing us to distinguish between valid and invalid accounts. During the initial web enumeration, another interesting hostname was discovered: Unfortunately, the mail server was offline, preventing us from receiving any password reset emails. Since we already have an arbitrary file read vulnerability through the LFI, the next objective is to determine whether we can manipulate the DNS configuration and redirect mail.snoopy.htb to our own machine. Abusing BIND Dynamic DNS Updates The Nmap scan revealed that the DNS service is running BIND. Configuration files for BIND are commonly stored under /etc/bind, making them excellent targets for our LFI. Searching online confirms that the primary configuration file is: Reading it using the lfi.py script reveals the following configuration: This is exactly what we were hoping to find. The configuration contains the RNDC key, which is used to authenticate dynamic DNS updates. If the server accepts updates using this key, we can modify DNS records without needing administrative access. The recovered key is: Before attempting any updates, it's useful to inspect the local DNS configuration. This configuration tells us two important things: Dynamic DNS updates are allowed when authenticated using the rndc-key. Zone transfers are restricted to the 10.0.0.0/8 network, which explains why we cannot retrieve the modified zone externally. Since we possess the authentication key, we can now update DNS records ourselves. First, create a file named key containing the recovered key. Now use the nsupdate utility to change the mail.snoopy.htb record so that it points to our attacker machine. In other words, we've hijacked the mail.snoopy.htb DNS record so that any future email destined for that hostname will instead be delivered to our machine. To verify that the update was successful: Success! We now have the password reset link. However, directly opening the URL results in an error. Screenshot 2026-07-10 at 01-06-36 The issue is that the email uses quoted-printable encoding, where characters such as = are inserted into long lines. Opening the email inside CyberChef and using the Magic recipe automatically decodes the content. Screenshot 2026-07-10 at 01-08-27 The decoded URL becomes: Visiting this decoded URL loads the password reset page successfully. Screenshot 2026-07-10 at 01-10-16 After choosing a new password, log in using the compromised account. Authentication succeeds. Screenshot 2026-07-10 at 01-11-50 Browsing through the chats reveals several internal conversations. One discussion mentions that the team is currently deploying a ClamAV solution. Provisioning Request Abuse While exploring the available Mattermost slash commands, one command immediately stood out. Screenshot 2026-07-10 at 01-15-20 A provisioning form allows employees to request new servers. Opening the form presents several fields that need to be completed. Screenshot 2026-07-10 at 01-16-08 To understand how the provisioning process works, I submitted a request using my own attacker IP address. Screenshot 2026-07-10 at 01-17-34 Only Linux templates were available, so I selected the Linux SSH (TCP/2222) option. Shortly after submitting the request, I received a direct message from cbrown. Screenshot 2026-07-10 at 01-20-01 The message stated that they were unable to connect to the supplied server. That immediately suggested that someone from the infrastructure team was attempting to SSH to the address I had provided. If that's true, instead of running a normal SSH server, we can place an SSH-MITM proxy in front of the connection and capture any credentials that are entered. Start the SSH-MITM server. With the proxy running, submit another provisioning request. A few moments later, another message arrives from cbrown. Screenshot 2026-07-10 at 01-34-42 This time, checking the SSH-MITM server reveals exactly what we were hoping for. Screenshot 2026-07-10 at 01-34-16 The SSH proxy successfully captures valid credentials: With valid SSH credentials in hand, we can now move on to gaining an interactive shell on the target. Initial Shell as cbrown Using the credentials captured from the SSH-MITM attack, I attempted to log in to the target over SSH. Success! We now have our initial shell as the cbrown user. Enumerating Sudo Permissions One of the first things I always check after obtaining a shell is the user's sudo privileges. This is very interesting. The user cbrown is allowed to execute: as the user sbrown. Although this appears to be a very restricted sudo rule, vulnerable versions of Git are affected by CVE-2023-23946, which allows a specially crafted patch to write files outside the repository through symlink manipulation. Before proceeding, I verified the installed Git version. Version 2.34.1 falls within the vulnerable range, making this attack possible. I found a public proof-of-concept for the vulnerability: Understanding the Vulnerability Normally, git apply is designed to apply patches only inside the curre