HTTP Response Splitting
Bei HTTP Response Splitting handelt es sich um eine Schwachstelle in Webapplikationen, die durch die unzureichende Überprüfung von Nutzerdaten entsteht. Während sie für sich genommen im Normalfall keine größeren Auswirkungen hat, kann sie als Basis für weiterführende Angriffe, wie z.B. Cache Poisoning verwendet werden.
Hintergrund
Wenn ein Nutzer in seinem Browser eine Webseite aufruft, schickt der Browser zunächst einen HTTP-Request an den Server. Dieser antwortet daraufhin mit einer HTTP-Response, welche im Idealfall die gewünschte Webseite enthält. Die ausgetauschten HTTP-Nachrichten bestehen dabei im Allgemeinen aus einem Header und einem optionalen Body. Während der Body den eigentlichen Inhalt der Nachricht – bspw. den Inhalt der Webseite – enthält, spezifiziert der Header Meta-Daten, wie z.B. Cookies oder den Typ des Body (d.h. JSON, Plain-Text, HTML,…).
Eine möglicher HTTP-Response kann z.B. wie folgt aussehen:
HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=UTF-8 Content-Length: 748757 [... Inhalt ... ]
Zunächst bestätigt der Server die erfolgreiche Ausführung der Abfrage mit einem HTTP Statuscode 200. Es folgen Angaben zu verwendeten Server-Software (nginx), der Art des im Body zurückgelieferten Inhalts (html) und der Gesamtlänge des Body in Bytes. Jede Zeile wird hierbei durch ein carriage return (CR, 0x13) und einem folgenden line feed (LF, 0x10) von der nach folgenden Zeile getrennt. Abschließend – und durch ein weiteres CR/LF getrennt – folgt der eigentliche Body.
Erlaubt eine Anwendung das Einbringen von Nutzerdaten in den Response-Header und prüft die Nutzerdaten nicht auf eventuell vorhandene CR/LF, dann kann ein Angreifer die Response in zwei Teile aufsplitten. Der Server wird nun den vom Angreifer gesendeten Request mit dem ersten Teil der Antwort beantworten, der zweite Teil wird als Antwort auf die nächste Anfrage der gleichen Verbindung geschickt.
Beispiel Web-Cache Poisoning
Eine Webapplikation biete eine URL mit einer redirect-Funktionalität an:
www.vulnerable.com/redirect.php?dest=http://www.google.de
Hierbei sei die Implementierung so gewählt, dass der Query-Parameter dest direkt und ungeprüft in das Location-Feld der Response geschrieben wird.
Das geht schnell und einfach z.B. mit folgendem PHP-Code:
header("Location:" . $_GET['dest'])
Ruft ein Nutzer die entsprechende URL (z.B. www.vulnerable.com/redirect.php?dest=http://www.google.de) auf, antwortet der Server mit einer Weiterleitung:
HTTP/1.1 301 Moved Permanently Location: http://www.google.de
Dieser Applikation sei nun ein Web-Cache vorgeschaltet, das heißt bereits bekannte Anfragen werden, um die Performance zu steigern, nicht neu generiert, sondern mit Antworten aus dem Cache beantwortet. Gelingt es einem Angreifer den Inhalt des Caches zu seinen Gunsten zu manipulieren, spricht man von Cache Poisoning. In dem Fall bekommen alle Besucher der betroffenen Seite den manipulierten Inhalt aus dem Cache ausgeliefert.
Der geneigte Angreifer würde im obigen Fall zunächst folgende GET-Request absetzen:
GET /redirect.php?dest=http://www.google.de%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP%2f1.1%20200%0d%0aContent-Length:%2016%0d%0a%0d%0a<h1>Evil!!!</h1> HTTP/1.1 Host: www.vulnerable.com
Entsprechend seiner Implementierung setzt der Server den in dest übergebenen Wert in das Location-Feld ein. Da der dest-Parameter aber explizite CR/LF (%0d%0a
) Terme enthält, wird die HTTP-Response in zwei Antworten aufgespalten:
HTTP/1.1 301 Moved Permanently Location: http://www.google.de Content-Length: 0
HTTP/1.1 200 Content-Length: 16 <h1>Evil!!!</h1>
Da nur eine Anfrage gestellt wurde, wird diese mit der ersten Antwort beantwortet, die zweite bleibt vorerst in der Ausgangsqueue des Servers.
Im letzten Schritt, stellt der Angreifer nun – über die gleiche Verbindung – eine Anfrage an die zu manipulierende Ziel-URL, z.B. www.vulnerable.com/about-us. Der Server beantwortet diese Anfrage mit der nächsten Antwort in der Ausgangsqueue, dass heißt:
HTTP/1.1 200 Content-Length: 16 <h1>Evil!!!</h1>
Landet diese Antwort nun im Web-Cache, erhält jeder zukünftige Besucher der about-us-URL die manipulierten Antwort aus dem Cache. Neben dem im Beispiel gezeigten Defacement (d.h. Verunstaltung) der Webseite durch entsprechenden HTML-Code, lassen sich auf diese Weise vom Angreifer auch manipulierte Antworten mit Skriptcode (z.B. Javascript) im Cache positionieren.
Abhilfe
Das wirksamste Mittel gegen HTTP Response Splitting ist eine korrekte Überprüfung der vom Nutzer übergebenen Daten vor dem Generieren der HTTP-Response. Lässt sich die Übernahme von nutzergenerierten Daten nicht vermeiden, sollten diese explizit auf alpha-numerische Werte beschränkt werden.
Links
[Owasp.org] HTTP Response Splitting
[Wikipedia] HTTP Response Splitting
[Portswigger] HTTP Response Splitting
[Whitepaper, Amit Klein] HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics