
# CVE-2024-35333 재현 및 근본 원인 분석 html2xhtml 1.3의 스택 버퍼 오버플로우로, ASan 크래시 출력과 코드 수준의 완화 지침을 포함합니다.
html2xhtml 버전 1.3의 문자셋(charset) 처리 기능에 스택 버퍼 오버플로(stack buffer overflow) 취약점이 존재합니다. 공격자는 특수하게 조작된 입력을 제공하여 이 취약점을 악용할 수 있으며, 이로 인해 스택에 위치한 'buf' 변수가 오버플로될 수 있습니다. 이 취약점을 성공적으로 악용하면 공격자가 임의의 코드를 실행하거나 애플리케이션을 충돌시켜 서비스 거부(denial of service)를 유발할 수 있습니다.
크래시를 재현하려면 프로젝트 웹사이트로 이동하여 최신 버전 1.3을 다운로드하세요.
tar 파일을 확보한 후 tar xvf XYZ.tar를 실행할 수 있습니다.
실행:
./configure
make
./html2xhtml poc.html
세그멘테이션 폴트(segmentation fault)가 발생해야 합니다. 이를 Address Sanitizer로 분석해 보겠습니다.
실행:
make clean
make CFLAGS=-fsanitize=address
./html2xhtml poc.html
다음 출력을 확인합니다:
=================================================================
==3468537==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fffffffde70 at pc 0x7ffff7493fc4 bp 0x7fffffffdc00 sp 0x7fffffffd3a8
READ of size 86 at 0x7fffffffde70 thread T0
#0 0x7ffff7493fc3 in __interceptor_memmem ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:686
#1 0x5555555f5f35 in read_charset_decl /home/kenny/Downloads/html2xhtml-1.3/src/charset.c:680
#2 0x5555555f7d89 in guess_charset /home/kenny/Downloads/html2xhtml-1.3/src/charset.c:508
#3 0x5555555f7d89 in charset_auto_detect /home/kenny/Downloads/html2xhtml-1.3/src/charset.c:343
#4 0x555555568d49 in main /home/kenny/Downloads/html2xhtml-1.3/src/html2xhtml.c:100
#5 0x7ffff7029d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#6 0x7ffff7029e3f in __libc_start_main_impl ../csu/libc-start.c:392
#7 0x55555556b914 in _start (/home/kenny/Downloads/html2xhtml-1.3/src/html2xhtml+0x17914)
Address 0x7fffffffde70 is located in stack of thread T0 at offset 544 in frame
#0 0x5555555e86bf in read_charset_decl /home/kenny/Downloads/html2xhtml-1.3/src/charset.c:536
This frame has 1 object(s):
[32, 544) 'buf' (line 537) <== Memory access at offset 544 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:686 in __interceptor_memmem
Shadow bytes around the buggy address:
0x10007fff7b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b80: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00
0x10007fff7b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007fff7bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[f3]f3
0x10007fff7bd0: f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
0x10007fff7be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1
0x10007fff7bf0: f1 f1 00 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
0x10007fff7c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==3468537==ABORTING
소스 코드를 살펴보고 취약한 함수인 read_charset_decl()을 검토해 보겠습니다. 이 함수는 100줄이 넘는 코드로 구성되어 있습니다. 이를 단순화하여 다음 특정 루프를 살펴보겠습니다.
for (i = ini, len = 0; i < avail && len < SCAN_LEN; i += step, len++) {
buf[len] = tolower(buffer[i]);
}
이 루프는 buffer 배열의 데이터를 buf로 복사하면서 문자를 소문자로 변환합니다. 문제는 avail이 SCAN_LEN보다 클 때 발생하며, 루프가 buf의 상한 경계를 초과하는지 확인하지 않는다는 점입니다.
이를 완화하려면 len이 SCAN_LEN을 초과하지 않도록 경계 검사(bounds checking)가 있어야 합니다.