Sicherheitslücken kombinieren

Sicherheitslücken kombinieren

Harmlose Sicherheitslücken können für versierte Angreifer sehr nützlich und in manchen Fällen sogar entscheidend für einen erfolgreichen Angriff sein. Mit Full Path Disclosure lässt sich beispielsweise der vollständige Pfad aus Fehler- und Warnmeldungen lesen. Viele fragen sich, was Angreifer denn schon mit einem einfachen Pfad angangen können. Dabei sind es oft wertvolle Informationen - zum Beispiel, um Local File Inclusion Sicherheitslücken auszunutzen oder um mehr über die interne Verzeichnis-Struktur zu erfahren.

Manchmal kommt auch es vor, dass SQL Injections für Angreifer unbrauchbar sind. In Kombination mit anderen Sicherheitslücken, wie XSS, XSRF oder aber auch Social Engineering kann sich das Blatt sehr schnell wenden.

Gefahrenstufen bei Sicherheitslücken

Sicherheitslücken werden häufig in Gefahrenstufen unterteilt.

Das könnte zum Beispiel so aussehen:
Gefahrenstufen

Remote Sicherheitslücken, mit denen sich Angreifer Root-Zugriff auf einem System verschaffen können, werden als "hochkritisch" eingestuft.

Sicherheitslücken, die es ermöglichen System-Befehle oder serverseitigen Code auszuführen, werden in der Regel als kritisch eingestuft.

Als nicht bzw. weniger kritisch gehören zum Beispiel Information Disclosure Sicherheitslücken, mit denen Angreifer Informationen über das Zielsystem erhalten.

Wie aus "harmlose" Sicherheitslücken "hochkritische" werden

Ich habe ja schon öfter erwähnt, dass XSS-Lücken allgemein nicht als harmlos einzustufen sind. Können XSS-Lücken auch zur Kompromittierung eines Systems führen? Einige würden sich über diese Frage sicherlich amüsieren.

Dabei ist es gar nicht mal so unrealistisch. Natürlich geht sowas nicht mit XSS alleine, aber in Kombination mit anderen Sicherheitslücken.

Das gleiche gilt auch für harmlose Sicherheitslücken - wie zum Beispiel Information Disclosure, HTML-Injection oder Cross-Site Authentication (XSA).

Proof-Of-Concept

Da solche Situationen unterschiedlich sein können und man kein allgemeines Beispiel nennen kann, werde ich das ganze anhand von zwei Szenarien demonstrieren.

Das zweite Szenario ist ein "Real-World" Beispiel - basierend auf einem Source Code Audit, den ich vor kurzem bei einem CMS gemacht habe.

Szenario 1 - Von XSS zum Root-Zugriff

Ein Angreifer findet eine XSS-Lücke in einer Forensoftware. Dort werden Cookies verwendet, um den Benutzern die Möglichkeit zu bieten längere Zeit angemeldet zu bleiben.

In diesen Cookies werden die Session-IDs übermittelt. Wenn ein Benutzer eingeloggt ist, die Seite verlässt und später wiederkommt, kann der Benutzer anhand der vom Browser übermittelten SID identifiziert werden - der Benutzer bleibt also eingeloggt.

Der Angreifer präpariert nun einen Link oder eine Webseite so, dass die Cookie-Informationen mithilfe der XSS-Lücke unbemerkt an den Angreifer übermittelt werden.

Diesen Link schickt er an einem Admin des Forums. Somit erhält er die SID des Admins und kann sie in seine eigene Cookie-Datei eintragen. Wenn der Angreifer nun die Seite besucht, wird die gültige SID erkannt und der Angreifer ist als Admin eingeloggt. Er hat die Session also übernommen. Diese Angriffstechnik ist auch als Session Hijacking bekannt.

Der Angreifer hat nun Adminrechte und kann einiges mehr anstellen. In diesem Beispiel kann der Angreifer im Admin-Bereich Templates editieren und dort PHP Code injizieren.

Dadurch verschafft er sich schonmal Zugriff auf dem Webserver und hat Zugriff auf sämtliche Dateien, die dort liegen. Die Server-Software bzw. OS Version ist nicht auf dem neuesten Stand und der Angreifer nutzt ein Local Root Exploit, mit dem er sich Root-Zugriff auf dem Server verschafft. Ziel erreicht.

Einige denken jetzt vielleicht "als ob das so einfach ist" - ist es auch oft nicht. Aber aus eigenen Erfahrungen kann ich sagen, dass soetwas sehr schnell Realität werden kann.

Szenario 2 - Die scheinbar unbrauchbare SQL Injection

Dieses Szenario ist wie gesagt ein "Real-World" Beispiel aus einem CMS, das ich hier aus Sicherheitsgründen nicht nennen werde. Den Code habe ich etwas abgeändert.

Das verwundbare Script (vereinfachtes Snippet):

<?php
  // ...

  function getbrowser($useragent)
  {
    if(preg_match("=MSIE ([0-9]{1,2}).[0-9]{1,2}=", $useragent, $browser))
      return "Internet Explorer ".$browser[1];
    elseif(preg_match("=^Mozilla.*Firefox\/(.*)$=", $useragent, $browser))
      return("Firefox ".$browser[1]);
    elseif(preg_match("=Mozilla/5.[0-9]{1,2}=", $useragent))
      return "Netscape Navigator 6";
    elseif(preg_match("=Mozilla/([0-9]{1,2}).[0-9]{1,2}=", $useragent, $browser))
      return "Netscape Navigator ".$browser[1];
    else
      return 0;
  }

  function getreferrer($referrer)
  {
    if(!empty($referrer))
    {
      $urlpart = parse_url($referrer);
      $url = 'http://'.$urlpart['host'].$urlpart['path'];
      return $url;
    }
    else
      return 0;
  }

  $ip = $_SERVER['REMOTE_ADDR'];
  $br = getbrowser($_SERVER['HTTP_USER_AGENT']);
  $ref = (isset($_SERVER['HTTP_REFERER']) ? getreferer($_SERVER['HTTP_REFERER']) : '');

  mysql_query("INSERT INTO prefix_table (browser,ip,ref)
               VALUES('".$br."','".$ip."','".$ref."')");

  // ...
?>

Nun analysieren wir mal eben diesen Code.

Die IP-Adresse, der Browser und der Referrer werden in Variablen gespeichert. Anschließend werden die Werte dieser Variablen mit einer INSERT SQL-Anweisung in eine Datenbank-Tabelle eingefügt.

Wenn die Variablen nicht ausreichend validiert werden, ist SQL Injection möglich.

Die Variable »ip« kann schonmal keine Benutzereingaben enthalten, da der Wert von $_SERVER['REMOTE_ADDR'] nicht verändert werden kann.

Für den Browser und den Referrer gibt es eigene Funktionen zur Validierung. Moment ... habe ich Validierung gesagt?

Bei der Funktion getreferrer wird der Wert von $_SERVER['HTTP_REFERER'] nur einmal durch die Funktion parse_url() gejagt und anschließend werden die ersten beiden Teile (Host und Pfad) zurück gegeben.

Die Funktion parse_url() ist allerdings nicht zur Validierung von URLs gedacht, sondern nur zum Parsen von URLs.

Diese Funktion ist nicht dazu gedacht, einen gegebenen URL zu validieren, sondern es gliedert einen URL in die unten aufgeführten Bestandteile. Unvollständige URLs werden als Parameter akzeptiert, parse_url() versucht, sie bestmöglich zu analysieren. Quelle: php.net

Die Variable »ref« kann also beliebige Benutzereingaben enthalten, da die Funktion parse_url() keine Filterung / Validierung ermöglicht.

Wie sieht's mit der Funktion getbrowser aus? Dort wird der User-Agent besser validiert, allerdings gibt es einen entscheidenen Fehler in folgender Zeile:

elseif(preg_match("=^Mozilla.*Firefox\/(.*)$=", $useragent, $browser))

Hier wird der User-Agent mit einem "Muster" bzw. einem Regulären Ausdruck verglichen.

Die Funktion liefert den Wert zurück, der in den Klammern steht. In diesem Fall: .*

Die Angabe .* bedeutet, dass jedes beliebige Zeichen angegeben werden kann. Und da der Wert von $_SERVER['HTTP_USER_AGENT'] im Browser verändert werden kann, ist diese Validierung nicht sicher.

Folgender String würde zum Beispiel funktionieren:

Mozilla1Firefox/foo'

Durch das Apostroph kann aus dem String ausgebrochen werden und eigene Werte können in die Datenbank-Tabelle eingefügt werden. Es handelt sich hierbei um eine klassische INSERT SQL-Injection.

Ich möchte jetzt aber nicht zu sehr auf SQL Injection eingehen - das werde ich in einem anderen Artikel noch ausführlich. Hier geht es nur darum das Passwort des Admins in die Datenbank-Tabelle zu injizieren. Also kurz und knapp - hier die SQL Injection, die ein Angreifer als User-Agent definieren kann, um das Passwort des Admins (anstatt den Referrer) in die Datenbank-Tabelle einzufügen:

Mozilla1Firefox/foo','127.0.0.1',(select pass from prefix_user limit 0,1))-- f

Folgende SQL-Anweisung wird nun ausgeführt:

INSERT INTO prefix_table (browser,ip,ref)
VALUES('Mozilla1Firefox/foo','127.0.0.1',(SELECT pass FROM prefix_user LIMIT 0,1))

Das Passwort wird also in der Datenbank-Tabelle eingefügt. Allerdings wird dieser Eintrag nirgendwo auf der Seite wieder ausgegeben und es existiert keine SQL-Lücke in einer SELECT-Abfrage. Wie kommt der Angreifer nun an das Passwort?

Im Admin-Bereich gibt es eine Besucherstatistik. Dort werden diese Inhalte ausgegeben. Normalerweise wird hier zum Beispiel der Referrer ausgegeben - da der Angreifer allerdings das Passwort in die Tabelle injiziert hat, wird das Passwort des Admins ausgegeben. Da der Angreifer auch JavaScript Code in die Tabelle injizieren kann und im Admin-Breich die Ausgabe nicht gefiltert wird, kann das Passwort mithilfe eines injizierten JavaScript Codes an den Angreifer gesendet werden. Hier wird also XSS genutzt, um die SQL Injection brauchbar zu machen und das Passwort auszulesen.

Fazit

Kreative und versierte Angreifer können Sicherheitslücken kombinieren, um einen erfolgreichen Angriff zu ermöglichen. Eine einfache XSS-Lücke könnte zum vollständigen Root-Zugriff führen. Eine unbrauchbare SQL Injection wird in Kombination mit XSS brauchbar. Harmlose Sicherheitslücken könnten das Einstiegstor für Angreifer sein.

Dir hat der Artikel gefallen? Dann abonniere doch einfach den RSS-Feed, damit du immer auf dem Laufenden bleibst und über neue Einträge kostenlos informiert wirst.

Diesen Artikel weiterempfehlen:
TwitterFacebookDeliciousTechnoratiMister WongWikio

2 Reaktionen zu “Sicherheitslücken kombinieren”

Kommentar hinterlassen