CUPS Network Backends SNMP Supply Injection -> PPD Modification
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
Start with backend/snmp-supplies.c, especially backend_walk_cb and the code that writes marker names to the status stream; trace how scheduler/statbuf.c and job.c classify and retain PPD lines, then inspect printers.c where keywords are written to the queue PPD. Compare the SNMP path with the control character handling in backend/ipp.c added by the cited fix. Done means SNMP supply descriptions cannot inject scheduler status or PPD keywords; add focused coverage for the path.
索引モデルが issue の本文から書いたものです。
説明
CUPS network backends: SNMP supply names reach the scheduler status stream unfiltered - a malicious printer or LAN SNMP spoofer can inject "PPD:" lines and change the
queue PPD (CVE-2026-55453 chain through the SNMP path; not fixed upstream on 2.4.x head; static read only)
Components: cups 2.4.7-1.2ubuntu7.14 (C8b876128848b, 7A34) and cups 2.4.16-1ubuntu1.3 (Ce8ddde6699cf, 7C56): socket and lpd
backends; cups-daemon 2.4.7-1.2ubuntu7.14 (Ccf49f64dc34c) and 2.4.16-1ubuntu1.3 (Cb8d63a2c1dbe): ipp backend and the
scheduler side (statbuf.c, job.c, printers.c). Sources: git-ubuntu applied/2.4.7-1.2ubuntu7.14 and applied/2.4.16-1ubuntu1.3;
upstream OpenPrinting/cups branch 2.4.x head. Copies in raw/level2/explorer-a-cups-bsd-cups-ubuntu/ (*-ubuntu-,
*-2.4.x-head). Line numbers: Ubuntu 2.4.7 / Ubuntu 2.4.16 / 2.4.x head.
Path from SNMP reply to PPD write
-
The backend walks the printer's supply table over SNMPv1 (community "public").
socket.c:273 and :429, lpd.c:945 and :1225, ipp.c:676 and :2199 (2.4.7) call backendSNMPSupplies() ->
backend_init_supplies() (snmp-supplies.c:217 / 218) -> _cupsSNMPWalk(..., backend_walk_cb).
The gate is only snmp-supplies.c:515-521 / 516-522: return if the PPD sets cupsSNMPSupplies to a value other than "true";
if the attribute is absent, polling runs (classic driver and vendor PPDs).
_cupsSNMPWalk (cups/snmp.c) does not compare the reply's request-id or source address with the query (loop reads
_cupsSNMPRead, then checks only the OID prefix and error fields), so a LAN host that answers the backend's UDP port can
supply the values (same weakness that GHSA-g863 and GHSA-5cpc describe). -
The reply string is copied raw. cups/snmp.c asn1_decode_snmp():1040-1046 / 1045-1051 calls
asn1_get_string(&bufptr, bufend, length, (char *)packet->object_value.string.bytes, sizeof(...));
and asn1_get_string():1406-1440 / 1411-1445 is a memcpy plus a NUL. No byte is filtered. -
The supply name keeps control characters. snmp-supplies.c backend_walk_cb(), prtMarkerSuppliesDescription branch,
charset csASCII/csUTF8/csUnicodeASCII (863-867 / 864-868 / 869-873):
strlcpy(supplies[i - 1].name, (char *)packet->object_value.string.bytes, sizeof(supplies[0].name));
The Latin-1, Shift-JIS, UTF-16 and UTF-32 branches convert without filtering too. Only the "unknown charset" default
branch replaces bytes < ' ' with '?'. The charset is the printer's prtLocalizationCharacterSet (snmp-supplies.c:649 / 650). -
The name goes to the backend's stderr status stream. snmp-supplies.c:715-739 / 716-740 / 721-745:
for (name_ptr = supplies[i].name; *name_ptr;)
{
if (*name_ptr == '\' || *name_ptr == '"' || *name_ptr == ''')
{ *ptr++ = '\'; *ptr++ = '\'; *ptr++ = '\'; }
*ptr++ = *name_ptr++;
}
...
fprintf(stderr, "ATTR: marker-names=%s\n", value);
LF (0x0A) and CR pass through, so one supply name can end the ATTR line and start new status lines.
The same names are written to the backend's .snmp cache (snmp-supplies.c:670-680 / 671-681) and read back on later runs
(575-583 / 576-584), so the injection repeats on every job without more attacker traffic while the description matches. -
The scheduler splits backend stderr at each '\n' (scheduler/statbuf.c:123 / 124, strchr(sb->buffer, '\n')) and classifies
a line that starts with "PPD:" as CUPSD_LOG_PPD (statbuf.c:258-261 / 259-262 / head 262). -
job.c update_job(): CUPSD_LOG_PPD (5461-5486 / 5475-5500 / head 5458-5482) runs cupsParseOptions(message, ...) and adds every
keyword except cupsFilter, cupsFilter2, cupsFinishingTemplate, cupsIPPFinishings, cupsIPPReason, cupsMarkerName,
cupsMaxSize, cupsMediaQualifier*, cupsMinSize, cupsPageSizeCategory, cupsPortMonitor, cupsPreFilter, cupsPrintQuality,
APPrinterPreset to job->keywords. FoomaticRIPCommandLine is kept (strcmp in Ubuntu, _cups_strcasecmp on head). -
At job end job.c:3618-3621 / 3631-3634 / head 3646 calls cupsdUpdatePrinterPPD(job->printer, job->num_keywords,
job->keywords), and printers.c:2873 / 2853 / head 2869 writes each one into /etc/cups/ppd/.ppd:
cupsFilePrintf(dst, "*%s: %s\n", keyword->name, keyword->value); -
If the queue uses foomatic-rip, the next job runs the injected FoomaticRIPCommandLine as lp (the GHSA-7hqf-mfhx-7r3v /
CVE-2026-55453 demonstration, which used the ipp backend's marker-message instead of an SNMP supply name).
Example supply name shape (not tested): "x\nPPD: FoomaticRIPCommandLine=cat;/usr/bin/id>/tmp/m;#\nDEBUG: y". The
payload must avoid \ " ' (they are escaped) - the GHSA payload already does (${IFS}).
Why the CVE-2026-55453 fix does not cover it
The fix (2.4.x d41cf0616, master 806e1b483) changes only backend/ipp.c quote_string() (control characters -> space). The
2.4.x head snmp-supplies.c differs from Ubuntu 2.4.16 only in buffer sizes and the marker-levels clamp; head job.c and
printers.c still accept and write the keyword. No OpenPrinting advisory in cups-ghsa.json (41 read by reader-k) describes
this SNMP path.
Preconditions and reach
- A queue on socket://, lpd:// or ipp:// to a printer the attacker controls, or on a LAN where the attacker can answer the
backend's SNMP queries; the PPD does not set *cupsSNMPSupplies: False (IPP Everywhere PPDs set False; classic driver PPDs
do not); a job runs on that queue. Code execution additionally needs a foomatic-rip queue (other PPD keyword changes still
alter the queue).
- 主要言語
- C
- スター
- 1.8k
- フォーク
- 352
- 平均マージ
- 2日 4時間
- マージ済み PR(30日)
- 16
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
OpenPrinting/cups のほかの issue
-
Don't use xgettext sort option (-s) when generating POT file対応中かも @michaelrsweet が 9 日前に担当しました。 オープンinvestigating
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
OpenPrinting/cups#1721 · コメント 4 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
`lp` (and other libcups clients) send `print-color-mode=<default>` alongside `ColorModel=Gray`, defeating the b0f1a00 "Don't override ColorModel" fix対応中かも @michaelrsweet が 3 日前に担当しました。 オープンinvestigating
難易度 4/5 1〜2日 初心者へのやさしさ 55/100
OpenPrinting/cups#1778 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 30/100
OpenPrinting/cups#1726 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
ippeveprinter: collection-valued job attributes are never exported to the command (IPP_MEDIA_COL always empty)対応中かも @michaelrsweet が 26 日前に担当しました。 オープンbug documentation priority-low
OpenPrinting/cups#1725 · コメント 2 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 38/100
OpenPrinting/cups#1707 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
OpenPrinting/cups の issue をすべて見る
似ている issue
-
difficulty: easy
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
-
performance solver
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
ChefKissInc/Inferno#319 ·
-
llvm-tools
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
llvm/llvm-project#235522 ·
メンテナーはふだん 1 日以内に返信