Frida: Android key store

How Secure is your Android Keystore Authentication ?

Introduction

Privileged malware or an attacker with physical access to an Android device is a difficult attack vector to protect against. How would your application maintain security in such a scenario?

This blog post will discuss the Android keystore mechanisms and the difficulties encountered when attempting to implement secure local authentication. By providing an introduction to the AndroidKeystore, it's API and usage you will be ab to understand the common vulnerabilities associated with the keystore as they are discussed. The core of this article will highlight the developed tools which can be used to audit an application's local authentication. This will conclude with general guidance on secure implementations and an application which can be used as a reference is presented.

KeyStore Introduction

The Android Keystore is a system that lets developers create and store cryptographic keys in a container making them more difficult to extract from the device. These keys are stored within specialized hardware, a so called trusted execution environment. Key material can be generated inside it and even the operating system itself should not have direct access to this secure memory. The Android Keystore provides APIs to perform cryptographic operations within this trusted environment and receive the result. It was introduced in API 18 (Android 4.3). A strongbox backed Android Keystore is currently the most secure and recommended type of keystore.

Android supports 7 different types of keystore mechanisms, each having their own advantages and disadvantages. For example the Android Keystore uses a hardware chip to store the keys in a secure way, while the Bouncy Castle Keystore (BKS) is a software keystore and uses an encrypted file placed on the file system. The Android documentation offers many code examples useful for developers but is somewhat confusing and convoluted when describing its keystore mechanisms. This results in a lot of developer headaches. In a lot of keystore related classes, the Android documentation is often taken directly from Java documentation. After not finding a concise explanation and a solution for developing secure local authentication, they resolve to StackOverflow, copying and pasting code which is not secure and can be easily bypassed with some Frida scripts. The fragmented Android ecosystem also makes working with the keystore an unpleasant experience as multiple compatibility checks need to be performed and various code paths need to be implemented in order to support a wide variety of devices.

Lets look at the following screenshot. The Android documentation is presented on the left and the Java documentation is presented on the right.


The AndroidKeystore implementation doesn't support passwords for unlocking the keystore or its specific entries. The code snippet shown in the documentation will throw an exception. The screenshot above shows that the Android documentation is not a 100% reliable source of knowledge about the AndroidKeystore implementation. Due to the fact that Android supports a new type of keystore system which is not included in classic Java, the example above will not work with AndroidKeystore. Having discovered more issues, we decided to take a deeper look at the keystore system available in Android. Further on in this post, you can find methods that can be used to test for insecure keystore usage.

Keystores, keystores everywhere!

An Android Keystore is just a Java class that Android developers can use. The Android Keystore is yet another implementation of the Java Keystore API, other types of keystores, like BSK, also implement this API.

We can just use the regular Java KeyStore API to access Android KeyStore:

KeyStore ks = KeyStore.getInstance("AndroidKeystore");

Keystore types

The table below lists keystore types supported by the stock Android (up utill Android 9):

AlgorithmSupported API Levels
AndroidCAStore 14+
AndroidKeyStore 18+
BCPKCS12 1-8
BKS 1+
BouncyCastle 1+
PKCS12 1+
PKCS12-DEF 1-8

A more up-to-date list can be found in this article:

https://developer.android.com/reference/java/security/KeyStore

There any other keystore types, for example Samsung supports its own keystore type named TIMA.

How to use the Android Keystore?

The Java keystore API contains a java.security.KeyStore class with methods for inserting keys. However, most of the calls that are supposed to insert keys into keystore will throw an exception. This was done by Android to prevent developers from inserting hardcoded keys. The assumption of Android Keystore is that keys should never leave the trusted environment, therefore developers can only generate new keys using android.security.keystore.KeyGenParameterSpec.Builder class. An example reference application which implements local authentication can be found here.

Every key stored within the keystore can have the following parameters set:

  • alias - used to identify the key.
  • key size (API 23).
  • purpose – encrypt/decrypt (API 23).
  • encryption mode, algorithm and padding (API 23).
  • should the key be authenticated with the keystore before usage? (API 23).
  • the time duration for which the key can be used after a successful authentication (API 23).
  • should a key be invalidated on new fingerprint enrolment? (API 24)
  • should a keystore require the screen to be unlocked before performing cryptographic operations? (API 28)
  • should a key be protected by a StrongBox hardware security module? (API 28)

Supported Android API versions are included in brackets to show what security features were introduced in different Android releases. More settings and information about them can be found in the appropriate Android documentation.

Let's discuss common vulnerabilities associated with the keystore:

  • Insecure keystore type in use:
    For example, if a BKS keystore is in use, keys are stored within a file that can be accessed by a privileged user. AndroidKeystore supports hardware-backed containers and should be preferred.
  • Key not invalidated on new fingerprint enrollment:
    An attacker with physical access to a device can enroll their own fingerprint and use a key locked by biometrics.
  • Keystore accessible without screen unlock:
    Allowing the key to be used without unlocking the screen increases attack surface.
  • Weak cryptography algorithms in use:
    Weak cryptography algorithms used in KeyGenerator.getInstance method.
  • Weak/hardcoded password for keystore or keystore entry:
    This type of vulnerability can only occur when it is possible to set a password to access a keystore. The AndroidKeystore is the recommended keystore type but if the application design requires the usage of a software backed keystore then setting a strong user-derived password is advised.

Frida audit scripts

To speed up keystore auditing and make assessments more robust, we prepared some useful Frida scripts. These script are available here. The list below describes their functionalities.

Keystore tracer

Generic keystore debugging script:

  • lists keystore types used by the application.
  • lists keystore entry aliases used by the specific keystore (or by any keystore within the application).
  • list all information about a key in AndroidKeystore. Useful when determining if biometrics can be bypassed.
  • other utilities useful in reverse engineering, when looking for interesting keys.

KeyGenParameterSpec tracer

  • lists information about a key which is generated at runtime using the KeyGenParameterSpec API. Information includes key size, encryption mode, algorithm and more.
  • useful in reviewing cryptography used within the application.

SecretKeyFactory tracer

  • hooks into PBEKeySpec constructor and getInstance() method to extract a password, number of iterations, salt and key size used to create a PBKDF key.
  • useful in reviewing cryptography used within the application - not only keystore

Cipher tracer

  • hooks into the Cipher API, lists information about a specific key such as key size, encryption mode, algorithm and more.
  • useful in reviewing cryptography used within the application - not only keystore

Comments

Popular posts from this blog

Mobexler: Os built for Pentesting

Charles: http/https proxy

Jadx: Reverse engineering tool