← 返回首页
Insecurely generated keys for local authentication — CodeQL query help documentation CodeQL docs
CodeQL documentation
CodeQL resources

Insecurely generated keys for local authentication

ID: java/android/insecure-local-key-gen Kind: problem Security severity: 4.4 Severity: warning Precision: medium Tags: - security - external/cwe/cwe-287 Query suites: - java-security-extended.qls - java-security-and-quality.qls

Click to see the query in the CodeQL repository

Biometric authentication, such as fingerprint recognition, can be used alongside cryptographic keys stored in the Android KeyStore to protect sensitive parts of the application. However, when a key generated for this purpose has certain parameters set insecurely, an attacker with physical access can bypass the authentication check using application hooking tools such as Frida.

Recommendation

When generating a key for use with biometric authentication, ensure that the following parameters of KeyGenParameterSpec.Builder are set:

Example

The following example demonstrates a key that is configured with secure paramaters:

private void generateSecretKey() { KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( "MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) // GOOD: Secure parameters are used to generate a key for biometric authentication. .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(keyGenParameterSpec); keyGenerator.generateKey(); }

In each of the following cases, a parameter is set insecurely:

private void generateSecretKey() { KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( "MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) // BAD: User authentication is not required to use this key. .setUserAuthenticationRequired(false) .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(keyGenParameterSpec); keyGenerator.generateKey(); } private void generateSecretKey() { KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( "MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) // BAD: An attacker can access this key by enrolling additional biometrics. .setInvalidatedByBiometricEnrollment(false) .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(keyGenParameterSpec); keyGenerator.generateKey(); } private void generateSecretKey() { KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder( "MySecretKey", KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .setUserAuthenticationRequired(true) .setInvalidatedByBiometricEnrollment(true) // BAD: This key can be accessed using non-biometric credentials. .setUserAuthenticationValidityDurationSeconds(30) .build(); KeyGenerator keyGenerator = KeyGenerator.getInstance( KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore"); keyGenerator.init(keyGenParameterSpec); keyGenerator.generateKey(); }

References