Перейти к содержанию

Приложение использует Android KeyStore, но не проверяет, что ключ аппаратно защищён (Hardware-Backed)

Описание

Android KeyStore может хранить ключи либо в защищённом аппаратном модуле (TEE / StrongBox HSM), либо в программном контейнере.
Если после генерации/импорта ключа приложение не проверяет признак isInsideSecureHardware() или не валидирует attestation-подпись, оно рискует использовать ключ, который:

  • хранится в системной памяти и может быть извлечён на рутованном устройстве;
  • был импортирован злоумышленником вместо сгенерированного аппаратно.

Google рекомендует подтверждать аппаратную защиту через Key Attestation или инспекцию KeyInfo перед использованием ключа.

Потенциальные последствия

  • Извлечение приватного ключа при root-доступе, что позволяет расшифровать базы, токены или сетевой трафик.
  • Подмена ключа вредоносным ПО: фальшивый ключ хранится в софте, но проходит валидацию приложения и открывает MITM-канал.
  • Несоответствие требованиям безопасности (OWASP MASVS - M9, Google Play Data Safety).
  • Неисполнение регуляторных норм (например, PSD2/SCA требует аппаратного ХСК для хранения банковских ключей).

Рекомендации

  1. Проверяйте isInsideSecureHardware() сразу после генерации/получения ключа

    KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
    ks.load(null);
    SecretKey key = (SecretKey) ks.getKey(alias, null);
    
    KeyFactory kf = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
    KeyInfo info = kf.getKeySpec(key, KeyInfo.class);
    
    if (!info.isInsideSecureHardware()) {
       throw new SecurityException("Key is NOT hardware-backed");
    }
    

    Пример проверки обсуждается в сообществе разработчиков. (Stack Overflow)

  2. Используйте Key Attestation для критичных операций

    • Запросите цепочку сертификатов (attestationChallenge) и проверьте, что attestationSecurityLevel == STRONGBOX или TEE.
    • Храните отпечаток сертификата на сервере и сравнивайте при каждом запуске. (Android Developers)
  3. При генерации ключа укажите StrongBox/TEE флаг

    new KeyGenParameterSpec.Builder(alias,
       KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
       .setIsStrongBoxBacked(true)          // требуем StrongBox
       .setUserAuthenticationRequired(true) // привязываем к биометрии/PIN
       .build();
    

    На устройствах без StrongBox обработайте StrongBoxUnavailableException (Android Developers)

  4. Откажитесь от импорта симметричных ключей, если можно сгенерировать их внутри TEE/StrongBox. Импортированные ключи никогда не могут быть помечены как hardware-backed.

  5. Для устройств до API 23 рассмотрите использование Trusted Execution Environment сторонних SDK или внешнего HSM; старые версии не поддерживают KeyInfo.

Дополнительные рекомендации

  • Сохраняйте результаты attestation на бэкенде и анализируйте отклонения (например, key перестал быть hardware-backed после обновления прошивки).
  • Периодически выполняйте принудительное re-key с новой проверкой аппаратной защиты.
  • Уведомляйте пользователя, если устройство не поддерживает аппаратный KeyStore, и предлагайте ограничения функционала.

Ссылки

  1. Verify hardware-backed key pairs with Key Attestation
  2. Android Keystore System Overview
  3. Android: Check if key is in secure hardware (isInsideSecureHardware) – Stack Overflow
  4. Android 9+ StrongBox Hardware Security Module
  5. Medium – A Deep Dive into Android Hardware-Backed Keystore
К началу