本地身份验证的不安全生成密钥¶
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
生物识别身份验证(例如指纹识别)可以与存储在 Android KeyStore
中的加密密钥一起使用,以保护应用程序的敏感部分。但是,当为此目的生成的密钥设置某些参数不安全时,具有物理访问权限的攻击者可以使用 Frida 等应用程序挂钩工具绕过身份验证检查。
建议¶
在为生物识别身份验证生成密钥时,确保已设置 KeyGenParameterSpec.Builder
的以下参数
setUserAuthenticationRequired
应设置为true
;否则,可以在没有用户身份验证的情况下使用密钥。setInvalidatedByBiometricEnrollment
应设置为true
(默认值);否则,攻击者可以通过在设备上注册其他生物识别信息来使用密钥。setUserAuthenticationValidityDurationSeconds
(如果使用)应设置为-1
;否则,可以使用非生物识别(安全性较低)凭据来访问密钥。我们建议使用setUserAuthenticationParameters
来明确设置超时时间和可以使用的凭据类型。
示例¶
以下示例演示了使用安全参数配置的密钥
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();
}
在以下每种情况下,都将参数设置为不安全
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();
}
参考¶
WithSecure:您的 Android 密钥库身份验证有多安全?。
Android 开发者:KeyGenParameterSpec.Builder。
常见弱点枚举:CWE-287。