Sichere Java-Webanwendungen, Teil 1: Cross-Site Scripting

Know-how  –  2 Kommentare

Viele Java-Webanwendungen enthalten auch heute noch kritische Sicherheitslöcher, für die es seit Jahren praktikable Gegenmaßnahmen gibt. Die Bedrohungen und Konsequenzen von Cross-Site Scripting, Cross-Site Request Forgery & Co. sind den meisten Java-Entwicklern zu wenig bekannt. Zeit für mehr Aufklärung.

Dieser Artikel ist der erste einer Serie rund um die Entwicklung sicherer Webanwendungen mit Java. Folgeartikel werden sich unter anderem um die Themen Cross-Site Request Forgery (CSRF) und die Verwendung von Third-Party-Bibliotheken in Webanwendungen drehen.

Cross-Site Scripting (XSS) hat in den meisten Fällen zum Ziel, einem Angreifer Zugriff auf die Session-ID eines anderen Benutzers zu ermöglichen. Mit dieser ID kann der Angreifer sich anschließend gegenüber der Webanwendung als dieser Benutzer ausgeben und in dessen Namen zugelassene Aktionen ausführen.

Die Folgen eines XSS-Angriffs können immens sein, die Einstufung der Attacke in den aktuellen OWASP Top 10 von 2013 auf Platz 3 ist damit mehr als gerechtfertigt. Wer sich aber näher mit dem Thema XSS beschäftigt, entdeckt unterschiedliche Varianten, Ursachen und Gegenmaßnahmen. Unabhängig von der konkreten Variante zielt ein XSS-Angriff zwar immer auf den Benutzer beziehungsweise dessen Browser. Der Weg dorthin unterscheidet sich aber je nach Variante. Erschwerend lassen sich die unterschiedlichen Varianten kombinieren und damit einfache Schutzmaßnahmen eventuell austricksen.

Bei Stored XSS handelt es sich um eine serverseitige persistente XSS-Variante. Dabei gelingt es einem Angreifer, XSS-Schadcode (dazu später mehr) in der Webanwendung – in der Regel in der Datenbank – zu speichern. Dazu verwendet der Angreifer meist einen der normalen Eingabekanäle der Webanwendung, beispielsweise ein Formular mit unzureichender Eingabevalidierung. Der so übertragene Schadcode wird gespeichert und beim nächsten Aufruf durch einen anderen Besucher mit den anderen ungefährlichen Daten ausgeliefert. Der XSS-Schadcode landet im Browser des Benutzers und wird dort ausgeführt.

Die verbreitetste Variante wird als Reflected XSS bezeichnet. Hierbei schiebt der Angreifer den ausgewählten Benutzern beispielsweise per E-Mail einen mit JavaScript manipulierten Link unter. Der im Link verborgene Schadcode wird beim Klick darauf vom Benutzer selbst zur anzugreifenden Webanwendung übermittelt, gelangt in deren Antwort wieder zurück zum Benutzer und wird wiederum in dessen Browser ausgeführt. Auch wenn Reflected XSS den Schadcode nicht in der Webanwendung speichert, handelt es sich dennoch um einen serverseitigen Angriff.

DOM Based XSS weist deutliche Unterschiede zu den vorherigen Varianten auf. Allein schon dessen Alias "clientseitiges XSS" zeigt, dass dieser nichtpersistente Angriff anders ist. Der XSS-Schadcode stammt dabei aus einem normalerweise harmlosen URL-Parameter, der bei der erwarteten Verwendung zum Beispiel die Währung einer Webanwendung festlegt:

http://www.sample.de?lang=German

Anstatt dieses ungefährlichen Werts übermittelt ein Angreifer JavaScript-Schadcode, den die Webanwendung clientseitig im JavaScript ausliest und direkt verwendet, beispielsweise über die document.location. Das Backend der Webanwendung hat dabei keinerlei Kontrolle über den Parameter und bekommt von dessen Manipulation nichts mit. Das Ergebnis des Angriffs ist aber wiederum die Ausführung des XSS-Schadcodes im
Browser des Benutzers.

Die Hauptursache von Cross-Site Scripting ist in den vorigen Abschnitten angeklungen: Eingabedaten werden ausgeführt und nicht nur angezeigt. Im HTML-Umfeld sorgen die bekannten spitzen Klammern < und > für die Ausführung des Inhalts.

Korrekterweise müssten diese aber vom Java-Code durch &lt; und &gt; ersetzt und damit an der Ausführung gehindert werden. Ein

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

würde damit nicht zur Anzeige eines Dialogs samt Session-ID führen, sondern den Text wie jeden anderen auch im Browser anzeigen:

&lt;script&gt;alert(document.cookie)&lt;/script&gt;

Fehlendes Output Escaping ist damit die Hauptursache für XSS. Gleichzeitig fehlt zumindest an einer (meist allerdings an mehreren oder gar allen) Eingabemöglichkeit der Webanwendung eine korrekte und vollständige Validierung sämtlicher Benutzereingaben. Bereits hier könnte die Webanwendung ungültige Daten abweisen und diese somit überhaupt nicht ins System gelangen lassen.

Wie eingangs erwähnt hat ein XSS-Angriff meist zum Ziel, die Session-ID von authentifizierten Benutzern der Webanwendung zu übernehmen. Dazu wird die ermittelte ID einfach an eine auf den Server des Angreifers verweisende URL angehängt und diese per JavaScript aufgerufen. Innerhalb der Gültigkeit der Session – also bis ein Timeout zuschlägt oder der Anwender sich abmeldet – kann sich der Angreifer damit als Benutzer ausgeben. Alle Operationen, die keine Passworteingabe erfordern, lassen sich nun von ihm ausführen. Das Passwort selbst ist dem Angreifer nicht bekannt; ein Rückschluss aus der Session-ID funktioniert nicht. Sollte die Webanwendung bei einer Passwortänderung allerdings nicht das aktuelle abfragen, kann der Angreifer einfach ein neues vergeben und so den legitimen Benutzer aussperren.

Möglich sind aber auch Angriffe zur Verunstaltung der Webanwendung (Site Defacement). Dabei wird beispielsweise ein vom Angreifer kontrolliertes Login-Formular in die Seite integriert. Anwender übermitteln damit ihre vollständigen Benutzerdaten an den Angreifer. Auch Redirects und Phishing-Angriffe werden so mit XSS möglich. Und schließlich unterwandert eine XSS-Verwundbarkeit jeden Schutz vor CSRF-Angriffen (Cross-Site Request Forgery) in der Webanwendung (dazu mehr in einem späteren Artikel).