HTML-Injection und reguläre Ausdrücke

Warum reguläre Ausdrücke nicht dazu geeignet sind, Code-Injection zu vereiteln

Um eine (HTML-) Eingabe eines Benutzers auf deren Validität zu überprüfen, scheinen sich reguläre Ausdrücke geradezu anzubieten und tatsächlich ist das auch sehr gut möglich. Allerdings gibt es dabei zwei Probleme: Erstens ist ein regulärer Ausdruck, der in der Lage sein soll, ein ganzes HTML-Dokument zu validieren so unglaublich komplex, dass ihn wohl kaum ein Mensch lesen könnte. Das erhöht die Fehleranfälligkeit und schafft damit Sicherheitslücken. Das zweite Problem jedoch ist wesentlich wichtiger: Was passiert, wenn die HTML-Eingabe nicht valide ist, wenn sie also Elemente enthält, die unerlaubte HTML-Elemente und/oder -Attribute enthalten und dadurch dazu geeignet ist, Cross-Site-Scripting Angriffe oder ähnliche Angriffe zu initiieren?

Man könnte nun die gesamte Eingabe verwerfen. Das wäre sicher, allerdings wird man das in der Praxis vermeiden wollen, um Nutzer nicht zu verärgern. Stattdessen kann man die Eingabe entweder wieder zurück an den Nutzer senden und ihn darauf aufmerksam machen, dass er verbotene Elemente in seinem Code verwendet hat. Der Nutzer könnte diese dann entfernen und sobald die Eingabe den Anforderungen des regulären Ausdrucks erfüllt, könnte diese gespeichert werden. Das wäre eine Lösung, würde man durch die Rückgabe des Codes nicht wissentlich einen Cross-Site-Scripting-Angriff ermöglichen! Indem man den sicherheitskritischen Code nämlich in ein HTML-Dokument einfügt, macht man genau das, was man eigentlich verhindern möchte. In Kombination mit anderen Angriffstechniken, könnte ein Angreifer so seine Eingaben an seine Opfer weiterleiten; dort würde der Schadcode dann ausgeführt werden. Man müsste die Eingabe also zumindest maskieren, wobei dann, wenn der Nutzer die Maskierung nicht wieder entfernt, der HTML-Code verloren ginge. Man hätte den Code also auch gleich nur maskieren können.

Eine andere Alternative wäre es, eine Methode wie preg_replace zu verwenden, um komplexe Ersetzungen in der Eingabe-Zeichenkette durchzuführen. Die Absicht ist klar: Man verwendet reguläre Ausdrücke, die Schadcode-Muster enthalten und ersetzt diese beispielsweise durch einen leeren String oder durch Teile dieser Zeichenketten. Das Problem dabei ist, dass ein Angreifer durch einen geschickten Aufbau seiner Eingabe Code erzeugen kann, der sich nach dem Einwirken von preg_replace zu neuem Schadcode zusammensetzt.

Das ist unbedingt zu vermeiden! Deshalb sollten Sie im Hinterkopf behalten, dass sich reguläre Ausdrücke in aller Regel nur zur Validierung einer Eingabe eignen, unter keinen Umständen jedoch dazu verwendet werden sollten, Eingaben im Nachhinein in ein valides Format umzuwandeln. Stattdessen ist ein Vorgehen, bei dem nur Teilzeichenketten validiert werden und anschließend entweder übernommen oder verworfen werden eine interessante Alternative zur Validierung von HTML-Eingaben. Ein solches Vorgehen ist im Artikel Validierung von HTML-Benutzereingaben beschrieben. Dort finden Sie auch eine Implementierung dieses Verfahrens.