
Security Advisory: Nicht authentifizierte NULL-Pointer-Dereferenzierung stürzt den Server ab (TinyWeb)
Zugewiesene CVE-ID: CVE-2026-67184
Wenn TinyWeb eine Anfragezeile nicht parsen kann, gibt es einen Fehler zurück, lässt aber den URL-Zeiger der Anfrage auf NULL gesetzt. Der Aufrufer ignoriert den Fehler und übergibt die Anfrage an den Antwort-Ersteller, der diesen NULL-Zeiger dereferenziert und den Worker zum Absturz bringt. Einige wenige fehlerhafte Anfragen legen den gesamten Server lahm, und er erholt sich nicht.
TnyWeb/0.0.8e48f15d (2018-11-20), wo dieser Parser und dieser Antwortpfad eingeführt wurden, bis a381da2 (2023-11-22, neuester Stand auf master).CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:NEin nicht authentifizierter entfernter Angreifer, der den lauschenden TCP-Port des Servers erreichen kann (9090 in der mitgelieferten Konfiguration). Es sind keine Anmeldedaten oder Benutzerinteraktion erforderlich.
HttpParser::execute() weist das URL-Objekt erst zu, nachdem die Anfragezeile erfolgreich geparst wurde. Eine fehlerhafte HTTP-Version lässt die Versionsprüfung fehlschlagen und zum Fehler-Label springen, das -1 zurückgibt, bevor die Zuweisung ausgeführt wird:
// src/tiny_http/http_parser.cc:1401 (das "H" von "HTTP" wird hier erwartet)
checkOrGoError((ch == 'H')); // false -> goto error
// src/tiny_http/http_parser.cc:1692 (vom obigen goto übersprungen)
request->url = new Url;
// src/tiny_http/http_parser.cc:1750-1753
error:
LOG(Debug) << "http request content is invalid\n";
return -1;
Die HttpRequest wird mit std::make_shared<HttpRequest>() erzeugt, was sie wertinitialisiert, sodass url NULL bleibt, wenn die Zuweisung übersprungen wird.
WebProtocol::dataReceived() zeichnet den Rückgabewert auf, ruft aber unabhängig davon buildResponse() auf:
// src/tiny_http/http_protocol.cc:57-61
valid = m_nParser.execute(data.c_str(), begin, data.size(), m_pRequest.get());
valid_requ = (valid == -1) ? false : true;
// src/tiny_http/http_protocol.cc:75
m_nResponser.buildResponse(m_pRequest.get(), valid_requ, m_pResponse.get());
buildResponse() erhält valid_requ == false, prüft dies aber nie und dereferenziert den NULL-URL-Zeiger:
// src/tiny_http/http_responser.cc:66
Url* url = req->url; // NULL
// src/tiny_http/http_responser.cc:83
if (url->field_set & (1 << HTTP_UF_PATH)) { // SIGSEGV
Der Worker-Prozess stürzt bei diesem Zugriff ab. Er wird nicht in einen dienenden Zustand neu gestartet. Sobald die Worker weg sind, antwortet der Server nicht mehr.
Starten Sie den Server mit der mitgelieferten Konfiguration (lauscht auf Port 9090).
Bestätigen Sie, dass er eine normale Anfrage beantwortet:
curl http://TARGET:9090/
XTTP/1.1 schlägt bei der Versionsprüfung fehl, nachdem sich die Anfragezeile bereits auf den Anfragemodus festgelegt hat:printf 'GET / XTTP/1.1\r\n\r\n' | nc TARGET 9090
Ein an einen Worker angehängter Debugger zeigt den Absturz an der NULL-Dereferenzierung:
#0 HttpBuilder::buildResponse (valid_requ=false) at src/tiny_http/http_responser.cc:83
#1 WebProtocol::dataReceived (data="GET / XTTP/1.1\r\n...") at src/tiny_http/http_protocol.cc:75
Ein nicht authentifizierter Angreifer kann die Server-Worker mit wenigen kurzen Anfragen zum Absturz bringen und den Dienst durch erneutes Senden offline halten. Dies ist ein Denial of Service.
Prüfen Sie in dataReceived(), ob valid_requ false ist; erstellen Sie in diesem Fall eine Fehlerantwort und kehren Sie zurück, statt buildResponse() aufzurufen. Prüfen Sie in buildResponse() req->url auf NULL, bevor Sie es verwenden. Auch das Zuweisen des URL-Objekts vor einem möglichen Fehlschlag des Parsens würde die Lücke schließen.