|
| 1 | +# eSIM / Java Card VM Exploitation |
| 2 | + |
| 3 | +{{#include ../banners/hacktricks-training.md}} |
| 4 | + |
| 5 | +## Overview |
| 6 | +Embedded SIMs (eSIMs) are implemented as **Embedded UICC (eUICC)** smart-cards that run a **Java Card Virtual Machine (JC VM)** on top of a secure element. |
| 7 | +Because profiles and applets can be provisioned *over-the-air* (OTA) via Remote SIM Provisioning (RSP), any memory-safety flaw inside the JC VM instantly becomes a remote code-execution primitive **inside the most privileged component of the handset**. |
| 8 | + |
| 9 | +This page describes a real-world full compromise of Kigen’s eUICC (Infineon SLC37 ESA1M2, ARM SC300) caused by missing type-safety checks in the `getfield` and `putfield` bytecodes. The same technique can be re-used against other vendors that omit on-card byte-code verification. |
| 10 | + |
| 11 | +## Attack Surface |
| 12 | +1. **Remote Application Management (RAM)** |
| 13 | + eSIM profiles may embed arbitrary Java Card applets. Provisioning is performed with standard APDUs that can be tunnelled through SMS-PP (Short Message Service Point-to-Point) or HTTPS. If an attacker owns (or steals) the **RAM keys** for a profile, they can `INSTALL`/`LOAD` a malicious applet remotely. |
| 14 | +2. **Java Card byte-code execution** |
| 15 | + After installation, the applet executes inside the VM. Missing run-time checks allow memory corruption. |
| 16 | + |
| 17 | +## The Type-Confusion Primitive |
| 18 | +`getfield` / `putfield` are supposed to operate only on **object references**. In Kigen eUICC the instructions never validate whether the operand on the stack is an *object* or an *array* reference. Because an `array.length` word lives at the exact same offset as the first instance field of a normal object, an attacker can: |
| 19 | + |
| 20 | +1. Create a byte-array `byte[] buf = new byte[0x100];` |
| 21 | +2. Cast it to `Object o = (Object)buf;` |
| 22 | +3. Use `putfield` to overwrite *any* 16-bit value inside an adjacent object (including VTABLE / ptr translation entries). |
| 23 | +4. Use `getfield` to read *arbitrary* memory once internal pointers are hijacked. |
| 24 | + |
| 25 | +```java |
| 26 | +// Pseudo-bytecode sequence executed by the malicious applet |
| 27 | +// buf = newarray byte 0x100 |
| 28 | +// o = (Object) buf // illegal but not verified |
| 29 | +// putfield <victimObject+offset>, 0xCAFE // arbitrary write |
| 30 | +// ... set up read-what-where gadgets ... |
| 31 | +``` |
| 32 | +The primitive provides **arbitrary read / write** in the eUICC address space – enough to dump the device-unique ECC private key that authenticates the card to the GSMA ecosystem. |
| 33 | + |
| 34 | +## End-to-End Exploitation Workflow |
| 35 | +1. **Enumerate firmware** – Use undocumented `GET DATA` item `DF1F`: |
| 36 | + ``` |
| 37 | + 80 CA DF 1F 00 // → "ECu10.13" (vulnerable) |
| 38 | + ``` |
| 39 | +2. **Install malicious applet OTA** – Abuse publicly-known keys of the TS.48 Generic Test Profile and push SMS-PP fragments that transport the CAP file (`LOAD`) followed by an `INSTALL`: |
| 40 | + ``` |
| 41 | + // simplified APDU chain |
| 42 | + 80 E6 02 00 <data> // LOAD (block n) |
| 43 | + 80 E6 0C 00 <data> // INSTALL for load |
| 44 | + ``` |
| 45 | +3. **Trigger type-confusion** – When the applet is selected it performs the write-what-where to hijack a pointer table and leak memory through normal APDU responses. |
| 46 | +4. **Extract GSMA certificate key** – Private EC key is copied to the applet’s RAM and returned in chunks. |
| 47 | +5. **Impersonate the eUICC** – The stolen key pair + certificates let the attacker authenticate to *any* RSP server as a legitimate card (EID binding may still be required for some operators). |
| 48 | +6. **Download and modify profiles** – Plaintext profiles contain highly sensitive fields such as `OPc`, `AMF`, OTA keys and even additional applets. The attacker can: |
| 49 | + * Clone a profile to a second eUICC (voice/SMS hijack); |
| 50 | + * Patch Java Card applications (e.g. insert STK spyware) before re-uploading; |
| 51 | + * Extract operator secrets for large-scale abuse. |
| 52 | + |
| 53 | +## Cloning / Hijacking Demonstration |
| 54 | +Installing the same profile on **PHONE A** and **PHONE B** results in the Mobile Switching Centre routing incoming traffic to whichever device most recently registered. One session of Gmail 2FA SMS interception is enough to bypass MFA for the victim. |
| 55 | + |
| 56 | +## Automated Test & Exploit Toolkit |
| 57 | +The researchers released an internal tool with a `bsc` (*Basic Security Check*) command that immediately shows whether a Java Card VM is vulnerable: |
| 58 | +``` |
| 59 | +scard> bsc |
| 60 | +- castcheck [arbitrary int/obj casts] |
| 61 | +- ptrgranularity [pointer granularity/tr table presence] |
| 62 | +- locvaraccess [local variable access] |
| 63 | +- stkframeaccess [stack frame access] |
| 64 | +- instfieldaccess [instance field access] |
| 65 | +- objarrconfusion [object/array size field confusion] |
| 66 | +``` |
| 67 | +Modules shipped with the framework: |
| 68 | +* `introspector` – full VM and memory explorer (~1.7 MB Java) |
| 69 | +* `security-test` – generic verification bypass applet (~150 KB) |
| 70 | +* `exploit` – 100 % reliable Kigen eUICC compromise (~72 KB) |
| 71 | + |
| 72 | +## Mitigations |
| 73 | +1. **On-card byte-code verification** – enforce full control-flow & data-flow type tracking instead of stack-top only. |
| 74 | +2. **Hide array header** – place `length` outside of overlapping object fields. |
| 75 | +3. **Harden RAM keys policy** – never ship profiles with public keys; disable `INSTALL` in test profiles (addressed in GSMA TS.48 v7). |
| 76 | +4. **RSP server side heuristics** – rate-limit profile downloads per EID, monitor geographic anomalies, validate certificate freshness. |
| 77 | + |
| 78 | +## Quick Checklist for Pentesters |
| 79 | +* Query `GET DATA DF1F` – vulnerable firmware string `ECu10.13` indicates Kigen. |
| 80 | +* Check if RAM keys are known ‑> attempt OTA `INSTALL`/`LOAD`. |
| 81 | +* After applet installation, brute-force simple cast primitive (`objarrconfusion`). |
| 82 | +* Try to read Security Domain private keys – success = full compromise. |
| 83 | + |
| 84 | +## References |
| 85 | +- [Security Explorations – eSIM security](https://security-explorations.com/esim-security.html) |
| 86 | +- [GSMA TS.48 Generic Test Profile v7.0](https://www.gsma.com/get-involved/working-groups/gsma_resources/ts-48-v7-0-generic-euicc-test-profile-for-device-testing/) |
| 87 | +- [Java Card VM Specification 3.1](https://docs.oracle.com/en/java/javacard/3.1/jc-vm-spec/F12650_05.pdf) |
| 88 | + |
| 89 | +{{#include ../banners/hacktricks-training.md}} |
0 commit comments