Blacklist umgehen - ein Beispiel aus der Praxis

Um Angriffe auf die eigene Webseite zu unterbinden setzen viele Unternehmen auf eine Blacklist. Das ist eine Liste an Begriffen, die in normalen Anfragen nicht vorkommen. Trifft die Webanwendung auf eine Anfrage mit einem dieser Begriffe, so leitet sie auf eine Fehlerseite um oder ersetzt den Begriff. Richtig eingesetzt, kann eine solche Liste helfen, Angriffe zu unterbinden. Dass dies jedoch schwierig ist, zeigt das folgende Beispiel bei einem bekannten News-Portal.

Die Suchfunktion und die Blacklist


Nachdem ich meine tägliche Portion sicherheitsrelevanter Nachrichten gelesen hatte, warf ich einen Blick auf die Suchfunktion besagter Webseite. In einem JavaScript Block fiel mir auf, dass die Filterung von Sonderzeichen fehlerhaft war. Sonderzeichen wurden mit einem Backslash maskiert, damit sie nicht aus dem Kontext ausbrachen. Beim Backslash selbst allerdings fehlte diese Maskierung.

Die Eingabe
111'222 wurde zu
variable = '111\'222'; , was soweit problemlos ist.

111\'222 wurde allerdings zu
variable = '111\\'222'; , was zu einem Fehler führte. Der Backslash hebelt den zweiten Backslash aus und die Zuweisung wird danach beendet. Die folgenden Zeichen „222';“ führen dann zu einem Fehler, weil sie dort nicht erwartet werden.

Nun sollte man über die Eingabe 111\'+alert(1);// eigentlich eine JavaScript Alert-Box öffnen können. Das schlug aber fehl.

Die Blacklist in Aktion


Ich änderte meine Eingabe voller Vorfreude, doch das Ergebnis war ernüchternd. Es passierte nichts.
Warum war das so? Ein Blick in den Quellcode zeigte das Problem.

Die Eingabe
111\'+alert(1); wurde zu
variable = '111\\'+ersetzt[1](1);//'; . Mein alert wurde durch ein ersetzt[1] ersetzt.

Auch andere Begriffe, wie:
- document.cookie, document.domain, document.(..)
- window.location, window.(..)
- String.fromCharCode
und viele mehr wurden durch ein „ersetzt“ ausgetauscht.

Nicht ausgetauscht und damit valide Suchbegriffe waren allerdings „String“, „document“ oder auch „eval“.

Die Strategie


Mit der String.fromCharCode Funktion kann man in JavaScript beliebige Zeichenketten bilden. Dabei werden der Funktion lediglich die Ascii-Werte der Zeichen übergeben (Zahlen von 0-255), welche wohl kaum von der Blacklist geblockt werden.
String.fromCharCode(72,97,108,108,111) wird z.B. zu „Hallo“.

Über diese Funktion können wir also unseren finalen Angriffsvektor einschleusen. Übergeben wir diese Zeichenkette an die eval-Funktion, die ja nicht geblockt war, so wird diese die Zeichenkette interpretieren und ausführen.

Wenn Sie aufmerksam waren, werden Sie das Problem bemerkt haben. „String.fromCharCode“ wird von der Liste blockiert. War also alles umsonst?

Der Angriffsvektor im Detail


Mein endgültiger Vektor war:
1\';a=String;b=a.fromCharCode(97, 108, 101, 114, 116, 40, 100, 111, 99, 117, 109, 101, 110, 116, 46, 100, 111, 109, 97, 105, 110, 41);c=eval(b);//
Die Zahlen übersetzen zu „alert(document.domain)“, und die Domain der Webseite wurde in der Alert-Box ausgegeben. Die Sicherheitslücke war also bestätigt.

Um den Filter für die fromCharCode Methode zu umgehen, habe ich zuerst das String-Objekt einer anderen Variable, a, zugewiesen. Nun konnte ich „a.fromCharCode“ aufrufen, was nicht blockiert war. Damit konnte ich meine JavaScript Anweisung in der Variable b speichern. Dann rufe ich eval(b) auf, was die Anweisung interpretiert und ausführt.

Was lernen wir daraus?


Die Blacklist hat mir in jedem Fall das Leben schwerer gemacht. Die Lücke, dass der Backslash nicht maskiert wurde, wäre sonst einfacher auszunutzen gewesen. Es zeigt aber auch, dass eine Blacklist nur sehr schwer die Ausnutzung einer Sicherheitslücke durch einen entschlossenen Angreifer verhindern kann. Dies gilt besonders, wenn an anderen Orten Schwachstellen existieren.
Die Möglichkeiten zur Ausnutzung sind einfach zu groß um alle Fälle abzudecken und gleichzeitig einen normalen Nutzer nicht zu sehr einzuschränken.

Eine konsequente Codierung der Sonderzeichen hätte in diesem Fall eine bessere Wirkung gehabt, da sie den kompletten Vektor unbrauchbar gemacht hätte.
Denis Werner
02.04.2015

zurück