From b6ed16173267ea07397be45b8cd3602e7d8a2c37 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Fri, 15 May 2026 14:11:03 +0000 Subject: [PATCH] Add content from: The Tiny UDP Cannon: An Android VPN Bypass --- .../android-applications-basics.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/mobile-pentesting/android-app-pentesting/android-applications-basics.md b/src/mobile-pentesting/android-app-pentesting/android-applications-basics.md index 3b4f21da1d5..903aa5b6310 100644 --- a/src/mobile-pentesting/android-app-pentesting/android-applications-basics.md +++ b/src/mobile-pentesting/android-app-pentesting/android-applications-basics.md @@ -639,6 +639,48 @@ Tools / scripts that speed-up Binder reconnaissance: * [`binder-scanner.py`](https://github.com/adenflare/binder-scanner) – walks the binder table and prints ACLs * Frida shortcut: `Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))` +### 8. Hidden Binder APIs, confused deputies and VPN-lockdown bypasses +A hidden Java API is still reachable when the underlying **Binder transaction is exposed to apps** and the service implementation forgets to perform its own authorisation. A useful triage pattern is: **untrusted app → Binder registration of attacker-controlled state → privileged system component later replays that state**. + +Typical red flags: +* A Binder method accepts a **`ParcelFileDescriptor`**, socket-like object, or raw **`byte[]`** payload from an app. +* The AIDL/service path has **no** `@EnforcePermission`, `enforceCallingOrSelfPermission()`, `checkCallingPermission()`, UID allowlist, or SELinux restriction. +* The privileged side later **recreates the socket or packet** as `system_server`/system UID and sends it on a network chosen from saved metadata. +* The payload is treated as protocol-specific data but the implementation never validates that it really matches the expected frame type. + +Example pattern seen in Android 16 QUIC graceful close abuse: +1. The app enumerates visible networks with `ConnectivityManager.getAllNetworks()` and `getLinkProperties()`. +2. Instead of `Network.bindSocket()` (which enforces VPN lockdown), it creates `new DatagramSocket(new InetSocketAddress(, 0))`. That path reaches the kernel `bind()` syscall, which only checks whether the local IP exists on an interface. +3. A later UDP `connect()` does **not** transmit traffic but helps associate the socket with the physical network `netId`/`SO_MARK`. +4. The app passes the connected socket plus attacker-controlled bytes to a Binder method. +5. When the socket dies, a privileged component recreates the flow and sends the bytes as **UID 1000**, bypassing per-app VPN policy because the policy is enforced against the original app UID, not the privileged deputy. + +Minimal direct-transaction pattern from an app when the SDK method is hidden but the Binder entry point is reachable: +```java +IBinder svc = (IBinder) Class.forName("android.os.ServiceManager") + .getMethod("getService", String.class).invoke(null, "connectivity"); +Parcel data = Parcel.obtain(); +try { + data.writeInterfaceToken("android.net.IConnectivityManager"); + data.writeTypedObject(pfd, 0); + data.writeByteArray(payload); + svc.transact(TXN_REGISTER, data, null, IBinder.FLAG_ONEWAY); +} finally { + data.recycle(); +} +``` + +Practical review workflow: +* Decompile `framework*.jar`, APEX jars and vendor service jars, then map `Stub.onTransact()` cases to method names and parameter types. +* Prioritise transactions that combine **network objects + raw bytes + delayed execution**. +* Check whether the privileged path calls helpers such as `Network.bindSocket()`, `Os.write()`, or creates a fresh `DatagramSocket`/`Socket` using attacker-influenced metadata. +* Compare **kernel-local operations** (`bind()`, UDP `connect()`) with **Android policy-aware wrappers** (`Network.bindSocket()`) because the former may shape metadata without triggering the higher-level policy gate. +* For confirmation, register the state, kill the app/process, and watch for a later packet from the device's real interface or another action performed by the privileged service. + +Defensive clues: +* Binder methods that should be protocol-specific must validate the payload format instead of accepting arbitrary bytes. +* Privileged services should re-check the **original caller UID/network policy** before replaying traffic or reconstructing sockets on behalf of apps. + --- ## References @@ -661,6 +703,8 @@ Tools / scripts that speed-up Binder reconnaissance: - [Bugscale - Here We Go Again: A Five-Bug Chain to Arbitrary APK Install on Samsung S25](https://bugscale.ch/blog/here-we-go-again-a-five-bug-chain-to-arbitrary-apk-install-on-samsung-s25/) - [bugscale/samsung-s25-research - graft_sig.py](https://github.com/bugscale/samsung-s25-research/blob/main/local-apk-install/graft_sig.py) - [Microsoft Authenticator’s Unclaimed Deep Link: A Full Account Takeover Story (CVE-2026-26123)](https://khaledsec.medium.com/microsoft-authenticators-unclaimed-deep-link-a-full-account-takeover-story-cve-2026-26123-e0409a920a02) +- [The Tiny UDP Cannon: An Android VPN Bypass](https://lowlevel.fun/posts/tiny-udp-cannon-android-vpn-bypass/) +- [0x33c0unt/quic-vpn-bypass PoC](https://github.com/0x33c0unt/quic-vpn-bypass) {{#include ../../banners/hacktricks-training.md}}