Cross-Site-Scripting
Ja, da ich in letzter Zeit mal wieder darauf gestoßen bin, hier mal ein kleiner Artikel zu einem Problem, das vor allem kleine Seiten und Scripts haben. Das Cross-Site-Scripting, kurz auch XSS.
Dabei handelt es sich um das Ausnutzen von Sicherheitslücken innerhalb fremder Seiten, indem Code entweder Client- oder Serverseitig auf diesen ausgeführt wird, ohne dass dies z.B. vom Besucher der Seite so ohne Weiteres zu erkennen wäre.
Der Einfachste Weg ist der Clientseitige. Dabei führt man, z.B. JavaScript, an Stellen aus, an denen es eigentlich nicht angedacht ist. Üblicherweise bieten sich dafür vor allem Formulare an, die ich als User selbst ausfüllen kann und deren Inhalt dann, aufbereitet oder nicht, z.B. in Forenprofilen o.Ä. angezeigt wird. Am einfachsten ist es, wenn die Angaben dann ohne Veränderung ausgegeben werden, was natürlich der optimalste Weg ist, da ich somit direkt in ein Formularfeld den Code eingeben kann, der beim Betrachter der Seite ausgeführt werden soll.
Wenn stattdessen aber z.B. der Inhalt als Link verwendet wird, muss man meistens erstmal aus der gegebenen Ausgabe "ausbrechen", d.h. letztendlich auch wieder Code ausführen können, bloß über einen kleinen Umweg. Wenn es sich um reines (x)HTML handelt reicht es meist den Parameter sowie Tag zu schließen, indem man z.B. folgendes als erstes angibt:
" /><!-- Hier geht es weiter mit dem eigenen Code -->
Gegebenenfalls muss auch am Ende eine ähnliche Struktur verwendet werden, um einen validen End-Quellcode zu erzeugen.
Eine andere, weniger bekannte, Fehlerquelle sind Bilder. Diese sollten nicht so ohne Weiteres mit der URL des Benutzers übernommen werden, denn der src-Parameter des Image-Tags eignet sich ebenfalls um Scriptcode auszuführen. Dieser könnte z.B. wie folgt aussehen:
<img src="javascript:alert('Das ist ein Beispiel für Cross-Site-Scripting.');" />
Was natürlich besonders gefährlich ist, dass sich genau auf dieselbe Art und Weise VB-Script im Internet Explorer ausführen lässt, indem man statt javascript: einfach vbscript: schreibt.
Als letztes, von mir hier aufgeführtes, Beispiel gibt es noch die Möglichkeit Unicode zu verwenden. Was ich mit am gefährlichsten ansehe, da es noch schwerer zu erkennen ist, als die anderen von mir genannten Varianten. Dabei lässt sich der o.g. Code z.B. wie folgt maskieren:
<img
src="javascrip
t:alert('D
as ist ei
n Beispie
l für Cro
ss-Site-Sc
ripting.'
);" />
Die Frage, wie man eben diese Gefahr abwehren kann, ist so einfach beantwortet, wie sie gestellt ist, nämlich durch sauberes und gewissenhaftes Coden. Am Beispiel von PHP sollte z.B. bei jeder Usereingabe gefiltert werden. Je nach Einsatzzweck ist oft ein guter erster Schritt die Funktion strip_tags(). Werden diese, z.B. zum posten von Code, doch gebraucht, dann speichert eure Daten erstmal soweit ab, achtet aber beim auslesen unbedingt darauf htmlentities() oder zumindnest htmlspecialchars() auf das, was ausgegeben werden soll, anzuwenden. Somit werden alle Sonderzeichen, die auch für eventuellen Code gebraucht werden, umgewandelt, sodass sie als Sonderzeichen im (x)HTML ausgegeben werden.
So wird z.B. < zu < und > zu >.
Bei dem im Image-Tag eingefügten Scripting kann man dann zusätzlich noch mit regulären Ausdrücken rangehen, bzw. sollte man auch, um eine erhöhte Sicherheit zu gewährleisten, hier am Beispiel von BBCode:
if(preg_match("/[img].*(javascript:|vbscript:|about:).*[/img]/siU",$Text))
{
$imgsearch = "/[img].*(javascript:|vbscript:|about:).*[/img]/siU";
$imgreplace = "";
$Text = preg_replace($imgsearch, $imgreplace, $Text);
}
Das Problem mit Unicode sollte durch das saubere Ersetzen der Sonderzeichen geklärt werden.
Eine noch viel größere Gefahr ist jedoch das Ausführen von User-Code durch eine Serverseitige Programmiersprache, d.h. dass der Code von PHP, ASP, usw. ausgeführt und verarbeitet wird.
Der dabei wohl bekannteste "Trick" ist die MySQL-Injection. Dabei wird, ähnlich wie bei dem "ausbrechen" aus (x)HTML-Tags ein SQL-String unterbrochen und durch Usereigene Angaben erweitert. Wenn der SQL-String also z.B. so aussieht:
SELECT * FROM user WHERE name='$_GET["name"]';
... dann könnte man die Variable $_GET["name"] z.B. so füllen:
name'; DELETE FROM user WHERE 1='1
... sodass am Ende dieser zusammengesetzte String entsteht:
SELECT * FROM user WHERE name='name'; DELETE FROM user WHERE 1='1';
Die Gute Nachricht ist, dass bei Aktuellen PHP-Versionen ein addslashes() automatisch bei jedem User-Request ausgeführt wird, sodass alle einfachen und doppelten Anführungszeichen automatisch "escaped" werden, also ' zu ' und " zu " wird.
Außerdem wurde mit PHP5 die Funktion mysqli_query() eingeführt, die bloß noch eine einzelne Abfrage zulässt.
Ansonsten empfiehlt es sich jedoch trotzdem auf jedem Request, der von MySQL verarbeitet werden soll, die Funktion mysql_real_escape_string() anzuwenden.
Genauso verhält es sich auch mit durch eval() ausgeführten Code, wobei da normalerweise addslashes() genügen sollte.
Sicherlich deckt dieser kleine Artikel jetzt nicht alle Methoden des Cross-Site-Scripting ab, aber doch wohl die, die sich auf einfache Art verhindern lassen, trotzdem aber noch viel zu oft praktikabel sind. An dieser stelle sollte auch klar sein, warum in fast keinem Forum das direkte Verwenden von (x)HTML-Code erlaubt ist. Zwar kann man mit strip_tags() auch gezielt Tags filtern, 100%-iger Verlass ist darauf jedoch keineswegs und das Ganze sollte sehr genau überdacht werden.