PHP-Sicherheit: Cross Site Scripting

1 | 5 Kommentare | 10905 Aufrufe
Sie können diese Wikiseite nach der Anmeldung auf Webmasterpro bearbeiten. Helfen Sie mit und verbessern Sie "PHP-Sicherheit: Cross Site Scripting" mit Ihrem Wissen!

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:

unsicheres Beispiel  
PHP
 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 "&lt;" 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.

 
PHP
 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.


Wikiseite bearbeiten

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.

Mitarbeiter
  • 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.

Kommentare: PHP-Sicherheit: Cross Site Scripting

Neuen Kommentar schreiben
Titel
Beantworten

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?

Cedric Staub am 19.07.2008 um 14:01
Re: Titel
Beantworten

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. ;-)

David Danier am 20.07.2008 um 01:21
Re: Titel
Cedric Staub am 20.07.2008 um 11:29
htmlentities
Beantworten

Diese Funktion ist nicht utf-8-fähig. Ich denke, das sollte im Artikel erwähnt werden.

Normalo am 24.05.2008 um 11:43
Re: htmlentities
Beantworten

Diese Funktion ist nicht utf-8-fähig. Ich denke, das sollte im Artikel erwähnt werden.

Stimmt, wäre eine wichtige Information. Schreibst du das dazu?

David Danier am 24.05.2008 um 12:34