Skip to content

Latest commit

 

History

History
213 lines (168 loc) · 12.3 KB

File metadata and controls

213 lines (168 loc) · 12.3 KB

Apple ImageIO DNG 디코더의 범위 밖 쓰기 (CVE-2025-43300)

메타데이터

항목 내용
CVE ID CVE-2025-43300
영향 제품 iOS, iPadOS, macOS의 ImageIO/RawCamera 경로
영향 버전 iOS 18.6.2, iPadOS 18.6.2, iPadOS 17.7.10, iOS/iPadOS 16.7.12·15.8.5, macOS Ventura 13.7.8·Sonoma 14.7.8·Sequoia 15.6.1 미만
취약점 유형 CWE-787 범위 밖 쓰기(out-of-bounds write)
심각도 CISA-ADP CVSS v3.1 8.8 — AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
공개일 2025-08-20
악용 상태 Apple은 특정 표적을 대상으로 한 매우 정교한 공격에서 악용됐을 가능성을 인지한다고 공지했으며, CISA KEV에 등재됨
분석 기준 Apple 보안 공지, NVD/CISA, Quarkslab의 공개 바이너리 diff 분석. PoC는 실행하지 않음

개요

CVE-2025-43300은 Apple 운영체제의 ImageIO가 악의적으로 조작된 이미지를 처리할 때 발생하는 범위 밖 쓰기 취약점이다. Apple은 iOS 18.6.2, iPadOS 18.6.2 및 각 구버전·macOS 보안 업데이트에서 수정했고, 이미지 처리 중 메모리 손상이 일어날 수 있다고 설명했다. Apple은 실제 악용 가능성도 언급했으며 이 CVE는 CISA의 Known Exploited Vulnerabilities 목록에 추가됐다.

이 사례의 핵심은 이미지 파일이 단순한 그림이 아니라, 압축 방식·가로세로 크기·채널 수·픽셀당 샘플 수를 함께 선언하는 작은 프로그램에 가깝다는 점이다. 공개 바이너리 diff 분석에 따르면 Apple의 RawCamera 경로에 있는 lossless JPEG 압축 DNG 디코더에서, 파일이 선언한 구성요소 수와 출력 버퍼 계산에 사용된 샘플 수가 어긋날 수 있었다. 그 결과 디코더의 출력 포인터가 할당된 버퍼의 끝을 넘어 이동했다.

사전 지식

ImageIO는 여러 앱이 공유하는 입력 경계다

ImageIO는 앱이 이미지 파일을 열고, 메타데이터를 읽고, 썸네일을 만들고, 다른 이미지 표현으로 변환할 때 사용하는 운영체제 프레임워크다. 따라서 취약점은 특정 사진 앱의 화면 코드에만 있는 것이 아니라, 이미지가 자동으로 미리보기·메시지 첨부·사진 보관함 인덱싱 등의 경로를 통과할 때 공유 디코더에서 발생할 수 있다.

외부 이미지 바이트
        │
        ▼
  ImageIO / RawCamera
  TIFF·DNG 태그 해석
        │
        ▼
  lossless JPEG marker·Huffman 해석
        │
        ▼
  압축 해제된 픽셀 버퍼
        │
        ├─ Core Image / CGImage
        └─ 미리보기·메시지·사진 보관함 등 소비자

이런 공용 파서는 입력을 호출자보다 먼저 처리한다. 호출자가 화면에 표시하기 전에 파서가 먼저 파일을 읽으므로, “사용자가 이미지를 열었다”는 명시적 동작이 없어도 자동 처리 경로가 공격 표면이 될 수 있다. 다만 이 CVE의 실제 전달 앱·메시지 경로와 공격 체인은 Apple이 공개한 사실과 구분해야 한다.

DNG와 TIFF는 태그가 데이터 해석 방법을 결정하는 형식이다

DNG(Digital Negative)는 TIFF/EP를 바탕으로 한 RAW 이미지 형식이다. TIFF는 고정된 한 종류의 픽셀 배열만 저장하지 않고 태그로 이미지의 구조를 설명한다. 대표적으로 TileWidth·TileLengthRowsPerStrip은 공간 분할을, TileOffsets·StripOffsetsTileByteCounts는 압축 데이터의 위치와 길이를 알려 준다.

DNG/TIFF
 ├─ 구조 태그: width, height, tile/strip 정보
 ├─ 색·샘플 태그: SamplesPerPixel, BitsPerSample
 └─ 압축 데이터: Strip/Tile offset + byte count
                         │
                         ▼
                  디코더의 루프·버퍼 크기

SamplesPerPixel은 픽셀 하나를 구성하는 채널 또는 샘플 수다. RGB 8비트 이미지는 보통 픽셀당 3개 샘플이고, 16비트 샘플이면 한 채널을 저장하는 데 2바이트가 필요하다. 이 값은 색상 정보뿐 아니라 “한 행에서 픽셀을 얼마나 진행할지”와 “압축 해제 결과를 얼마나 할당할지”에 직접 영향을 준다.

lossless JPEG는 JPEG라는 이름만으로 충분히 설명되지 않는다

DNG는 손실 없는 JPEG 압축을 사용할 수 있다. 이 경로는 일반적인 사진용 baseline JPEG의 DCT 결과를 그대로 복원하는 경로와 다르게, JPEG marker와 Huffman table을 해석해 센서 데이터의 차분 값을 복원한다. Quarkslab 분석에서 문제 경로는 lossless Huffman JPEG를 뜻하는 SOF3 marker, DHTSOS marker를 처리하는 코드로 식별됐다.

SOF3에는 정밀도, 이미지 높이·너비, NumComponents가 들어간다. DHT는 압축된 픽셀 차분을 해석할 Huffman table을 정의하고, SOS 뒤에서 실제 scan 데이터의 압축 해제가 시작된다. 파서는 선언값을 신뢰해 반복 횟수와 출력 위치를 계산하므로, 서로 다른 태그가 논리적으로 일관되는지 검사하는 것이 메모리 안전성의 전제다.

출력 버퍼의 크기와 출력 포인터는 하나의 불변식을 공유해야 한다

압축 해제기는 보통 예상 출력 크기에 맞는 버퍼를 할당한 뒤, output 포인터를 디코딩한 바이트 수만큼 증가시키는 형태로 동작한다. 안전한 구현은 매 쓰기마다 다음 불변식을 유지해야 한다.

0 <= output - buffer_start
output + bytes_to_write <= buffer_start + buffer_size

크기 계산에 사용한 값과 실제 반복문이 사용한 값이 다르면, 할당 자체가 충분해 보여도 포인터가 끝을 넘을 수 있다. 특히 픽셀 수·채널 수·샘플 바이트 수를 각각 다른 태그에서 읽는 파서에서는 “파일 형식상 가능한 조합”과 “이 코드 경로가 가정한 조합”을 분리해 검증해야 한다.

취약점 분석

확인된 사실

  • Apple과 NVD는 악의적인 이미지 처리 중 메모리 손상이 가능한 범위 밖 쓰기로 설명한다.
  • Quarkslab은 iOS 18.6.1과 18.6.2의 바이너리를 비교해 RawCamera에서 변경된 함수들을 좁혔고, 관련 코드가 DNG 안의 JPEG lossless 압축 데이터를 해제하는 CDNGLosslessJpegUnpacker 경로임을 분석했다.
  • 분석된 입력 조건은 SOF3 marker, 구성요소 수에 맞는 Huffman table, SamplesPerPixel=2, NumComponents=1 조합이다.
  • Apple의 수정본은 출력 버퍼를 확보하고 그 크기를 얻는 함수를 호출한 뒤, 출력 쓰기 전에 버퍼 범위를 확인하고 초과 시 예외를 발생시키는 방어를 추가했다.
  • Quarkslab은 문제 재현을 위한 공개 분석을 설명하지만, 이 보고서에서는 해당 코드나 입력을 실행하지 않았다.

패치 전 동작과 불변식 붕괴

Quarkslab이 제공한 의사 코드는 실제 소스 그대로가 아니라 분석을 설명하기 위한 모델이다. 그 모델에서 출력 버퍼는 width * height * SamplesPerPixel을 기준으로 할당된다. 그런데 취약 경로는 파일의 NumComponents=1을 처리하면서도 반복 상한을 width * 2로 사용하고, 디코더의 출력 증가량도 샘플 수 2를 반영하는 것으로 분석됐다.

패치 전 — 선언값과 루프 가정이 어긋나는 경로

SOF3: NumComponents = 1 ─────┐
TIFF: SamplesPerPixel = 2 ────┼─> 버퍼: width × height × 2
                              │
                              └─> 루프: width × 2까지 진행
                                  decompress() 후 output += 2 bytes
                                             │
                                             ▼
                         output + write > buffer_end 가능
                                             │
                                             ▼
                                      범위 밖 쓰기

문제는 단순히 width * 2라는 숫자 하나만의 오류가 아니다. 디코더가 “픽셀당 저장 샘플 수”와 “압축 스트림이 제공하는 구성요소 수”를 동일한 의미로 취급하지 못했고, 그 차이를 출력 버퍼의 남은 크기로 보정하지 않았다. NumComponents=1인 상태에서 코드가 최소 2개 구성요소를 전제로 행을 계속 진행하면, 한 행에서 기대한 양보다 많은 데이터를 기록하고 그 오차가 높이 방향으로 누적된다.

여기서 NumComponents=1SamplesPerPixel=2 조합이 실제 파일 형식에서 어떤 의미를 가지는지, 그리고 각 내부 필드의 모든 값이 어떻게 설정되는지는 공개 분석이 설명한 범위를 넘어선다. 따라서 그 조합을 일반적인 DNG의 정상 구성이라고 단정하지 않고, 취약 코드 경로에 도달하는 분석 조건으로 기록한다.

보안 영향

할당된 버퍼 뒤의 메모리에 쓰면 인접 객체의 필드나 allocator가 관리하는 데이터를 덮을 수 있다. 그 결과는 충돌부터 메모리 손상, 정보·제어 데이터 변조까지 범위가 넓다. Apple의 CVSS 평가는 기밀성·무결성·가용성에 높은 영향을 부여하지만, 공개 자료만으로 이 CVE 하나가 어떤 실행 권한과 어떤 후속 체인을 제공했는지 확정할 수는 없다.

특히 이미지 파서가 메시지나 미리보기 같은 자동 처리 경로에서 호출될 수 있다는 점은 입력 경계의 중요성을 보여 준다. 그러나 “zero-click”이라는 전달 조건과 특정 공격자가 사용한 정확한 체인은 Apple 공지의 제한된 표현과 구분해야 한다.

수정 방법

운영체제를 다음 수정 버전 이상으로 업데이트한다.

악성 이미지
    │
    ▼
RawCamera / lossless JPEG 디코더
    │  (각 쓰기 전에 output + size <= buffer_end 검사)
    ├─ 참: 출력 기록
    └─ 거짓: 예외 처리, 범위 밖 기록 중단

확인된 패치의 중심은 출력 버퍼의 실제 크기를 조회하고, 디코더가 쓰려는 위치가 그 범위를 넘는지 각 쓰기 전에 검사하는 것이다. 이 방어는 입력 태그 사이의 의미 불일치가 남아 있더라도 메모리 경계를 직접 보호하는 마지막 불변식을 복원한다.

수정 버전은 iOS 18.6.2, iPadOS 18.6.2, iPadOS 17.7.10, iOS/iPadOS 16.7.12, iOS/iPadOS 15.8.5, macOS Sequoia 15.6.1, Sonoma 14.7.8, Ventura 13.7.8이다. Apple 제품군은 동일 CVE를 여러 브랜치에 백포트하므로 단일 버전 번호만 확인하지 말고 기기별 운영체제의 보안 업데이트 버전을 확인해야 한다.

PoC 관련 언급

NVD는 CVE와 연결된 공개 분석·PoC 참조를 기록하고 있다. 이 보고서는 링크의 존재를 취약점 자료의 공개성 판단에만 사용하며, 코드를 내려받거나 실행하지 않았다. 공개 코드의 실제 성공 여부나 공격 영향은 독립 검증하지 않았으므로, 재현 단계·페이로드·무기화 지침은 제공하지 않는다.

미해결/불확실 지점

  • Apple의 원본 소스와 공식 패치 diff는 공개되지 않아, 바이너리 분석의 함수명·필드 오프셋과 소스 수준 이름을 일대일로 확정할 수 없다.
  • SamplesPerPixel=2NumComponents=1이 만들어지는 정확한 태그 조합 및 모든 유효성 검사 순서는 공개 분석의 의사 코드와 설명에 한정된다.
  • Apple이 언급한 표적 공격에서 이 CVE가 단독으로 사용됐는지, 다른 취약점과 결합됐는지, 어떤 앱·전달 경로를 거쳤는지는 공개되지 않았다.
  • 범위 밖 쓰기가 실제로 어떤 객체를 덮고 최종적으로 어떤 권한의 코드 실행으로 이어졌는지는 공개된 자료만으로 확정하지 않는다.

참고 자료