A security researcher has developed an exploit that leverages several vulnerabilities in CUPS (common UNIX printing system), the default printing system on most Linux systems. The exploit chain allows attackers to remotely register a rogue printer device on the system and then execute commands as root if the user directs a printing job to it.
Simone Margaritelli, a security researcher and creator of the bettercap open-source network reconnaissance tool, published details about the vulnerabilities on his blog despite not all of them being patched after his report and proof-of-concept exploit was somehow leaked during the disclosure process and appeared on a cybercrime forum.
Margaritelli also expressed frustration with the disclosure process which, according to him, involved 22 days of back and forth trying to convince the CUPS developers that the problems pose a serious security threat and are worth fixing.
Automated printer discovery over the internet
Margaritelli started his investigation when he installed a fresh copy of Ubuntu Linux 24.04.1 LTS on a new laptop and looked at the open ports. He noticed that a service was listening on all network interfaces on UDP port 631 and wondered what it was.
He quickly tracked it down to a service called cups-browsed, which he suspected was related to the printing service based on the name. It turns out cups-browsed is the component responsible for discovering new printers on a network and automatically adding them to the system.
“I had no idea Linux just added anything found on a network before the user can even accept or be notified,” Margaritelli said. “The more you know!”
The problem is that since this service binds to 0.0.0.0, which on Linux indicates all IP addresses and interfaces, it also discovers printers over the internet if the port is not blocked in the system firewall. How big is this problem? Margaritelli scanned the internet for a couple of weeks for devices that listened on UDP 631 and found hundreds of thousands with peaks of 200-300K concurrent devices.
While there are likely hundreds of millions of Linux devices on the internet, that number might not seem high, but it’s certainly big enough for a very powerful botnet if they were to be compromised. Also, as attackers have proven time and time ago, getting a foothold inside a network is not that hard, and from there this issue can potentially be exploited for lateral movement.
“Well it turns out that while you could configure who can and who can’t connect by editing the /etc/cups/cups-browsed.conf configuration file… the default configuration file, on pretty much any system, is entirely commented out and simply allows anyone,” the researcher said.
A buffer overflow and an arbitrary file write
The ability to send packets to an open port is not a security issue in itself. It’s just a vector of attack if there is actually a way to exploit a vulnerability in that service. Margaritelli investigated how cups-browsed parses the UDP packets it receives, which have the format HEX_NUMBER HEX_NUMBER TEXT_DATA.
It wasn’t long until he found a function called found_cups_printer that parsed two text fields from the data, so he fired up a fuzz tester — a program used to try and locate exploitable crashes by feeding random inputs — and it wasn’t long until he found five inputs that seemed to trigger a buffer overflow and another race condition.
“Both these issues have been reported and thoroughly documented, to the devs and the CERT, but nobody seemed to give a damn,” the researcher said. “I can tell you that there’re other, more easily exploitable code paths going on, not just in the discovery mechanism – also reported and ignored. To this day they have not been acknowledged or patched. Happy hunting.”
Going further, the researcher looked at what the text values are expected to be and one of them is a URL of the type http://<IP>:<PORT>/printers/whatever. It’s essentially a way for a remote server to tell the service where its printers are located and the service will connect to this URL to obtain more information.
The communication is done over HTPP using the internet printing protocol (IPP) and the first request is looking for the printer attributes: name, make, model, location, status, etc. The system will then automatically add that printer without any user notification and will pass the attributes to a component called libppd which will save them to a temporary file with the PPD (postscript printer description) extension.
“We finally get to libppd, where the ppdCreatePPDFromIPP2 API is used to save some of those attacker-controlled text attributes to a file with a very specific, line-oriented syntax, without any sanitization whatsoever,” the researcher said.
So, until this step we have a way for an attacker to remotely register a printer on a system with attributes they control which will get saved as values into a file.
Command execution for legacy support
The PPD file defines a printer’s capabilities and functions as a driver which means it can also include commands that will be executed during print jobs. One of those is a directive called cupsFilter2 which can be used to load one of CUPS’ built-in filter binaries that are used to perform document conversion if the printer doesn’t support a specific format.
One of the filters included in CUPS is called foomatic-rip and serves as a universal print filter/RIP wrapper and supports a directive named FoomaticRIPCommandLine which can execute any shell command, and since the CUPS service runs as root, this provides a path to command execution.
The security implications of foomatic-rip and FoomaticRIPCommandLine have been known for at least a decade and have played a part in other vulnerabilities such as CVE-2011-2964 and CVE-2011-2697 and the more recent CVE-2024-35235.
So why has this functionality not been removed? According to Margaritelli, the developers told him that it’s very hard to limit what can be done through Foomatic without breaking existing printer drivers and losing support for hundreds of older printer models from before 2010 that can only be supported through this filter.
This completes the attack chain: force the machine to connect back to the attacker-controlled IPP server, return IPP attributes that inject malicious PPD directives calling FoomaticRIPCommandLine to execute arbitrary commands and then wait for the user to send a print job to the fake printer.
Since the FoomaticRIPCommandLine directive will only execute when a print job is initiated, this is the only limiting factor that requires user interaction. However, it’s not unlikely that someone who suddenly notices a new printer registered on their machine to try to print something to it just to see what happens or where it gets printed.
Mitigation
Margaritelli recommends disabling or removing the cups-browsed service entirely if not needed and blocking access to UDP port 631. However, he notes that it’s also possible to spoof zeroconf, mDNS and DNS-SD as attack paths instead of relying on port 631 using methods that will be disclosed at a later time.
CUPS is not only used on Linux-based systems but on BSD and Solaris too. Security patches should be installed when and if they become available for your system. The currently disclosed vulnerabilities — others are still in the disclosure process — are tracked as follows:
CVE-2024-47176 in 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.
CVE-2024-47076 in libcupsfilters <= 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.
CVE-2024-47175 in 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.
CVE-2024-47177 in cups-filters <= 2.0.1 foomatic-rip allows arbitrary command execution via the FoomaticRIPCommandLine PPD parameter.