Advanced

OpenPrinting CUPS Remote Code Execution: What You Should Know

This exploit chain in the OpenPrinting CUPS ecosystem combines four separate vulnerabilities — a network-exposure flaw in cups-browsed, unsanitized-attribute flaws in libcupsfilters and l...

Table of Contents

Module 1: The OpenPrinting CUPS Remote Code Execution Exploit Chain

Background: What Is CUPS?

CUPS (Common Unix Printing System) is a collection of tools used to manage printers and print jobs in a standardized way across Unix and Linux systems. It allows a machine to act as a print server: accepting print jobs from clients, processing them, and dispatching them to a physical or virtual printer. Functionally, it plays a role similar to the print spooler service on Windows.

Because print-related packages from the OpenPrinting/CUPS ecosystem ship installed by default on many Linux distributions — Debian being a particularly well-known example — a vulnerability in these components has broad reach across the Linux server and desktop landscape, even though CUPS is not tied to any single distribution.

Disclosure Overview

On September 26th, a security researcher operating under the handle @evilsocket (Simone Margaritelli) published a blog post describing a set of vulnerabilities in the Common Unix Printing System. Under specific conditions, these vulnerabilities can be chained together to achieve arbitrary remote code execution, with the initial network exposure occurring over UDP port 631.

Key characteristics of the disclosure:

  • The exploit chain can only be triggered if the victim system starts a print job — at the time of disclosure, that print job had to be initiated by a user (no known way to force it remotely).
  • Chatter in security forums at the time suggested further vulnerabilities might be disclosed that could remove the need for user interaction.
  • Research at the time of disclosure estimated several hundred thousand vulnerable, internet-facing machines with the affected UDP port exposed.
mindmap
  root((CUPS Exploit Chain Disclosure))
    Researcher
      evilsocket / Simone Margaritelli
      Published Sept 26
    Scope
      Several hundred thousand internet-facing machines
      UDP port 631 exposed
    Constraint
      Requires victim to print a job
      No remote-trigger known at disclosure time
    Outlook
      More disclosures rumored
      Possible removal of user-interaction requirement

The Four Vulnerabilities in the Exploit Chain

The exploit chain is made up of four distinct vulnerabilities spread across four different components of the CUPS/OpenPrinting ecosystem. Each one plays a specific role in enabling the next stage of the attack.

#ComponentRole of the ComponentNature of the Flaw
1cups-browsed (helper daemon)Discovers and browses network printers for CUPSCauses the CUPS print service to bind to 0.0.0.0 instead of localhost, exposing it to remote hosts and letting a remote attacker register an attacker-controlled printer
2libcupsfiltersLibrary providing filter and API functions for printer applications/driversFails to properly validate/sanitize printer attributes supplied by an untrusted (remote) source
3libppdLibrary providing functions/APIs for handling PostScript Printer Description (PPD) files, which describe a printer’s capabilitiesAllows an attacker to write malicious printer attributes into a temporary PPD file
4cups-filtersCollection of filters and back-ends letting CUPS 2.x run on non-Mac systemsContains the actual code-injection vulnerability, allowing arbitrary code execution when the malicious printer is used

The vulnerabilities effectively cascade: the first flaw exposes the service to the network, the second and third let an attacker smuggle malicious data into a file CUPS trusts, and the fourth turns that trusted file into a code-execution primitive.

flowchart TD
    A["cups-browsed flaw:\nservice binds to 0.0.0.0"] --> B["Remote attacker can register\na malicious printer"]
    B --> C["libcupsfilters flaw:\nmalicious printer attributes accepted\nwithout sanitization"]
    C --> D["libppd flaw:\nmalicious attributes written\ninto a temporary PPD file"]
    D --> E["cups-filters flaw:\ncode injection when the\nmalicious printer is used"]
    E --> F["Arbitrary remote code execution\non the victim host"]

Affected Packages and Versions

Because these are package-level vulnerabilities rather than distribution-specific ones, exposure depends on which package versions are installed rather than which Linux distribution is in use.

PackageVulnerable Versions
cups-browsedUp to and including 2.01
cups-filtersUp to and including 2.01
libcupsfiltersUp to and including 2.1b1
libppdUp to and including 2.1b1

Step-by-Step Exploitation Flow

Because this is an exploit chain rather than a single-shot vulnerability, an attacker needs to walk through several steps to reach code execution:

  1. Network exposure. The cups-browsed flaw causes the CUPS print service to listen on all network interfaces instead of only locally, making it reachable over UDP port 631.
  2. Malicious printer announcement. The attacker sends a UDP packet to port 631 containing a URL pointing to an Internet Printing Protocol (IPP) server under the attacker’s control.
  3. Outbound information gathering. The victim’s CUPS installation makes an outbound HTTP POST request to the attacker-controlled IPP server to gather information about this newly announced printer.
  4. Malicious PPD generation. CUPS uses the (attacker-supplied) information to build a PPD file describing the printer’s capabilities and supported features. Because CUPS reads this PPD configuration data directly from the attacker-controlled IPP server, the attacker can inject arbitrary values into it.
  5. Command injection via FoomaticRIPCommandLine. The FoomaticRIPCommandLine directive is a filter that can be invoked from the command line (or by an application) to execute a print job, using values sourced from the PPD file. Since the PPD content is attacker-controlled, the attacker can specify arbitrary commands through this directive.
  6. Trigger. The final step requires the victim machine to attempt to print something using the malicious printer. This step cannot be triggered remotely by the attacker — but once a real print job is sent to the malicious printer, the PPD file is read and the injected arbitrary command executes.
sequenceDiagram
    participant Attacker
    participant CUPS as Victim CUPS / cups-browsed (UDP 631)
    participant IPP as Attacker-Controlled IPP Server
    participant User as Victim User/App

    Attacker->>CUPS: UDP packet to port 631 with URL to malicious IPP server
    CUPS->>IPP: Outbound HTTP POST to gather "printer" info
    IPP-->>CUPS: Malicious printer attributes / capabilities
    CUPS->>CUPS: Generate PPD file from attacker-controlled data\n(contains malicious FoomaticRIPCommandLine value)
    Note over CUPS: Malicious printer now appears as available
    User->>CUPS: Sends a print job to the malicious printer
    CUPS->>CUPS: Reads PPD file, executes FoomaticRIPCommandLine
    CUPS-->>Attacker: Arbitrary command executes on victim host

The User-Interaction Requirement and Real-World Likelihood

A natural question is: how likely is a victim to print to a malicious printer they didn’t set up? A few points temper that skepticism:

  • Linux is far less common than Windows as a day-to-day desktop OS, but it underpins a large amount of infrastructure — many web applications run on Linux systems, and those applications may themselves need to submit print jobs.
  • A user (or an application acting on a user’s behalf) might select a printer that simply appears as “available” in a print dialog, with no visible indication that it is attacker-controlled.
  • Once that printer is chosen and a print job is sent to it, the exploit chain runs automatically through to code execution.

So while the attack cannot be triggered purely remotely, the requirement is lower-friction than it might initially appear, especially on systems where print jobs are issued programmatically by backend applications rather than by a human consciously picking a printer.

Determining Whether a System Is Vulnerable

Several checks can be performed (commands shown here are for Debian-based systems; the specific tooling will vary by distribution):

  1. Confirm a vulnerable version of cups-browsed is installed (versions 2.01 or lower are vulnerable):
dpkg -l | grep cups-browsed
  1. Confirm the cups-browsed service is actually running. If the service shows as inactive (dead), it is not running and this vector is not active:
systemctl status cups-browsed
  1. Confirm the service is listening on UDP port 631 on all interfaces — this is indicative of the CVE affecting cups-browsed (binding to 0.0.0.0):
netstat -anu | grep 631

Look specifically for a UDP listener bound to 0.0.0.0:631 rather than 127.0.0.1:631.

  1. Check the cups-browsed configuration for the BrowseRemoteProtocols directive. If it contains the value cups, and all of the previous checks are positive, the system is vulnerable to this exploit chain:
grep -i BrowseRemoteProtocols /etc/cups/cups-browsed.conf
flowchart TD
    A[Start assessment] --> B{"cups-browsed version\n<= 2.01 installed?"}
    B -- No --> Z[Not vulnerable via this package]
    B -- Yes --> C{"cups-browsed service\nrunning / enabled?"}
    C -- "inactive (dead)" --> Z
    C -- Running --> D{"Listening on UDP 631\non 0.0.0.0 (all interfaces)?"}
    D -- No / localhost only --> Z
    D -- Yes --> E{"BrowseRemoteProtocols\ncontains 'cups'?"}
    E -- No --> Z
    E -- Yes --> F[System is vulnerable\nto the exploit chain]

Proof-of-Concept Availability

At the time of recording, several proof-of-concept exploits existed publicly:

  • A couple of the early published PoCs contained syntactical errors that were relatively easy to fix but left them non-functional out of the box.
  • A separate tool, CUPSHax, was confirmed to work. Rather than directly querying the cups-browsed service over UDP port 631, it uses DNS-SD printer discovery via broadcast messages. It is reliable, but its downside is that the attacker and the victim must be on the same local network segment for the broadcast-based discovery to work.

Evidence of Scanning and Active Exploitation

At the time of recording, tens of thousands — potentially hundreds of thousands — of internet-facing systems had UDP port 631 exposed, making them potentially vulnerable. However, the requirement that a victim must trigger a print job to the malicious printer significantly limits real-world exploitability.

Security researchers identified a number of IP addresses actively scanning the internet for vulnerable systems. Some of that scanning activity is presumably attributable to security researchers assessing the scale of the problem, but in some observed cases the scanning traffic also included an actual exploitation payload rather than pure reconnaissance.

flowchart LR
    subgraph Exposure
        A["~100k-hundreds of thousands\nof hosts with UDP 631 exposed"]
    end
    subgraph Activity
        B[Internet-wide scanning observed]
        C[Some scans include\nexploitation payloads]
        D[Some scans likely\nresearcher reconnaissance]
    end
    subgraph Limiting Factor
        E["Attack still requires victim\nto print to the malicious printer"]
    end
    A --> B --> C
    B --> D
    C --> E
    D --> E

CVSS Scoring Breakdown

At the time of recording, NIST NVD had not yet completed its own assessment of these CVEs, so the scores discussed were those published by GitHub, an approved CVE Numbering Authority (CNA).

CVEComponentAttack ComplexityUser InteractionConfidentiality/Integrity/Availability ImpactCVSS Score
CVE-2024-47076 (libcupsfilters)libcupsfiltersLowNoneIntegrity impact only (untrusted data flowing into PPD file)8.6
CVE-2024-47175 (libppd)libppdLowNoneIntegrity impact only (untrusted data flowing into PPD file)8.6
CVE-2024-47176 (cups-browsed)cups-browsedHighRequired (victim must send a print job)Confidentiality and availability impacted in addition to integrity8.3
CVE-2024-47177 (cups-filters, command injection)cups-filtersHighNot requiredConfidentiality, integrity, and availability all rated high9.0

Note: the narration itself only explicitly names CVE-2024-47176 for the cups-browsed binding flaw; the other three CVE identifiers above are included as commonly referenced public identifiers for this same disclosure and are provided for reference alongside the CVSS details that were discussed directly.

The first two vulnerabilities (libcupsfilters and libppd) share an identical CVSS vector: low attack complexity, exploitable across the network, with no privileges and no user interaction required — because both stem from a lack of sanitization of untrusted data flowing into the PPD file, both are rated 8.6 with an integrity-only impact.

CVE-2024-47176 (the cups-browsed binding flaw) scores slightly lower on paper due to higher attack complexity and a requirement for user interaction (sending a print job) — but because it also affects confidentiality and availability rather than integrity alone, its score is pulled back up to 8.3.

The final vulnerability — the command-injection flaw in cups-filters — has high attack complexity but does not require user interaction, and impacts confidentiality, integrity, and availability at a high level, giving it the highest individual score of 9.0.

There are various informal guidelines for combining multiple CVSS scores across an exploit chain, but none of them are part of the official CVSS standard — they exist only to help analysts reason about aggregate risk in their own environment, not to produce an authoritative combined score.

xychart-beta
    title "CVSS Scores Across the Exploit Chain"
    x-axis ["libcupsfilters", "libppd", "cups-browsed", "cups-filters (RCE)"]
    y-axis "CVSS Score" 0 --> 10
    bar [8.6, 8.6, 8.3, 9.0]

Remediation and Mitigation

  • Patch. Vendors have begun rolling out fixes for the affected packages. Because the disclosure happened earlier than the researcher had originally planned, some vendors were still catching up at the time of recording. Canonical, for example, published status updates for Ubuntu indicating which packages had been fixed in which releases — other vendors are expected to publish similar tracking pages.
  • Mitigate if a patch isn’t yet available. If an update is not yet available for a given distribution, or it cannot be applied immediately, the recommended mitigation is to stop the cups-browsed service and disable it so it does not restart on reboot:
systemctl stop cups-browsed
systemctl disable cups-browsed
  • General hardening. As a broader security best practice, disable or remove any protocol or service that isn’t actively needed — an exposed, unused service (such as UDP 631 open to the internet) is unnecessary attack surface.
flowchart TD
    A[Is a vendor patch available?] -- Yes --> B[Apply the vendor update\nfor cups-browsed / cups-filters /\nlibcupsfilters / libppd]
    A -- No --> C["systemctl stop cups-browsed\nsystemctl disable cups-browsed"]
    B --> D[Verify service no longer\nbinds to 0.0.0.0:631]
    C --> D
    D --> E[Continue monitoring vendor\nadvisories for follow-up CVEs]
    E --> F[Apply general hardening:\ndisable unused network services/protocols]

Summary

This exploit chain in the OpenPrinting CUPS ecosystem combines four separate vulnerabilities — a network-exposure flaw in cups-browsed, unsanitized-attribute flaws in libcupsfilters and libppd, and a command-injection flaw in cups-filters — into a path to arbitrary remote code execution triggered by a victim printing to an attacker-controlled printer announced over UDP port 631. Hundreds of thousands of internet-facing systems were estimated to have the relevant port exposed at the time of disclosure, and while exploitation is gated on user interaction (sending a print job), scanning activity — including scans carrying live exploitation payloads — was already being observed. CVSS scores across the four component CVEs ranged from 8.3 to 9.0, and while NVD had not finalized its own assessment at the time, GitHub’s CNA-issued scores made clear this was a high-severity issue deserving prompt attention.

Mitigation Checklist

  • Identify all systems with cups-browsed, cups-filters, libcupsfilters, or libppd installed.
  • Check installed package versions against the vulnerable ranges (≤ 2.01 for cups-browsed/cups-filters; ≤ 2.1b1 for libcupsfilters/libppd).
  • Confirm whether cups-browsed is running and, if so, whether it is bound to 0.0.0.0 on UDP port 631.
  • Check the BrowseRemoteProtocols directive in the cups-browsed configuration for a cups value.
  • Apply vendor-provided patches as soon as they are available for your distribution.
  • If a patch is not yet available, stop and disable the cups-browsed service to prevent it from restarting on reboot.
  • Restrict or firewall UDP port 631 from untrusted/internet-facing networks where CUPS network browsing is not required.
  • As a general hardening practice, disable any printing/browsing protocols and services that are not actively in use.
  • Continue monitoring vendor and researcher advisories, since additional related vulnerabilities were anticipated to be disclosed after this initial batch.

Search Terms

openprinting · cups · remote · execution · know · vulnerability · briefings · networking · systems · security · chain · exploit · exploitation · mitigation

More Vulnerability Briefings courses

View all 30

Interested in this course?

Contact us to book it or get a custom training plan for your team.