Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2023-52356-libtiff-analysis — CVE-2023-52356(libtiff)의 근본 원인 분석 및 AddressSanitizer와 GDB를 사용한 패치 검증 | Kitploit
도구/GitHubGitHub/yardenbenita/cve-2023-52356-libtiff-analysis
Vulnerability AnalysisDebuggersBinary AnalysisPapers & ResearchLearning & Education
GitHubyardenbenita/cve-2023-52356-libtiff-analysis

CVE-2023-52356-libtiff-analysis

CVE-2023-52356(libtiff)의 근본 원인 분석 및 AddressSanitizer와 GDB를 사용한 패치 검증

저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
12시간 2분 전아직 검토되지 않음
공유

CVE-2023-52356 – libtiff TIFFReadRGBATileExt 분석

개요

이 실습은 libtiff의 CVE-2023-52356을 분석하며, TIFFReadRGBATileExt가 유효한 이미지 경계를 벗어난 이미지 좌표를 수신할 때의 동작에 초점을 맞춥니다.

이 분석에는 원본 크래시 재현, AddressSanitizer 및 GDB를 사용한 디버깅, 근본 원인 분석, 업스트림 패치 검토, 원본 리프로듀서 분석, 수정 버전 검증이 포함됩니다.

테스트 환경

  • 대상: libtiff
  • 취약 커밋: 4d0329a4
  • 수정 커밋: 51558511
  • 트리거 파일: triger_input_47
  • 도구: Clang, AddressSanitizer, GDB, CMake

크래시 재현

원본 리프로듀서는 AddressSanitizer를 활성화한 취약한 libtiff 빌드에 대해 컴파일되었습니다.

리프로듀서는 제공된 트리거 파일로 실행되었습니다:

root@kitploit:~
LD_LIBRARY_PATH="$PWD/libtiff/build-asan/libtiff" ./poc triger_input_47

실행 결과 잘못된 메모리 읽기로 인한 세그멘테이션 폴트가 재현되었습니다. AddressSanitizer 스택 추적은 TIFFReadRGBATileExt에서 호출된 memmove 작업 중 실패를 식별했습니다.

근본 원인 분석

GDB를 사용하여 다음 런타임 값으로 크래시 조건이 재현되었습니다:

root@kitploit:~
row = 34
img.height = 33
tile_ysize = 1

취약한 코드는 다음을 실행했습니다:

root@kitploit:~
read_ysize = img.height - row;

관찰된 값으로 이 계산은 다음과 같습니다:

root@kitploit:~
33 - 34 = -1

read_ysize가 부호 없는(unsigned) 타입이므로 결과는 다음과 같이 래핑되었습니다:

root@kitploit:~
read_ysize = 4294967295

이는 UINT32_MAX입니다.

read_ysize 값은 이후 memmove의 소스 포인터 계산에 사용되었습니다.

실패한 memmove 직전에 GDB는 다음을 보여주었습니다:

root@kitploit:~
read_ysize = 4294967295
read_xsize = 1
tile_ysize = 1
tile_xsize = 1
i_row = 0
raster = 0x7d0ff67e2d40

대상 포인터는 다음과 같이 평가되었습니다:

root@kitploit:~
0x7d0ff67e2d40

이는 raster 버퍼의 시작이었습니다.

소스 포인터는 다음과 같이 평가되었습니다:

root@kitploit:~
0x7d13f67e2d38

계산된 소스 포인터는 raster 버퍼 시작 지점에서 17179869176바이트, 약 16GiB를 초과한 위치였습니다.

GDB에서 memmove를 실행한 결과:

root@kitploit:~
SIGSEGV, Segmentation fault

백트레이스는 다음 크래시 경로를 보여주었습니다:

root@kitploit:~
__sanitizer_internal_memmove
__asan_memmove
TIFFReadRGBATileExt at tif_getimage.c:3345
LLVMFuzzerTestOneInput at poc.cc:61

이는 read_ysize의 부호 없는 언더플로우가 범위를 벗어난 소스 오프셋을 생성했음을 확인합니다. 결과적으로 잘못된 소스 포인터가 memmove에서 사용되어 잘못된 메모리 읽기와 세그멘테이션 폴트를 발생시켰습니다.

패치 분석 및 수정 검증

업스트림 수정은 취약한 read_ysize 계산 전에 명시적 경계 검사를 추가했습니다:

root@kitploit:~
if (col >= img.width || row >= img.height)
{
    TIFFErrorExtR(tif, TIFFFileName(tif),
                  "Invalid row/col passed to TIFFReadRGBATile().");
    TIFFRGBAImageEnd(&img);
    return (0);
}

수정된 버전에서 GDB를 사용하여 다음 런타임 값이 관찰되었습니다:

root@kitploit:~
row = 34
img.height = 33
col = 0
img.width = 2047

이 값들에 대해 새 검증 조건은 다음 때문에 true로 평가됩니다:

root@kitploit:~
row >= img.height
34 >= 33

따라서 함수는 다음을 보고했습니다:

root@kitploit:~
Invalid row/col passed to TIFFReadRGBATile()

그리고 0을 반환했습니다.

결과적으로 실행은 취약한 계산에 도달하지 못했습니다:

root@kitploit:~
read_ysize = img.height - row;

이는 취약한 버전에서 관찰된 부호 없는 언더플로우를 방지하고 잘못된 값이 이후 memmove 소스 포인터 계산에 사용되는 것을 차단합니다.

리프로듀서 분석 및 전제 조건

원본 리프로듀서는 Y축을 따라 타일 수를 잘못 계산합니다.

관련 코드는 TIFFGetField()의 반환 값을 TIFFComputeTile()의 Y 좌표로 직접 전달합니다:

root@kitploit:~
TIFFComputeTile(
    in_tif,
    0,
    TIFFGetField(in_tif, TIFFTAG_IMAGELENGTH, &tile_height),
    0,
    0)

GDB를 사용하여 tile_height에 다음이 포함된 것이 관찰되었습니다:

root@kitploit:~
tile_height = 33

그러나 TIFFGetField()는 다음을 반환했습니다:

root@kitploit:~
1

반환 값은 성공을 나타냅니다. 이는 이미지 높이가 아닙니다. 따라서 호출은 사실상 다음과 같이 됩니다:

root@kitploit:~
TIFFComputeTile(in_tif, 0, 1, 0, 0)

이 TIFF에 대해 GDB는 이 호출이 다음을 반환함을 보여주었습니다:

root@kitploit:~
2047

이 값은 Y축을 따른 타일 수가 아닌 타일 인덱스입니다.

원본 리프로듀서는 이 값을 num_tiles_y 계산에 사용하여 다음 결과를 얻었습니다:

root@kitploit:~
num_tiles_y = 63

그러나 이미지 크기와 타일 크기는 다음과 같습니다:

root@kitploit:~
image_width  = 2047
image_height = 33
tile_width   = 1
tile_height  = 1

따라서 Y축을 따른 올바른 타일 수는 다음과 같습니다:

root@kitploit:~
num_tiles_y = 33

잘못된 값 63은 이미지 높이가 33이고 유효한 Y 좌표가 0부터 32까지만임에도 불구하고 루프가 0부터 62까지의 Y 값으로 반복되게 합니다.

이로 인해 다음과 같은 잘못된 값이:

root@kitploit:~
row = 34

TIFFReadRGBATileExt에 전달될 수 있습니다.

취약한 libtiff 버전은 부호 없는 img.height - row 계산을 수행하기 전에 이 범위를 벗어난 좌표를 거부하지 않았습니다. 이로 인해 리프로듀서가 생성한 잘못된 API 입력이 메모리 안전성 실패로 이어질 수 있었습니다.

유지보수자가 제공한 수정된 리프로듀서는 이미지 및 타일 크기에서 직접 타일 수를 계산합니다.

동일한 TIFF에 대해 수정된 계산은 다음을 생성합니다:

root@kitploit:~
num_tiles_x = 2047
num_tiles_y = 33

수정된 리프로듀서는 동일한 취약한 libtiff 빌드와 동일한 트리거 파일로 테스트되었습니다.

프로그램은 상태 0으로 종료되었으며 AddressSanitizer 또는 SIGSEGV 보고가 생성되지 않았습니다.

이는 원본 리프로듀서에 잘못된 타일 수 계산이 포함되어 있다는 유지보수자의 관찰을 뒷받침합니다. 그러나 취약한 libtiff 버전은 여전히 방어적 행(row) 및 열(column) 검증이 부족하여 잘못된 API 좌표가 메모리 안전성 실패로 이어질 수 있었습니다.

검증 요약

리프로듀서libtiff 버전결과
원본 PoC취약 (4d0329a4)memmove에서 잘못된 읽기 및 SIGSEGV
수정된 리프로듀서취약 (4d0329a4)종료 상태 0, ASan/SEGV 없음
원본 PoC수정 (51558511)잘못된 행/열 거부, ASan/SEGV 없음

결론

TIFFReadRGBATileExt의 크래시는 범위를 벗어난 이미지 좌표가 취약한 libtiff 구현에 도달할 때 발생합니다.

원본 리프로듀서에서 잘못된 타일 수 계산으로 인해 num_tiles_y가 올바른 값 33 대신 63으로 계산됩니다. 결과적으로 리프로듀서는 유효한 이미지 범위를 벗어난 행을 TIFFReadRGBATileExt에 전달할 수 있습니다.

취약한 libtiff 버전에서는 다음 계산 전에 행 및 열 인수가 검증되지 않았습니다:

root@kitploit:~
read_ysize = img.height - row;

재현된 사례에서 row는 34였고 img.height는 33이었습니다. read_ysize가 부호 없는 타입이므로 뺄셈이 UINT32_MAX로 언더플로우되었습니다. 이 값은 이후 memmove의 소스 포인터 계산에 사용되어 잘못된 메모리 읽기와 세그멘테이션 폴트를 발생시켰습니다.

업스트림 수정은 이 계산 전에 명시적 행 및 열 경계 검증을 추가합니다. 수정된 빌드를 테스트하여 동일한 잘못된 좌표가 언더플로우와 memmove가 발생하기 전에 거부됨을 확인했습니다.

유지보수자가 제공한 수정된 리프로듀서도 동일한 TIFF 파일을 사용하여 취약한 빌드에 대해 테스트되었습니다. 올바른 타일 수를 계산했으며 AddressSanitizer 또는 SIGSEGV 보고 없이 완료되었습니다.

따라서 이 분석은 API가 올바르게 사용될 때 TIFF 파일 단독으로 메모리 안전성 실패를 유발한다는 것을 입증하지 않습니다. 원본 리프로듀서에는 잘못된 타일 수 계산이 포함되어 있으며, 역사적 libtiff 구현은 방어적 경계 검증이 부족하여 결과적으로 생성된 잘못된 API 입력이 메모리 안전성 실패로 이어질 수 있었습니다.

도구 다운로드