PHP-Sicherheit: Cross Site Scripting

1 | 23966 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 benötigt den $encoding-Parameter um UTF-8-Texte korrekt zu verarbeiten. Ab PHP 5.4.0 ist UTF-8 Standard.

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