Закрепление открытого ключа с помощью X509TrustManagerExtensions checkServerTrusted

Закрепление открытого ключа для соединения HTTPS TLS.

Существует проблема с Android API ниже 17, которая позволяет атаковать MITM (Человек посередине) в случае закрепления открытого ключа. Это было объяснено в ссылке ниже.

https://www.cigital.com/blog/inefficient-certificate-pinning-implementations/

Таким образом, в Android с минимальным пакетом SDK ниже 17, т. е. ниже версии Android 4.2, нам нужно инициализировать X509TrustManager с хранилищем ключей Android, которое имеет только корневые сертификаты сервера (вместо хранилища ключей по умолчанию, которое все сертификаты установлены на устройстве). Это помогает очищать листовые сертификаты, полученные от сервера, перед выполнением закрепления открытого ключа.

Начиная с Android API 17, Android представил X509TrustManagerExtensions, который выполняет эту очистку корня на уровне ОС.

https://developer.android.com/reference/android/net/http/X509TrustManagerExtensions.html

Мой вопрос:

Я был бы рад, если бы кто-нибудь мог привести пример того, как реализовать следующий метод, предоставленный X509TrustManagerExtensions для очистки корня.

List<X509Certificate> checkServerTrusted (X509Certificate[] chain, 
                String authType, 
                String host)

Меня смущает следующее.

  1. host; должен ли это быть URL-адрес домена? с https или без? или это должен быть полный URL-адрес (домен + относительный путь)

  2. Как создать момент X509TrustManagerExtensions? Конструктор для X509TrustManagerExtensions принимает X509TrustManager в качестве входных данных. Создадим ли мы этот X509TrustManager с хранилищем ключей Android по умолчанию?

Фрагмент кода (не работает):

   TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
   tmf.init(KeyStore.getInstance(KeyStore.getDefaultType()));

   for (TrustManager trustManager : tmf.getTrustManagers()) {
       X509TrustManagerExtensions tme = new X509TrustManagerExtensions((X509TrustManager) trustManager);
       tme.checkServerTrusted(chain, authType, <<String https://www.example.com>>);
   }

Исключение: якорь доверия для пути сертификации не найден

Возможная угроза безопасности: использование KeyStore.getDefaultType()

Любая помощь будет принята с благодарностью.


person B.B.    schedule 10.08.2016    source источник
comment
Есть ли причина, по которой вы не можете использовать ›= API 17?   -  person Chris    schedule 01.09.2016
comment
«X509TrustManagerExtensions» существует только в API 17 и выше.   -  person B.B.    schedule 02.09.2016


Ответы (1)


Во-первых, вам нужно получить доверительный менеджер, используя файл TrustManagerFactory. При инициализации вы передаете значение null, чтобы использовать значение по умолчанию Keystore, и оно вернет менеджеры доверия по умолчанию. При этом вы можете создать X509TrustManagerExtensions, используя первый X509TrustManager.

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);

// Find first X509TrustManager in the TrustManagerFactory
X509TrustManager x509TrustManager = null;
for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
    if (trustManager instanceof X509TrustManager) {
        x509TrustManager = (X509TrustManager) trustManager;
        break;
    }
}

X509TrustManagerExtensions x509TrustManagerExtensions = 
        new X509TrustManagerExtensions(trustManager());

Затем, чтобы выполнить этот хост, я успешно использовал только доменную часть:

List<X509Certificate> trustedCerts = x509TrustManagerExtensions
        .checkServerTrusted(untrustedCerts, "RSA", "appmattus.com");

Для тех, кто использует HttpUrlConnection, ненадежные сертификаты определяются с помощью:

Certificate[] serverCerts = ((HttpsUrlConnection)conn).getServerCertificates();
X509Certificate[] untrustedCerts = Arrays.copyOf(serverCerts, 
        serverCerts.length, 
        X509Certificate[].class);

Если вы используете OkHttp, вы можете просто использовать встроенный CertificatePinner. который с тех пор был обновлен, чтобы исправить проблемы, упомянутые в этой статье.

person appmattus    schedule 07.01.2017