O'Reilly logo

PHP-Sicherheit: PHP/MySQL-Webanwendungen sicher programmieren by Stefan Esser, Christopher Kunz

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

974.12 XSS verbieten, HTML erlauben – wie?
Nutzt das Dokument den UTF-8-Zeichensatz, dann sieht der Auf-
ruf von
htmlentities() in etwa so aus:
$str = htmlentities($str, ENT_QUOTES, ‘UTF-8’);
Zu beachten ist bei der Wahl des Zeichensatzes, dass dieser den Brow-
sern bekannt ist. Wird ein unbekannter Zeichensatz ausgewählt, dann
führt das wiederum zu heuristischer Ermittlung des Zeichensatzes.
4.12 XSS verbieten, HTML erlauben – wie?
Leider ist das Leben nicht immer so einfach wie im obigen Fall. Gerade
Autoren von CMS- oder Blog-Systemen und oft auch Foren sehen sich
mit der Anforderung konfrontiert, HTML-Code in ihren Eingabefor-
mularen zuzulassen und trotzdem Sicherheit gegen XSS-Angriffe zu
gewährleisten. Ein einfaches
strip_tags(), das sämtliche SGML-Tags
vernichtet, ist hier fehl am Platze, da dem Benutzer die Möglichkeit
gegeben werden soll, seinen Text ansprechend zu formatieren.
4.12.1 BBCode
Eine Möglichkeit, diesem Problem beizukommen, ist ein Pseudo-Mar-
kup wie BBCode, also eine zusätzliche Auszeichnungssprache, die von
Ihrer Anwendung dann wieder in HTML zurückübersetzt wird. Dieser
Ansatz ist Erfolg versprechend, wenn Sie den Benutzern Ihres CMS,
Blog- oder Forumsystems die Benutzung von BBCode nahebringen
können – effektiv hat sich die Benutzerfreundlichkeit dann jedoch
nicht wesentlich gegenüber der direkten Eingabe von HTML erhöht.
Zudem müssen Sie mit einigem Aufwand rechnen, wenn Sie mittels
BBCode die Funktionalität, die HTML bietet, also insbesondere ver-
schachtelte Tags und Tag-Attribute, reimplementieren möchten.
Der Ansatz, den BBCode verfolgt, ist recht simpel: Der Autor eines
Textes oder Postings verwendet an den HTML-Standard angelehnte
oder von Ihnen vorgegebene Tags, die statt mit Spitzklammern »<>«
mit eckigen Klammern »[ ]« umrahmt werden. Ihr Skript führt dann
zunächst mit sämtlichen Benutzereingaben ein
strip_tags() durch, um
möglicherweise im Text enthaltenen HTML-Code zu eliminieren, und
evaluiert dann alle BBCode-Tags. Diese Auswertung ist meist ein
schlichtes
str_replace() oder preg_replace().
/2+8./68 #3/ /8?>D/</381+,/8 @9< ./< 8D/31/ =>/>= 738./=>/8=73>
htmlentities ($benutzereingabeENT_QUOTES$zeichensatz)?8.>/36/8
#3/./7<9A=/< 377/<:/<$$ /+./< 9./<$/>+$+173>A/6
-2/<)/3-2/8=+>D1/8?>D>A3<.
4 Cross-Site Scripting98
Um sich die äußerst zeitaufwendige Implementierung von BBCode
zu sparen, können Sie auf das PEAR-Paket HTML_BBCodeParser
2
zurückgreifen. Dieser Parser enthält eine komplette Parsing-Engine
anstatt einiger Regex-Aufrufe und ist in der Lage, fehlerhaftes Nesting,
also Verschachtelung in BBCode-Tags, selbsttätig zu beheben.
Das PEAR-Paket installieren Sie wie von Ihrer Umgebung gewohnt
per Kommandozeile, Webinterface oder indem Sie die Dateien von
Hand ins passende Verzeichnis kopieren.
Eine Instanz des BBCode-Parsers rufen Sie dann mit folgendem
Codeschnipsel auf, der auch gleich einen String mit BBCode in HTML
wandelt:
require_once("HTML/BBCodeParser.php");
$parser = new HTML_BBCodeParser();
$parser->setText($zu_parsender_text);
$parser->parse();
$output = $parser->getParsed()
Das BBCode-Parser-Paket ersetzt nun alle gültigen BBCode-Tags
durch die entsprechenden XHTML-kompatiblen HTML-Tags. Für
den String
Dieser String ist [b]fett[/b] und [u]unterstrichen[/u] und
[i]kursiv[/i]
wäre die korrekte Ersetzung
Dieser String ist <strong>fett</strong> und <u>unterstrichen</u>
und <em>kursiv</em>
Auch geschachtelte Tags werden unterstützt, URLs und Listen sind
auch im Angebot des für Foren und viele andere Anwendungen völlig
ausreichenden Paketes.
Vorsicht: Cross-Site Request Forgery (CSRF) ist prinzipbedingt lei-
der bei allen bisherigen Implementierungen von BBCode möglich –
dazu später mehr.
4.12.2 HTML-Filter mit XSS-Blacklist
Wir möchten Ihnen zusätzlich eine etwas andere Vorgehensweise ans
Herz legen, die in mehreren Schritten eine flexible, aber dennoch wirk-
same Methode gegen XSS darstellt. Zwar ist sie etwas aufwendiger als
strip_tags() oder ähnliche Funktionen, aber wenn Sie die in diesem
Buch vorgestellten »XSS-Cleaner« in eine Funktionsbibliothek einfü-
gen, können Sie sämtliche Inhalte ebenso einfach filtern.
2. http://pear.php.net/package/HTML_BBCodeParser
994.12 XSS verbieten, HTML erlauben – wie?
Beim Überfliegen des Abschnittes über das XSS Cheat Sheet haben
Sie vermutlich festgestellt, dass es eine große Zahl von Möglichkeiten
gibt, XSS-Angriffe auf Ihre Skripte auszuführen – und dass Sie mit
einem einzigen Filter nur eine kleine Untermenge dieser Angriffe finden
und entfernen können. Die ideale Strategie für einen XSS-Filter, der
selektiv HTML zulässt, wäre daher eine Whitelist, die ausschließlich
die Tags und Attribute im Quellcode belässt, die keinen schädlichen
Code enthalten können. Eine solche Whitelist wird von der Anwen-
dung »HTML Purifier« implementiert, die wir Ihnen im nächsten
Abschnitt vorstellen. Für bestimmte Fälle kann es jedoch nützlich sein,
einen Blacklist-basierten HTML-Filter zu kennen, der als verdächtig
bekannte Elemente aus HTML-Code entfernt.
Bevor Sie die tatsächliche Entfernung XSS-verdächtiger Tags und
Attribute vornehmen, können Sie zunächst Ihre eigene Tag-Whitelist
erstellen, die nur gewollte HTML-Tags enthält. Nicht für Benutzerein-
gaben sinnvoller Markup-Code wie
<META>, <script> und <BODY> wird
dann von PHP entfernt.
Die PHP-Funktion
strip_tags() verfügt über eine solche Whitelist-
Funktionalität, mit der Sie zunächst alle HTML-Tags entfernen kön-
nen, die Ihr Skript nicht benötigt. Sie sollten jedoch darauf achten,
dass diese Funktion keine Syntaxprüfung vornimmt. Halboffene Tags
oder inkorrekte HTML-Syntax können dazu führen, dass mehr Inhalt
entfernt wird als erwartet.
Möchten Sie alle HTML-Tags bis auf
<a>, <div>, <img> und <pre>
verbieten, erreichen Sie das mit dem Funktionsaufruf
$stripped_html = strip_tags($html, "<a><div><img><pre>");
Aus einem HTML-Block wie
<div> <a href="http://www.foobar.de/"> <u>foo</u> </a> <b>blah</b>
<pre>fasel</pre>
wird mit der oben genannten Funktion Folgendes:
<div><a href="http://www.foobar.de/"> <u>foo</u> </a>blahfasel
Nachdem Sie alle Tags entfernt haben, die in jedem Fall unerwünscht
sind, ist es Zeit, mit einem geeigneten Parser sämtliche restlichen uner-
wünschten Attribute und Tags zu entfernen. Die Klassensammlung
SafeHTML
3
verfügt über einen solchen Parser auf Basis der PEAR-
Klasse XML_HTMLSax3
4
und gilt als ein gutes Mittel gegen XSS.
3. http://pixel-apes.com/safehtml/
4. http://pear.php.net/package/XML_HTMLSax3

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required