Internet Printing Protocol
The Internet Printing Protocol (IPP) is the standard application protocol for network printing. The current IPP/1.1 specifications are RFC 8010 (encoding/transport) and RFC 8011 (model/semantics), which obsolete RFCs 2910 and 2911. IPP is carried over HTTP and supports print jobs, printer capability queries, and queue management. IPP-based profiles such as IPP Everywhere also support driverless printing, while PWG extensions reuse the model for additive-manufacturing/3D printers and bind the Cloud Imaging Model so printers can obtain jobs from shared network or cloud services.[7][8][9][10][11]
IPP normally uses TCP/631. UDP/631 is associated with legacy CUPS browsing/cups-browsed discovery rather than the IPP request transport itself. Exposing either surface can create risk on printers and Linux/Unix hosts running CUPS.[3][7]
Quick PoC – crafting raw IPP with Python
import struct
import requests
def attribute(tag, name, value):
name = name.encode()
value = value.encode()
return bytes([tag]) + struct.pack(">H", len(name)) + name + struct.pack(">H", len(value)) + value
printer_uri = "ipp://printer:631/ipp/print"
ipp = struct.pack(">BBHI", 2, 0, 0x000B, 1) # version 2.0, operation, request-id
ipp += b"\x01" # operation-attributes-tag
ipp += attribute(0x47, "attributes-charset", "utf-8")
ipp += attribute(0x48, "attributes-natural-language", "en")
ipp += attribute(0x45, "printer-uri", printer_uri)
ipp += b"\x03" # end-of-attributes
r = requests.post("http://printer:631/ipp/print", headers={"Content-Type": "application/ipp"}, data=ipp)
print(r.status_code, r.content[:40])
Enumeration & Recon
1. Nmap NSE
# run all CUPS/IPP scripts
nmap -sV -p631 --script=cups* <target>
# or only basic info
nmap -p631 --script=cups-info,cups-queue-info <target>
The cups-info script extracts model, state and queue statistics while cups-queue-info enumerates pending jobs.
2. IPP utilities from CUPS
ippfind– multicast/UDP discovery (works against cups-browsed):ippfind --timeout 3 --txt -v "@local and port=631" # list printersipptool– arbitrary requests defined in a .test file:
The bundled get-printer-attributes.test file queries firmware version, supported document formats, etc.ipptool -tv ipp://<IP>/ipp/print get-printer-attributes.test
3. Shodan / Censys dorks
shodan search 'product:"CUPS (IPP)" port:631'
More than 70 000 hosts were publicly exposing CUPS in April 2025.[1]
4. Emulating a rogue IPP printer in the lab
For client-side testing you do not need real hardware: ippeveprinter exposes a minimal IPP Everywhere server, can advertise itself over DNS-SD, optionally require HTTP Basic auth with -A, and can either write rendered jobs to a directory with -D or execute a helper for every printed document with -c.[4]
mkdir -p /tmp/ipp-spool /tmp/ipp-out
# Save rendered jobs into /tmp/ipp-out and listen on TCP/8631
ippeveprinter -v -p 8631 -d /tmp/ipp-spool -D /tmp/ipp-out \
-f application/pdf,image/jpeg,image/pwg-raster "LabPrinter"
# Auth-enabled variant for testing client credential prompts
ippeveprinter -v -A -p 8631 "AuthLabPrinter"
Recent Vulnerabilities (2023-2025)
| Year | CVE ID(s) | Affected component | Impact |
|---|---|---|---|
| 2024 | CVE-2023-50739 | Lexmark firmware (IPP parser) | Heap-overflow → RCE over Wi-Fi/LAN[5] |
| 2024 | CVE-2024-47076, 47175, 47176, 47177 | cups-browsed, libcupsfilters, libppd, cups-filters | Unauthenticated rogue-printer installation leading to command execution when a victim prints[3] |
| 2024 | CVE-2024-35235 | cupsd before the vendor fix | Symlink-assisted permission change that can support local privilege escalation[2] |
| 2023 | CVE-2023-0856 (Canon) + Pwn2Own | Stack-overflow in sides attribute → remote code execution[6] |
cups-browsed RCE chain (September 2024)
The 2024 cups-browsed bug chain is the most practical modern IPP attack path against UNIX endpoints.[3]
cups-browsedlistens on UDP/631 for printer advertisements.- An attacker sends a single spoofed packet pointing to a malicious IPP URL (CVE-2024-47176).
libcupsfiltersautomatically fetches the remote PPD without validation (CVE-2024-47076 & 47175).- A crafted PPD abuses the foomatic-rip filter to execute arbitrary shell commands whenever anything is printed (CVE-2024-47177).
Public PoCs exist, and the attacker can either auto-install a new rogue printer or silently replace an existing printer URI so the payload triggers on the next print job.[3]
On LANs, the same path can be reached by spoofing Zeroconf/mDNS/DNS-SD advertisements instead of attacking a public UDP/631 listener directly, so it is worth pairing this with mDNS/DNS-SD abuse during local network operations.[3]
Execution normally happens when a user prints to the malicious queue, and the resulting code runs in the lp context on default Linux installs.[3]
Temporary mitigations
sudo systemctl stop cups-browsed
sudo systemctl disable cups-browsed
sudo ufw deny 631/udp # or equivalent firewall rule
Update the whole printing stack together — cups-browsed, libcupsfilters/cups-filters, libppd, and CUPS — instead of treating this as a single-package issue.[1][3]
Install the coordinated fixed packages supplied by the target distribution. Do not rely on a single upstream version number because affected components and backported fixes vary by distribution.[1][3]
cupsd symlink Listen misconfiguration (CVE-2024-35235)
Placing a symbolic link in cupsd.conf’s Listen directive can make cupsd (often running as root) change permissions on an attacker-chosen path to world-writable, which is a solid local privilege-escalation primitive when you can influence the configuration or win the bind-time race.[2]
Offensive Techniques
- Rogue printer replacement / auto-install – abuse
cups-browseddiscovery over UDP/631 or spoofed DNS-SD to register a malicious printer or replace a trusted printer URI, then wait for the next print job to reach attacker-controlled IPP metadata.[3] - Unauthenticated raw print job – test whether the printer accepts
POST /ipp/printwithout authorization. Some PostScript-capable devices expose unsafe interpreter extensions, butsystem(...)command execution is device/firmware-specific and is not guaranteed by PostScript or IPP. - Job hijacking – if authorization checks are missing, operations such as
Cancel-JobandSend-Documentmay let an attacker disrupt or replace another user’s job. The operation names alone do not bypass access control.[8] - SNMP → IPP combination – a default SNMP community such as
publicmay reveal the queue or printer URI needed for subsequent IPP testing.
Defensive Best Practices
- Patch CUPS and printer firmware promptly; subscribe to vendor PSIRT feeds.
- Disable
cups-browsedand UDP/631 unless zeroconf printing is required. - Restrict TCP/631 to trusted subnets/VPN and enforce TLS (ipps://).
- Require Kerberos/Negotiate or certificate auth instead of anonymous printing.
- Monitor logs:
/var/log/cups/error_logwithLogLevel debug2can reveal unsolicited PPD downloads or suspicious filter invocations. - In high-security networks, move printing to a hardened, isolated print server that proxies jobs to devices via USB only.
References
- [1] Akamai SIG — Critical Linux RCE Vulnerability in CUPS — What We Know and How to Prepare
- [2] Debian Security Tracker — CVE-2024-35235
- [3] Simone Margaritelli — Attacking UNIX Systems via CUPS, Part I
- [4] ippeveprinter(1) — Linux manual page
- [5] Lexmark Security Advisory - CVE-2023-50739
- [6] ZDI-23-556: Canon imageCLASS MF743Cdw IPP sides Stack-based Buffer Overflow RCE
- [7] RFC 8010 - IPP/1.1 Encoding and Transport
- [8] RFC 8011 - IPP/1.1 Model and Semantics
- [9] OpenPrinting - Driverless Printing
- [10] Printer Working Group - 3D Printing
- [11] PWG 5100.18-2025 - IPP Shared Infrastructure Extensions v1.1