PHP-Sicherheit: Cross Site Scripting
Anzeige Hier werben
Beim Cross Site Scripting (nachfolgend mit XSS abgekürzt) wird (meist ausführbarer Javascript-)Code in die Webseite eingefügt. Dieser Code läuft dann im Kontext der Webanwendung und ist für den Besucher der Seite (und Browser) nicht von der restlichen Seite zu unterscheiden. Mithilfe von XSS lassen sich so:
- falsche Tatsachen darstellen
Beispiel: Ein Benutzer ersetzt seine schlechten Bewertungen durch gute - Daten ausspionieren
Beispiel: Cookie-Daten, inklusive der Session-Daten um die Benutzersitzung zu übernehmen (auch die des Adminstrators) - Benutzer auf schadhafte Seiten leiten
Beispiel: Ersetzen von Link-Zielen - Browserbugs ausnutzen um den Computer des Opfers mit einem Virus/Trojaner zu infizieren
Da der Administrator von solchen Angriffen im Normalfall keinerlei Notiz nimmt sind XSS-Fehler im Nachhinein schwer zu finden. Der Programmierer sollte deswegen schon beim Erstellen der Seite darauf achten XSS zu unterbinden.
Funktionsweise vom Cross-Site-Scripting
Es ist auch möglich XSS-Angriffe direkt durch den Einsatz von Javascript auszuführen. Dieser Artikel beschäftigt sich aber nur mit Fehlern die mit PHP auftreten können.
Wenn ein Script einen Parameter, der aus Benutzereingaben (GET, POST oder auch Cookies) stammen könnte, ungeprüft weiterverarbeitet und später ausgibt kann beliebiger Quelltext in die Seite eingeschleust werden.
Als Beispiel soll folgendes, sehr einfaches PHP-Script dienen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?php
if (isset($_COOKIE['name']) or isset($_GET['name']))
{
if (isset($_GET['name']))
{
setcookie('name', $_GET['name']);
$_COOKIE['name'] = $_GET['name'];
}
echo "Hallo ". $_COOKIE['name'];
}
else
{
?>
<form action="" method="get">
Gib deinen Namen ein: <input type="text" name="name" /><br />
<input type="submit" name="submit" />
</form>
<?php
}
?>
|
Hier kann der Benutzer in einem Formular seinen Namen eingeben, hat er das getan wird er in Zukunft mit "Hallo [Name]" begrüßt und das Formular verschwindet. Um den Namen über mehrere Aufrufe zu speichern wird außerdem ein Cookie mit dem Namen gesetzt.
Gibt nun ein Besucher <script type="text/javascript">alert("Test")</script> in das Formular ein wird genau dieser Text in der Seite ausgegeben. Folglich erscheint eine Hinweisbox mit dem Text Testim Browser. Natürlich sind weitaus weitreichendere Dinge mit Javascript möglich, die möglichen Angriffe sind bereits oben gelistet.
Schutz vor Cross Site Scripting
Benutzereingaben escapen
PHP bietet zwei Funktionen um HTML-Quelltext zu escapen. Das bedeutet, dass alle HTML-Sonderzeichen (z.B. "<", "&") so ausgezeichnet werden, dass sie vom Browser als eben diese Zeichen angezeigt und nicht als HTML interpretiert werden. Im Fall von "<" wird so beispielsweise "<" erzeugt.
htmlspecialchars()
Hierbei werden alle HTML-Sonderzeichen ersetzt. Konkret betrifft das "<", "&", ">" und je nach Parametern auch "'" und '"' (doppeltes und einfaches Anführungszeichen).
htmlentities()
Zusätzlich zu den von htmlspecialchars() ersetzen Zeichen werden hier auch Umlaute und andere Zeichen, entsprechend des Zeichensatzes, ersetzt. Vorsicht: Diese Funktion kann nicht korrekt mit dem "utf-8"-Zeichensatz umgehen.
Beispiel oben absichern
Werden die Ausgaben maskiert kann der Benutzer keinen HTML-Code mehr eingeben. Der obige Code ist somit sehr einfach abzusichern, indem man htmlspecialchars() oder htmlentities() bei der Ausgabe des Namens benutzt. Hierzu muss nur Zeile 9 ergänzt werden.
1 2 3 4 5 6 7 8 9 10 11 | <?php
if (isset($_COOKIE['name']) or isset($_GET['name']))
{
if (isset($_GET['name'])) /* ... */
echo "Hallo ". htmlspecialchars($_COOKIE['name']);
}
else
{
/* ... */
}
?>
|
Was ist mit strukturierten Texten?
Soll der Benutzer allerdings strukturierte Texte eingeben können wird die Aufgabe komplizierter. Reicht es, dass Zeilenumbrüche berücksichtigt werden, so ist nl2br() ein geeignetes Mittel. Für kompliziertere Auszeichnungen des Textes kann man BB-Code, ReST, Textile, Wikitext o.ä. benutzt werden.
Reicht die Auszeichnung mit reinem Text nicht aus kann man auch zu XML-Dokumenten greifen. Hier kann man sein eigenes Markup schaffen und dieses in XHTML umsetzen. Durch die Validierung der Dokumente können Strukturfehler sowie Javascript-Attribute vermieden werden. Allerdings muss das href-Attribute speziell gesichert werden (<a href="javascript:...">...</a>) und die Eingabe wird in den meisten Fällen für einem normalen Benutzer nicht machbar sein (ohne Web-Editor).
Wichtig bei XML-Dokumenten ist außerdem, dass XML-Kommentare nicht ausgegeben werden. Diese können über Conditional Comments Quelltext beinhalten, den der Internet Explorer interpretiert.
Keine Lösung: reguläre Ausdrücke
Reguläre Ausdrücke werden von einigen Seiten eingesetzt um Javascript in Eingaben zu erkennen und dann die Verarbeitung dieser Eingaben zu verweigern. Viele Beispiele in der Vergangenheit haben aber gezeigt, dass diese Technik die Möglichkeiten, die Javascript bietet, nicht abdecken kann. Das hat zur Folge, dass so gesicherte Seiten in der Vergangenheit immer wieder mit XSS-Lücken zu kämpfen hatten, die vom regulären Ausdruck nicht abgedeckt wurden.
Einspeisung von Quelltext durch den Image-Tag
Gerne wird auch schädlicher Quelltext durch den schlichten Einsatz eines Image-Tags eingespeist (<img src="test.php" />). Der heimtückische Trick hierbei besteht darin, dass als Source des Tags eine gefährliche Datei auf einem fremden Server eingespeist werden kann (im Grunde das selbe Problem wie mit den Includes). Es kann auch vorkommen das die Dateiendung einer bösen Quellcodedatei der eines Bildformates entspricht (jpg, gif, png), somit ist geraten durch im Absatz "Was ist mit strukturierten Texten?" schon hervorgehoben, BB-Code oder ähnliches zu verwenden und keine Bildeingabe zuzulassen.
Diese Seite kann von jedem registrierten Benutzer bearbeitet werden. Bisher haben 4 Personen an der Seite "PHP-Sicherheit: Cross Site Scripting" mitgewirkt.
Sie haben einen Fehler entdeckt oder möchten etwas ergänzen? Dann können Sie nach der Anmeldung "PHP-Sicherheit: Cross Site Scripting" hier bearbeiten.
-
David Danier arbeitet seit mehr als neun Jahren im Bereich Web Programmierung und ist unter anderem Geschäftsführer der Webagentur Team23 GbR, sowie Webmasterpro.de.
-
graphic, motion & web design - kernreaktor - staportal - mukitu
-
hat keine Beschreibung angegeben. Eine Beschreibung kann man unter dem Punkt "Profil bearbeiten" im Kontrollzentrum eintragen.
-
Patrick Freitag arbeitet als Java-Programmierer und Webworker in einer österreichischen Firma und beschäftigt sich seit ca. 6 Jahren mit der Webentwicklung. Neben der Programmierung in JavaScript, Python und PHP sind auch das Markup und Software Architektur seine Leidenschaft. Er ist auch auf Twitter aktiv.


Titel
Ich finde den Titel auf eine Art irreführend, das Problem (XSS) ist nicht nur auf Sprachen wie PHP beschränkt. Würde es nicht Sinn machen den Artikel auszubreiten und auch auf andere Sprachen einzugehen, sowie eventuell auch andere Sicherheitsprobleme wie CSRF?
Re: Titel
In dem Artikel geht aber aber gerade um die Prävention von XSS-Angriffen in PHP, er ist Teil der Serie "PHP Sicherheit". So etwas wie
htmlspecialchars()ist eben PHP-bezogen.Gerne können wir noch einen allgemeinen Artikel über gängige Sicherheitsprobleme im Web starten. ;-)
Re: Titel
Dann guckst du hier :-)
htmlentities
Diese Funktion ist nicht utf-8-fähig. Ich denke, das sollte im Artikel erwähnt werden.
Re: htmlentities
Stimmt, wäre eine wichtige Information. Schreibst du das dazu?