Nachdem Charlie Belmer in seinem Blogpost „Why is This Website Port Scanning me?“ als Erster darüber berichtet hat, wurde das Thema von vielen Newssites aufgegriffen. Zum Beispiel hat Golem darüber berichtet und bei Heise gibt es noch mehr Hintergrundinformationen. Da das Thema eBay Portscan gerade viel diskutiert wird, möchte ich hier den technischen Hintergrund erläutern. Zusätzlich zeige ich, wie man sich effektiv dagegen schützen kann.
eBay Portscan
Der Portscan von eBay ist in JavaScript realisiert und verwendet die Websockets Technologie. Er ist eigentlich kein typischer Portscan, da mithilfe von JavaScript und Websockets nicht die Dienste angesprochen werden können. Es wird nur überprüft, ob auf dem entsprechenden Port ein Dienst läuft. Aus der Zeitdauer für die Rückmeldung kann abgeleitet werden, ob ein Dienst aktiv ist. Ein aktiver Dienst liefert schneller eine Rückmeldung als wenn kein Dienst aktiv ist. Daher ist es ein ungefähres Abklopfen der Ports, ohne dass Informationen über die Dienste gesammelt werden können.
Solch ein „Scan“ kann mit nur wenigen Zeilen in JavaScript realisiert werden. Diese Methode wurde bereits 2016 von Tom Gallagher im Vortrag „Port Scanning and WebSockets“ vorgestellt. Das folgende Beispiel zeigt die Untersuchung des Port 80:
var s = new WebSocket("ws://127.0.0.1:80"); s.start = performance.now(); s.onerror = function() {console.log("Port 80 " + (performance.now() – s.start) + " ms");}; s.onopen = function() {console.log("Port 80 " + (performance.now() – s.start) + " ms");};
Lokaler Zugriff
Wie das Beispiel des eBay Portscanner zeigt, ist ein lokaler Zugriff mit JavaScript möglich. Dieser beschränkt sich aber nicht nur auf den eigentlichen Rechner, der die Website aufgerufen hat. Da das JavaScript lokal auf dem Client ausgeführt wird, kann der Zugriff auf das lokale Netzwerk ausgedehnt werden. Allerdings ist dies nur sehr eingeschränkt möglich, da bei einer quellübergreifenden Anfrage die Cross-Origin Regelung greift. Dies sorgt dafür, dass ohne explizite Zustimmung bzw. Konfiguration keine Anfrage zu einer fremden Domain bzw. IP-Adresse ausgeführt werden kann.
FRITZ!Box Beispiel
Am einfachsten ist dieser Vorgang am Beispiel der FRITZ!Box erklärt. Die FRITZ!Box der Firma AVM ist ein Router für den Internetzugang und sehr verbreitet, daher eignet sie sich gut für das Beispiel. Die Standard IP-Adresse ist die 192.168.178.1 im lokalen Netzwerk. Als Nächstes wird ein Element auf der Startseite benötigt, um die Anwesenheit zu überprüfen. Dazu habe ich mich für das Logo entschieden, das über die URL http://192.168.178.1/css/rd/logos/logo_fritzDiamond.svg aufrufbar ist.
Dieses Bild wird normal per HTML eingebunden. Dann werden zwei Funktionen für die Callback-Funktionen onload (Ladevorgang erfolgreich abgeschlossen) und onerror (Ladevorgang war nicht möglich) definiert. Ist der Ladevorgang erfolgreich, ist eine FRITZ!Box vorhanden. Hier der Beispielcode:
<script> function fritzboxPos(){alert('Fritzbox ;-)');} function fritzboxNeg(){alert('keine Fritzbox');} </script> <img src="http://192.168.178.1/css/rd/logos/logo_fritzDiamond.svg" onload="fritzboxPos()" onerror="fritzboxNeg()">
Wird der Code in einer Website mit HTTPS eingebunden, greifen bei einigen Webbrowsern die Sicherheitsfunktion, dass alle Anfragen ausschließlich über HTTPS erfolgen. Die FRITZ!Box ist zwar über HTTPS erreichbar, aber nur mit einer ausdrücklichen Zustimmung wegen dem selbst zertifizierten SSL-Zertifikat. Daher schlägt hier dann der Test fehl.
Gegenmaßnahmen
Diese Art von Zugriff lässt sich sehr einfach im Webbrowser mit dem Werbeblocker uBlock Origin blockieren. Er ist für Chromium, Firefox, Microsoft Edge und Safari (macOS) verfügbar. Die Filterregeln zum Blocken von lokalen Verbindungen inkl. Websockets, und damit zum unterbinden der Portscans, sind im Privacy Handbuch beschrieben.
Um die Zugriffe auf den eigenen Rechner zu unterbinden, müssen die folgenden Regeln in uBlock Origin eingetragen werden:
||localhost^$important,third-party ||127.0.*^$important,third-party ||[::1]^$important,third-party
Die drei Einträge stellen unterschiedliche Arten von Schreibweisen dar. Der Name localhost ist der definierte Domainnamen der virtuellen IP-Adresse auf dem momentan genutzten Rechner. Die IP-Adresse 127.0.0.1 repräsentiert ebenfalls den eigenen Rechner und ::1 stellt die IPv6 Schreibweise dar.
Zusätzlich sollte noch der Zugriff auf das lokale Netzwerk geblockt werden. Dazu muss diese vierte Zeile eingetragen werden. Gegebenenfalls muss hier noch die IP-Adresse angepasst werden.
||192.168.*^$important,third-party