CodeQL 文档

本地身份验证的不安全生成密钥

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

单击以在 CodeQL 存储库中查看查询

生物识别身份验证(例如指纹识别)可以与存储在 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();
}

参考

  • ©GitHub, Inc.
  • 条款
  • 隐私