[Security] Heap buffer overflow (OOB read past GPAC sample buffer) in process_avc_sample() at mp4.c:99 when parsing a crafted MP4 file
Maintainer thường phản hồi trong vòng 2 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 74/100
Hướng nghiên cứu
Bắt đầu tại src/lib_ccx/mp4.c, ở process_avc_sample(), quanh các bước kiểm tra độ dài NAL và các lần đọc ở dòng 99-100; trước tiên hãy đọc phần mã xử lý mẫu xung quanh. Tái hiện lỗi bằng tệp MP4 sai định dạng đính kèm với AddressSanitizer, sau đó xác minh rằng các độ dài không hợp lệ bị từ chối trước khi truy cập byte mẫu hoặc gọi do_NAL(). Hoàn tất khi đầu vào sai định dạng kết thúc mà không xảy ra lỗi đọc ngoài phạm vi và một mẫu avc1 hợp lệ vẫn được xử lý bình thường.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
1. Summary
CCExtractor (master commit d7eb132e15f4d1e2c40f4655349596b2b8f708de, version string 0.96.5) performs an out-of-bounds read while parsing a crafted MP4 file. During GPAC-based MP4 processing of an AVC video track, process_avc_sample() (src/lib_ccx/mp4.c) walks the sample bytes NAL by NAL. The bounds check before using the NAL length is computed in 32-bit unsigned arithmetic (mp4.c:82, "i + nal_length <= previous_index || i + nal_length > s->dataLength"), so a nal_length value close to UINT32_MAX wraps around and passes both comparisons while the index i reaches s->dataLength. Line 99 then reads s->data[i] one byte past the end of the GPAC sample buffer ("s_nalu_stats.type[s->data[i] & 0x1F] += 1;"), and line 100 additionally passes the out-of-range pointer/length pair to do_NAL(). Under AddressSanitizer the process aborts with "heap-buffer-overflow ... READ of size 1 ... 0 bytes to the right of 892-byte region ... in process_avc_sample" at mp4.c:99:22.
2. Affected version / environment
- Project: CCExtractor (https://github.com/CCExtractor/ccextractor)
- Version: version string 0.96.5, master branch commit d7eb132e15f4d1e2c40f4655349596b2b8f708de (source dated 2026-10-17, binary compiled 2026-10-26)
- Environment: Linux x86_64 (Ubuntu container), ccextractor built with AddressSanitizer, statically linked; libGPAC 2.0; default CLI options, output target .srt
- Component: src/lib_ccx/mp4.c:99 (process_avc_sample), reached via process_avc_track (mp4.c:295) and processmp4 (mp4.c:989) through the GPAC MP4 demux path
3. Steps to reproduce
1. Build ccextractor at master commit d7eb132e15f4d1e2c40f4655349596b2b8f708de with AddressSanitizer.
2. Save the attached crash-input.bin (SHA-256 9d42a6cb84ce7989f69e897a7b94d4e694fd90ffecd1ddf5642746ca9dfe64b2, a malformed MP4 file, 85,748 bytes).
3. Run: ccextractor crash-input.bin
(verification used: env ASAN_OPTIONS=abort_on_error=0:symbolize=1:detect_leaks=0:allocator_may_return_null=1:print_legend=0:malloc_context_size=0 /lh/ccextractor/src/build/ccextractor /lh/tmp/poc-export/ccx-mp4avc/crash-input.bin inside the container)
4. Observe the process abort with an AddressSanitizer heap-buffer-overflow report while "Processing track 1, type=vide subtype=avc1".
5. Negative control: a valid MP4 file with an avc1 track (negative-control.bin, SHA-256 c4e5198b915b07d943983858a3c5f339b9d5aa77151eaca1e028175c0317f4d7) takes the same GPAC path ("Processing track 1, type=vide subtype=avc1") and completes with no sanitizer report, confirming the crash is input-specific.
4. Expected behavior
ccextractor should reject the malformed NAL length (32-bit wrap-around defeat of the bounds check), skip or report the corrupted sample, and exit normally without reading past the end of the GPAC sample buffer.
5. Actual behavior
=================================================================
==2938641==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6180000063fc at pc 0x55a148390d9f bp 0x7ffd5e0f28d0 sp 0x7ffd5e0f28c8
READ of size 1 at 0x6180000063fc thread T0
#0 0x55a148390d9e in process_avc_sample /lh/ccextractor/src/src/lib_ccx/mp4.c:99:22
#1 0x55a148390d9e in process_avc_track /lh/ccextractor/src/src/lib_ccx/mp4.c:295:13
#2 0x55a148390d9e in processmp4 /lh/ccextractor/src/src/lib_ccx/mp4.c:989:9
#3 0x55a14808c4e0 in start_ccx /lh/ccextractor/src/src/ccextractor.c:252:12
0x6180000063fc is located 0 bytes to the right of 892-byte region [0x618000006080,0x6180000063fc)
allocated by thread T0 here:
#0 0x55a147efe28b in malloc (/lh/ccextractor/src/build/ccextractor+0x19928b) (BuildId: 7698bf0a2d6a1980221851c4e3b7738245c921f8)
SUMMARY: AddressSanitizer: heap-buffer-overflow /lh/ccextractor/src/src/lib_ccx/mp4.c:99:22 in process_avc_sample
6. Impact
Out-of-bounds read on the heap (CWE-125). The read byte past the GPAC sample buffer is used as an NAL-type statistic index, and the same out-of-range cursor/length pair is then handed to do_NAL() (mp4.c:100), which parses attacker-reachable out-of-bounds memory as NAL content; under AddressSanitizer the process aborts deterministically, and outside the sanitizer the oversized NAL parse walks into unmapped memory and crashes. Automated caption-extraction or transcoding pipelines that accept user media can therefore be crashed by a single crafted file. No write primitive is demonstrated; information disclosure was not observed (the read value only increments an internal counter), and the conservative CVSS impact ratings are documented in the attached report.
7. Suggested fix
Perform the end-of-NAL bounds check in wrap-safe (64-bit) arithmetic, e.g.
const u32 previous_index = i;
i += c->nal_unit_size;
[poc.zip](https://github.com/user-attachments/files/34296733/poc.zip)
if ((uint64_t)i + nal_length <= previous_index || (uint64_t)i + nal_length > s->dataLength)
return status;
and additionally reject nal_length values that exceed the remaining sample bytes before line 99 reads s->data[i] and before do_NAL() is called at line 100. An equivalent alternative is to validate `nal_length <= s->dataLength - i` explicitly after reading the length field.
8. Additional context (PoC / logs, redacted)
- Attached: crash-input.bin (malformed MP4, ftyp/free/mdat boxes, one avc1 video track; SHA-256 9d42a6cb84ce7989f69e897a7b94d4e694fd90ffecd1ddf5642746ca9dfe64b2)
- Negative control attached: negative-control.bin (valid MP4 with avc1 track, SHA-256 c4e5198b915b07d943983858a3c5f339b9d5aa77151eaca1e028175c0317f4d7) — same code path, runs clean
- Crash discovered by coverage-guided fuzzing of the master build (AFL crash id:000028 of the campaign); full sanitizer transcript archived in the verification environment; terminal screenshots of the live reproduction are available on request.
- Distinct from the NULL pointer dereference in sei_message() (src/lib_ccx/avc_functions.c:395): different function, different source location, different defect class.
- No reproduction was attempted on any other version; affected range is therefore not asserted beyond the tested commit.
- Ngôn ngữ chính
- C
- Star
- 913
- Fork
- 603
- Merge trung bình
- 1 ngày 10 giờ
- Pull request đã merge (30 ngày)
- 24
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc 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 CCExtractor/ccextractor
-
[BUG] DVB subtitle decoder: heap-buffer-overflow write in dvbsub_parse_clut_segment via unbounded entry_idCó thể đã có người làm @Aditya-Saroha đã nhận 6 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
CCExtractor/ccextractor#2440 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Heap OOB read in parse_ad_cdp: cc_count not bounded by packet lengthCó thể đã có người làm @Aditya-Saroha đã nhận 6 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CCExtractor/ccextractor#2425 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[BUG] Heap buffer overflow in parse_PMT with C0/C1 section lengthCó thể đã có người làm @kun-codes đã nhận 15 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
CCExtractor/ccextractor#2419 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[BUG] Filename sequence expansion (`+`) panics on numeric values exceeding `i32::MAX`Có thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
CCExtractor/ccextractor#2402 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
[BUG] CEA-708 .srt is written as Latin-1 and ignores --utf8/--latin1/--unicodeCó thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 65/100
CCExtractor/ccextractor#2450 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của CCExtractor/ccextractor
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
micropython/micropython#19906 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 10 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 83/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
sk3llo/ffmpeg_kit_flutter#176 ·