UPDATE  (Jun. 30, 2014):
The vulnerability affects Android 4.3 only. Thanks for the Android Security Team for correcting our advisory.

Nine months ago, my team came across a classic stack-based buffer overflow in the Android KeyStore service.

As always, we adhered to our responsible disclosure policy and privately reported this issue to the Android Security Team; the result is a patch that is now available in KitKat. Considering Android’s fragmented nature and the fact that this was a code-execution vulnerability, we decided to wait a bit with the public disclosure.

See the full advisory with more details here.

As an anecdote, the vulnerable source code file contains the following comment:

/* KeyStore is a secured storage for key-value pairs. In this implementation,
 * each file stores one key-value pair. Keys are encoded in file names, and
 * values are encrypted with checksums. The encryption key is protected by a
 * user-defined password. To keep things simple, buffers are always larger than
 * the maximum space we needed, so boundary checks on buffers are omitted. */

Though things are simple, buffers are not always larger than the maximum space they needed.

The Android KeyStore Service

Android provides a secure storage service implemented by /system/bin/keystore. In the past, this service was accessible to other applications using a UNIX socket daemon found under /dev/socket/keystore; nowadays, however, it is accessible by the Binder interface. Each Android user receives his or her own secure storage area. A Blob is encrypted with AES using a master key, which is random, and is encrypted on-disk using a key that is derived from a password (the lock screen credentials) by the PKCS5_PBKDF2_HMAC_SHA1 function.

In recent Android versions, credentials such as RSA private keys can be hardware-backed. This basically means that the keystore keys only serve as identifiers for the real keys backed by the hardware. Despite the hardware support, some credentials, such as VPN PPTP credentials, are still stored (encrypted) on-disk.

The following diagram best illustrates the operation of the KeyStore service:

More internals of KeyStore are available on the excellent series of posts (1, 2, 3, 4, 5) by Nikolay Elenkov.

The Vulnerability

A stack buffer is created by the ‘KeyStore::getKeyForName’ method.

ResponseCode getKeyForName( Blob* keyBlob, 
                            const android::String8& keyName,
                            const uid_t uid,
                            const BlobType type)
{
  char filename[NAME_MAX];
  encode_key_for_uid(filename, uid, keyName);
...
}

This function has several callers, which are accessible by external applications using the Binder interface (e.g., ‘android::KeyStoreProxy::get’). Therefore, the ‘keyName’ variable can be controllable with an arbitrary size by a malicious application. As you can see, the ‘encode_key’ routine that is called by ‘encode_key_for_uid’ can overflow the ‘filename’ buffer, since bounds checking is absent:

static int encode_key_for_uid( char* out,
                               uid_t uid,
                               const android::String8& keyName)
{
  int n = snprintf(out, NAME_MAX, "%u_", uid);
  out += n; return n + encode_key(out, keyName);
}

static int encode_key( char* out, const android::String8& keyName)
{
  const uint8_t* in = reinterpret_cast(keyName.string());
  size_t length = keyName.length();
  for (int i = length; i > 0; --i, ++in, ++out)
  {
     if (*in < '0' || *in > '~')
     {
        *out = '+' + (*in >> 6);
        *++out = '0' + (*in & 0x3F);
        ++length;
     }
     else
     {
        *out = *in;
     }
  }
  *out = '';
  return length;
}

Exploitation

Exploiting this vulnerability can theoretically be done by a malicious application; however, a working exploit needs to overcome a combination of obstacles:

  1. Data Execution Prevention (DEP). This can be bypassed by Return-Oriented Programming (ROP) payloads.
  2. Address Space Layout Randomization (ASLR)
  3. Stack Canaries
  4. Encoding. Characters below 0x30 (‘0’) or above 0x7e (‘~’) are encoded before being written on the buffer.

However, the Android KeyStore is respawned every time it terminates. This behavior enables a probabilistic approach; moreover, the attacker may even theoretically abuse ASLR to defeat the encoding.

Impact

Successfully exploiting this vulnerability leads to a malicious code execution under the keystore process. Such code can:

  1. Leak the device’s lock credentials. Since the master key is derived by the lock credentials, whenever the device is unlocked, ‘Android::KeyStoreProxy::password’ is called with the credentials.
  2. Leak decrypted master keys, data and hardware-backed key identifiers from the memory.
  3. Leak encrypted master keys, data and hardware-backed key identifiers from the disk for an offline attack.
  4. Interact with the hardware-backed storage and perform crypto operations (e.g., arbitrary data signing) on behalf of the user.

Vulnerable Versions

Android 4.3.

Non-vulnerable Versions

Android 4.4.

Disclosure Timeline

Jun. 23, 2014 Public disclosure.
Nov. 11, 2013 Fix confirmed by Android Security Team.
Oct. 22, 2013 Updates requested from Android Security Team.
Sept. 9, 2013 Vulnerability acknowledged by Android Security Team.
Sept. 9, 2013 Private disclosure to Android Security Team.

Identifiers

CVE-2014-3100
ANDROID-10676015

Acknowledgment

We would like to thank Android Security Team for the efficient way in which they handled this security vulnerability.

More from Software Vulnerabilities

Patch Tuesday -> Exploit Wednesday: Pwning Windows Ancillary Function Driver for WinSock (afd.sys) in 24 Hours

‘Patch Tuesday, Exploit Wednesday’ is an old hacker adage that refers to the weaponization of vulnerabilities the day after monthly security patches become publicly available. As security improves and exploit mitigations become more sophisticated, the amount of research and development required to craft a weaponized exploit has increased. This is especially relevant for memory corruption vulnerabilities.Figure 1 — Exploitation timelineHowever, with the addition of new features (and memory-unsafe C code) in the Windows 11 kernel, ripe new attack surfaces can…

Direct Kernel Object Manipulation (DKOM) Attacks on ETW Providers

Overview In this post, IBM Security X-Force Red offensive hackers analyze how attackers, with elevated privileges, can use their access to stage Windows Kernel post-exploitation capabilities. Over the last few years, public accounts have increasingly shown that less sophisticated attackers are using this technique to achieve their objectives. It is therefore important that we put a spotlight on this capability and learn more about its potential impact. Specifically, in this post, we will evaluate how Kernel post-exploitation can be used…

Dissecting and Exploiting TCP/IP RCE Vulnerability “EvilESP”

September’s Patch Tuesday unveiled a critical remote vulnerability in tcpip.sys, CVE-2022-34718. The advisory from Microsoft reads: “An unauthenticated attacker could send a specially crafted IPv6 packet to a Windows node where IPsec is enabled, which could enable a remote code execution exploitation on that machine.” Pure remote vulnerabilities usually yield a lot of interest, but even over a month after the patch, no additional information outside of Microsoft’s advisory had been publicly published. From my side, it had been a…

Self-Checkout This Discord C2

This post was made possible through the contributions of James Kainth, Joseph Lozowski, and Philip Pedersen. In November 2022, during an incident investigation involving a self-checkout point-of-sale (POS) system in Europe, IBM Security X-Force identified a novel technique employed by an attacker to introduce a command and control (C2) channel built upon Discord channel messages. Discord is a chat, voice, and video service enabling users to join and create communities associated with their interests. While Discord and its related software…