Skip to content
Exploit for Improper Authentication in Openprinting Cups

Exploit for Improper Authentication in Openprinting Cups

Sploitus • September 27, 2026

Local privilege escalation against a root `cupsd`. When coerced into acting as an IPP

**client** toward a rogue local server, cupsd answers a `401 WWW-Authenticate: Local`

challenge by replaying its own admin token. Capturing that token lets an unprivileged user

drive cupsd as admin (root). A persistent `file://` print queue (`printer-is-temporary=false`)

bypasses the FileDevice policy, so a raw `Print-Job` writes attacker bytes to any path as

Two primitives chain into arbitrary root file-write:

1. **Reusable `Local` auth.** cupsd accepts a `Local` authentication backed by a root

certificate under `/run/cups/certs/`. Acting as an IPP client, it *volunteers* that admin

token when challenged with `401 WWW-Authenticate: Local`. Point cupsd at a fake IPP server

you control and you capture a token valid to drive it as root.

2. **FileDevice bypass.** `file://` as a `device-uri` is refused by default. Creating the queue

with `printer-is-temporary=false` persists it and side-steps that guard; a raw `Print-Job`

then writes its bytes straight into the target file, as root.

cupsd (root) rogue server 127.0.0.1:9189

CUPS-Create-Local-Printer |

device-uri=ipp://127.0.0.1:9189/ipp/print |

|----------------------------------->| capture

`` is cupsd's own admin token — replay it against `/admin/` and you are root-equivalent.

1. Cap thread bind 127.0.0.1:9189, answer 401 Local, capture token

2. Coerce CUPS-Create-Local-Printer -> device-uri ipp://127.0.0.1:9189/...

-> cupsd connects out -> 401 -> retry -> [+] Local token

3. Root write CUPS-Add-Modify-Printer device-uri=file:///etc/sudoers.d/-pwn

printer-is-temporary=false (FileDevice bypass) + accept + resume

Print-Job (application/vnd.cups-raw, gzip) = " ALL=(ALL) NOPASSWD: ALL"

4. Verify sudo -n id -> root

(fallback: a root cron job dropped to /etc/cron.d/-pwn copies /etc/shadow

to /tmp/shadow- mode 644; wait ≤90s for cron)

The reference PoC (GHSA-c54j-2vqw-wpwp / *cups2root*, R. de Jager) is a **demo harness**: it

runs as root, spawns its own cupsd and a throwaway `unpriv` user, then `sudo -u unpriv` to

simulate the attacker. Unusable as-is. Changes:

1. **De-harnessed** — no root/spawn scaffolding; targets the **system cupsd already root** on

2. **Real target** — attacker = current user (or `$ATTACKER`); fragment ` ALL=(ALL) NOPASSWD: ALL`.

3. **Raw IPP over sockets** — full rewrite with no `ipptool` / `lpadmin` / `lpinfo` / `cupsctl`

| Status | Versions |

|------------|-----------------------------------------------------|

| Vulnerable | CUPS ≤ 2.4.16 |

| Fixed | CUPS 2.4.17 and later |

| File | Role |

|--------------|---------------------------------------------------------------|

| `exploit.py` | PoC: token leak → file:// queue → raw Print-Job → sudoers root |

| `README.md` | This file |

Python 3 standard library only — no dependencies.

# attacker = current user, cupsd on 127.0.0.1:631

# override the target user (e.g. after landing as anotheruser)

IPP_HOST=127.0.0.1 IPP_PORT=631 CAPTURE_PORT=9189 python3 exploit.py

2. Do not run `cupsd` as root where avoidable; drop privileges / sandbox the service.

3. Restrict the `Local` auth and `file://` device backend; keep FileDevice policy enforced for

4. If printing is not needed: `systemctl disable --now cups cups-browsed` and remove the

* GHSA-c54j-2vqw-wpwp — *cups2root* (R. de Jager, v12-security)

* OpenPrinting CUPS 2.4.17 release notes

This project is for authorized security testing, education, and defensive research only. You are responsible for complying with applicable laws and the rules of engagement of your lab or client.

Extracted Entities