AQUANTUM GmbH

Web Application Security (Teil 2)

Dies ist der zweite Teil unserer Reihe zum Thema “Web Application Security” in Anlehnung an die Top 10 Sicherheitsrisiken für Webanwendungen des Open Web Application Security Projects (OWASP).

2. Cross-Site Scripting (XSS)

Cross-Site Scripting (abgekürzt mit “XSS”) bezeichnet das Einschleusen von clientseitig ausführbarem Code in eine Webanwendung. Der eingeschleuste Code wird im Browser anderer Anwender ausgeführt und besteht in den meisten Fällen aus JavaScript. Auf diese Weise lassen sich verschiedenste Angriffe durchführen:

  • Das Mitschneiden von Tastatureingaben auf der verwundbaren Website.
  • Die Übernahme von Sitzungen (z.B. als eingeloggter Administrator der Website) durch Auslesen der Session-Cookies.
  • Das Ausführen beliebiger Aktionen im Kontext des angemeldeten Benutzers (z.B. das Hinzufügen eines neuen Administrators).

Auch mit eingeschleustem HTML+CSS lassen sich Angriffe durchführen, z.B. durch das Überlagern eines Passwort-Formulars mit einem eigenen Formular, welches die Formulardaten an den eigenen Server sendet.

Wie entstehen Cross-Site Scripting Lücken?

Cross-Site Scripting Lücken entstehen ähnlich wie Injection Lücken durch die ungeprüfte Übernahme von Benutzerparametern. XSS-Code wird jedoch erst bei der Ausgabe und Interpretation durch den Browser zur Gefahr. XSS-Lücken entstehen also durch die ungefilterte Ausgabe von Benutzerparametern:

Für XSS anfälliger PHP Code:
<?php
setcookie('secret', '123456');
echo 'Hallo, '.$_GET['name'].'!';
?>

Für XSS anfälliges Ruby on Rails Template:
<% cookies[:secret] = { :value => '123456' } %>
<%= 'Hallo, '+params[:name].to_s+'!' %>

Der PHP-Code und das Rails Template ermöglichen das Einschleusen von JavaScript-Code über den Parameter “name”. Der folgende Link enthält als Wert für “name” URL-kodierten JavaScript-Code, der den Benutzer von localhost auf einen anderen Server weiterleitet und den Inhalt des von localhost gesetzten Cookies als Parameter übergibt:

XSS Example Link

Natürlich kann ein Angreifer keinen Schaden anrichten, so lange er selbst diese präparierte URL aufruft. Bindet er jedoch die URL als Quelle eines iframes in einer eigenen Webseite ein, wird der im Parameter “name” übergebene JavaScript-Code bei jedem Besucher der präparierten Webseite im Kontext der eigentlich vertrauenswürdigen Website ausgeführt. Durch Cross-Site Scripting Lücken ist es also möglich, die Same Origin Policy der Browser zu umgehen.

Alle Benutzervariablen, die ungefiltert ausgegeben werden, sind potentielle Cross-Site Scripting Lücken. Dazu zählen z.B. Fehlermeldungen in Formularparametern, Suchergebnisse und Datenbankinhalte wie Profilinformationen in Online-Communities, Forenbeiträge oder Benutzerkommentare. Persistent gespeicherte und ungefiltert ausgegebene Benutzerparameter erlauben die Ausführung von JavaScript-Code im Browser anderer Anwender ohne die Notwendigkeit, eigene Webseiten zu präparieren.

Wie kann ich eine Anwendung vor Cross-Site Scripting schützen?

Um eine Anwendung vor Cross-Site Scripting zu schützen, müssen alle Benutzerdaten vor der Ausgabe gefiltert werden, damit alle Metazeichen des Ausgabekontexts durch entsprechende Zeichenreferenzen ersetzt werden. Das heißt, daß praktisch alle Zeichen ersetzt werden müssen, die vom Browser an der entsprechenden Stelle nicht als Teil einer reinen Zeichenkette interpretiert werden. Im Fall unserer Beispielcodes betrifft das insbesondere die Zeichen “<" und ">“, die mittels der Funktionen htmlspecialchars (PHP) bzw. html_escape (Rails) ersetzt werden können:

Mit Hilfe von htmlspecialchars abgesicherter PHP Code:
<?php
setcookie('secret', '123456');
echo 'Hallo, '.htmlspecialchars($_GET['name']).'!';
?>

Mit Hilfe von html_escape abgesichertes Ruby on Rails Template:
<% cookies[:secret] = { :value => '123456' } %>
<%= 'Hallo, '+h(params[:name].to_s)+'!' %>

Wichtig ist, jeweils den Kontext der Ausgabe zu beachten. Werden Benutzerparameter beispielsweise als Attributwerte eines HTML-Tags ausgegeben, reicht es nicht, nur die Zeichen “<" und ">” zu ersetzen. Das folgende Rails Template ist beispielsweise trotz der Verwendung von html_escape verwundbar, auch wenn dies auf den ersten Blick nicht offensichtlich ist:
<img src='/images/<%=h(params[:img].to_s)%>.png'/>

Übergibt man folgenden Code als Wert für den Parameter “img”, öffnet sich zur Demonstration der XSS-Lücke eine JavaScript-Dialogbox:
'%20onerror=alert(1)%20alt='

In diesem Fall besteht die Lücke darin, das html_escape nur die Zeichen &, >, < und " (Double Quote) filtert, nicht jedoch das Zeichen ‘ (Single Quote), wir aber Single Quotes für die Angabe des HTML-Attributs “src” verwenden. Abhilfe schafft hier die Verwendung von Double Quotes zur Umschließung von HTML-Attributen oder die Verwendung der tag helper Funktion, die automatisch Double Quotes um Attribute setzt und HTML Metazeichen in die entsprechenden Referenzen umwandelt:
<%= tag(:img, { :src => '/images/'+params[:img].to_s+'.png' }) %>

Schwierig wird es, wenn Benutzer die Möglichkeit haben sollen, HTML zur Formatierung ihrer Texte zu verwenden, beispielsweise zur Umsetzung eines Online-RichText-Editors. So ist es nicht möglich, pauschal alle Metazeichen zu ersetzen, da dann auch die erwünschten Formatierungselemente unbrauchbar werden. In diesem Fall ist ein speziell angepasster XSS-Filter notwendig, der erlaubte HTML-Tags und Attribute nicht filtert, gleichzeitig jedoch immun gegen die Vielzahl von XSS-Angriffsvektoren ist. Für Rails Applikationen lassen sich hierfür beispielsweise die Sanitize Helper nutzen.

Sicherheitsregeln

  • Alle Benutzervariablen, die ungefiltert ausgegeben werden, sind potentielle Cross-Site Scripting Lücken.
  • Alle Metazeichen des Ausgabekontexts müssen durch entsprechende Zeichenreferenzen ersetzt werden.
  • Je nach Ausgabekontext (HTML body, HTML attribute, JavaScript, CSS) müssen unterschiedliche Metazeichen ersetzt werden.
  • Benutzervariablen niemals in Script Tags, HTML-Kommentaren, HTML-Attributnamen oder HTML-Tagnamen ausgeben, da innerhalb dieser Kontexte ein XSS-Filter nur schwer bis gar nicht umsetzbar ist.
  • Die XSS Prevention Rules (OWASP) befolgen.
  • Die Vielzahl der XSS-Angriffsvektoren beachten.

Hinterlasse einen Kommentar