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:
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.
Ü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
Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 5
Vorschau anzeigen