Skip to content

XSS-Angriffe, Teil 5: Ein Portscan (nicht nur) im LAN

Über XSS lassen sich in den Browser zum Beispiel Informationen einschleusen oder Cookies und Tastendrücke sowie Zugangsdaten und die History ausspähen. Viel mehr ist da auch nicht zu holen. Aber der Browser kann auch als Sprungbrett ins lokale Netz des Opfers dienen. Und welche Rechner da zu finden sind verrät ein

JavaScript-Portscan

In der vorherigen Folge habe ich ja schon beschrieben, wie sich mit JavaScript ein Ping-Befehl realisieren lässt. Und mit diesem Ping lässt sich dann ein Portscan im lokalen Netz realisieren, mit dem dann zum Beispiel nach Webservern gesucht werden kann.

Dazu muss zunächst festgestellt werden, ob eine HTTP-Verbindung zustande gekommen ist oder nicht. Dazu wird ein iframe in Verbindung mit einem onLoad()-Event und einem Timer verwendet. Das src-Attribut des iframes wird gesetzt und der Timer gestartet. Läuft auf dem gefundenen Host ein Webserver, wird der onLoad()-Event ausgelöst. Ist kein Webserver erreichbar, wird der Timer-Event ausgelöst.

Nachdem so erst Hosts und danach Webserver ermittelt werden können, stellt sich die Frage, welcher Webserver oder welche Webanwendung genau gefunden wurde. Für das sogenannte Fingerprinting wird wieder ein Image-Objekt mit einem onLoad()-Event verwendet. Damit wird nach für Webserver/Webanwendungen typischen Bildern gesucht, wobei nur noch zwei mögliche Ergebnisse vorkommen können: Ein angefordertes Bild wird geladen oder es wird nicht geladen. Konnte das Bild geladen werden, werden seine Dimensionen mit den bekannten Werten verglichen. Stimmen sie überein, wird davon ausgegangen, das der Webserver erfolgreich identifiziert wurde. Stimmen sie nicht überein oder konnte das Bild nicht geladen werden, wird mit dem nächsten Bild weiter gemacht.

Statt nach Bildern kann auch zum Beispiel nach typischen CSS- oder JavaScript-Dateien gesucht werden. Typische Bilder sind zum Beispiel für Microsofts IIS das 36x48 Pixel große Bild /pageerror.gif oder für Apache-Webserver das 20x22 Pixel große Bild /icons/c.gif. Für die Erkennung der webbasierten Konfigurationsoberflächen von Netzwerkgeräten wie zum Beispiel Routern können meist spezifische Bilder der jeweiligen Hersteller verwendet werden ("Wo XYZ draufsteht, ist auch ein XYZ-Icon drin").

Das Prinzip ist also verblüffend einfach. Trotzdem wurde das Verfahren erst 2006 von den SPI Labs im Paper "Detecting, Analyzing, and Exploiting Intranet Applications using JavaScript" (Kopie auf archive.org) vorgestellt. Das dazu gehörende Beispiel ist ebenfalls auf archive.org verfügbar und funktioniert nach wie vor, wie das folgende Bild beweist:

JavaScript-Portscanner der SPI Labs auf archive.org
Abb. 1: JavaScript-Portscanner der SPI Labs auf archive.org

Inzwischen gibt es weitere JavaScript-Portscanner im Web, zum Beispiel eine einfache Variante bei GNUCITIZEN (an dessen Sourcecode sich das folgende Beispiel anlehnt und der in einer verbesserten Version Bestandteil der AttackAPI von GNUCITIZEN ist) und eine auf HTML5 basierende Version bei den Attack and Defense Labs (auf die ich später noch zurück komme).

Ein einfacher Portscanner für einen Host

Der Portscanner könnte zum Beispiel so implementiert werden:

PortScanner = {};

PortScanner.scanPort = function (callback, host, port, timeout) {
   var timeout = (timeout == null)?100:timeout;
   var img = new Image();
   
   img.onerror = function () {
      if (!img) return;
      img = undefined;
      callback(host, port, 'open');
   };
   
   img.onload = img.onerror;
   img.src = 'http://' + host + ':' + port;
   
   setTimeout(function () {
      if (!img) return;
      img = undefined;
      callback(host, port, 'closed');
   }, timeout);
};

Die Funktion scanPort() ist für den eigentlichen Portscan zuständig. Wie bereits beschrieben wird ein neues Image-Objekt mit onLoad()- und onError()-Event sowie einem Timer erzeugt, dessen src-Attribut auf den zu prüfenden Host und Port gesetzt wird. Außer Host, Port und gewünschten Wert für den Timer wird eine Callback-Funktion für die Ausgabe des Ergebnisses übergeben. Bei Bedarf könnte auch nach einem bestimmten Bild gesucht werden, dann müsste allerdings der onLoad()-Event passend erweitert werden.

Möchte man mehrere Ports eines Hosts mit einem Aufruf prüfen, ist eine weitere Funktion notwendig:

PortScanner.scanHost = function (callback, host, ports, timeout) {
   for (index = 0; index < ports.length; index++)
      PortScanner.scanPort(callback, host, ports[index], timeout);
};

scanHost() wird unter anderem. mit einem Array mit den zu prüfenden Ports aufgerufen. Das Array kann beim Aufruf durch split(',') aus einer zum Beispiel über ein Formular übergebenen Liste durch Kommata getrennter Ports erzeugt werden. Insgesamt könnte ein Portscanner für den Scan eines oder mehrerer Ports eines einzelnen Rechners dann so aussehen:

<form>
Ziel: <br>
<input type="text" name="host">
(Domainname oder IP-Adresse) <br>
Ports: <br>
<input type="text" name="ports" value="80">
(Es kann auch eine Reihe von Ports angegeben werden, z.B. 80,81,8080,1024)<br>
Timeout: <br>
<input type="text" name="timeout" value="1000">
(Der Timeout-Wert muss evtl. erhöht werden) <br>
Ergebnis: <br>
<textarea id="ergebnis" name="ergebnis" rows="7" cols="50"></textarea><br>
<input class="button" type="button" value="scan" onClick="javascript:scanne(this.form)">
</form>

<script>
PortScanner = {};

PortScanner.scanPort = function (callback, host, port, timeout) {
   ...
};

PortScanner.scanHost = function (callback, host, ports, timeout) {
   ...
};

var ergebnis = document.getElementById('ergebnis');
function callback(host, port, status) {
   ergebnis.value += host + ':' + port + ' ' + status + "\n";
};

function scanne(form) {
   PortScanner.scanHost(callback, form.host.value, form.ports.value.split(','), form.timeout.value);
};
</script>

Ich hätten Ihnen den Scanner gerne als funktionsfähige Demo bereit gestellt, aber dann besteht die Gefahr, dass mal wieder ein SchlangenölherstellerAntivirenhersteller harmlos und böse nicht unterscheiden kann und mein Blog als "gefährlich" brandmarkt. Wenn nicht sogar schon die obigen Beispiele dafür ausreichen, denn ich vermute nach wie vor, dass damals nicht ausführbarer Beispiel-Code für Drive-by-Infektionen als ausführbar und damit "gefährlich" erkannt wurde.

Sie können sich eine funktionsfähige Demo aber ganz einfach selbst zusammen stellen, indem Sie den Code aus dem letzten Beispiel in eine HTML-Datei kopieren und den Code für die beiden Funktionsaufrufe von oben hinein kopieren.

In der nächsten Folge wird dieser einfache Portscanner für einen Host zu einem Portscanner für einen IP-Adressbereich erweitert.

Carsten Eilers


Übersicht über alle Artikel zum Thema

Cross-Site Scripting im Überblick, Teil 1: Reflektiertes XSS
Cross-Site Scripting im Überblick, Teil 2: Persistentes XSS
Cross-Site Scripting im Überblick, Teil 3: Der MySpace-Wurm Samy
Angriffe über Cross-Site Scripting: Der Sourcecode des MySpace-Wurms Samy
Cross-Site Scripting im Überblick, Teil 4: DOM-basiertes XSS
Cross-Site Scripting im Überblick, Teil 5: Resident XSS
XSS-Angriffe, Teil 1: Informationen einschleusen
XSS-Angriffe, Teil 2: Cookies und Tastendrücke ausspähen
XSS-Angriffe, Teil 3: Zugangsdaten ausspähen
XSS-Angriffe, Teil 4: Ein Blick in die History, und dann auf ins LAN!
XSS-Angriffe, Teil 5: Ein Portscan (nicht nur) im LAN
XSS-Angriffe, Teil 6: Ein verbesserter Portscanner
XSS-Angriffe, Teil 7: Hindernisse beim JavaScript-Portscan beseitigen
XSS-Angriffe, Teil 8: Ein Portscan mit WebSockets oder Cross-Origin Requests
XSS-Angriffe, Teil 9: Der Router im Visier
XSS-Angriffe, Teil 10: Weitere Angriffe auf den Router
XSS-Angriffe, Teil 11: Unerwünschtes Firmware-Update für den Router
XSS-Angriffe, Teil 12: Browser-basierte Botnets
XSS-Angriffe, Teil 13: Fortgeschrittene Angriffe
XSS-Angriffe, Teil 14: Das Browser Exploitation Framework BeEF

Trackbacks

Dipl.-Inform. Carsten Eilers am : Filet-o-Firewall - ein neuer browserbasierter Angriff auf die Firewall

Vorschau anzeigen
Jetzt habe ich gestern doch glatt vergessen, den Text online zu stellen. Also mit kurzer Verzögerung: Wie angekündigt geht es ab dieser Folge erst mal wieder um aktuellere Themen. Den Anfang machen Schwachstellen in und Angriffe au

Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 5

Vorschau anzeigen
Die Beschreibung der gefährlichsten Schwachstellen in den Geräten des IoT geht weiter. In der Liste der Top IoT Vulnerabilities von OWASP sind wir immer noch bei Platz 1, dem &quot;Insecure Web Interface&quot;. Aber wenigstens sind wir beim zweiten