不安全的本地身份验证¶
ID: java/android/insecure-local-authentication
Kind: problem
Security severity: 4.4
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-287
Query suites:
- java-code-scanning.qls
- java-security-extended.qls
- java-security-and-quality.qls
生物识别本地身份验证(如指纹识别)可用于保护应用程序中的敏感数据或操作。但是,如果此身份验证不使用 KeyStore
支持的密钥,则它可能会被具有特权的恶意应用程序绕过,或者被使用 Frida 等应用程序挂钩工具进行物理访问的攻击者绕过。
建议¶
在 Android KeyStore
中生成安全密钥。确保生物识别提示的 onAuthenticationSuccess
回调以应用程序敏感部分正常运行所需的方式使用它,例如通过使用它来解密敏感数据或凭据。
示例¶
在以下(错误)情况下,生物识别提示不需要 CryptoObject
来授予访问权限,因此它可能会被绕过。
biometricPrompt.authenticate(
cancellationSignal,
executor,
new BiometricPrompt.AuthenticationCallback {
@Override
// BAD: This authentication callback does not make use of a `CryptoObject` from the `result`.
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
grantAccess()
}
}
)
在以下(正确)情况下,在 Android KeyStore
中生成一个密钥。应用程序需要此密钥才能访问,并使用它来解密数据。
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)
.build();
KeyGenerator keyGenerator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
}
private SecretKey getSecretKey() {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
return ((SecretKey)keyStore.getKey("MySecretKey", null));
}
private Cipher getCipher() {
return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
+ KeyProperties.BLOCK_MODE_CBC + "/"
+ KeyProperties.ENCRYPTION_PADDING_PKCS7);
}
public prompt(byte[] encryptedData) {
Cipher cipher = getCipher();
SecretKey secretKey = getSecretKey();
cipher.init(Cipher.DECRYPT_MODE, secretKey);
biometricPrompt.authenticate(
new BiometricPrompt.CryptoObject(cipher),
cancellationSignal,
executor,
new BiometricPrompt.AuthenticationCallback() {
@Override
// GOOD: This authentication callback uses the result to decrypt some data.
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
Cipher cipher = result.getCryptoObject().getCipher();
byte[] decryptedData = cipher.doFinal(encryptedData);
grantAccessWithData(decryptedData);
}
}
);
}
参考¶
OWASP 移动应用程序安全性:Android 本地身份验证
OWASP 移动应用程序安全性:测试生物识别身份验证
WithSecure:您的 Android Keystore 身份验证有多安全?
Android 开发者:生物识别身份验证
常见弱点枚举:CWE-287.