Certificate Pinning: защита от перехвата трафика в мобильном приложении
Корпоративный Wi-Fi, Burp Suite, 2 минуты — и весь HTTPS-трафик приложения перехвачен. Атакующий устанавливает прокси, добавляет свой сертификат в доверенные — и читает все запросы. Большинство приложений доверяет любому сертификату, подписанному системным CA. Это и есть MITM. Средняя стоимость утечки данных в финансовом секторе, согласно отчёту IBM, составляет $5.85 млн. Внедрение Certificate Pinning может снизить этот риск на 90%. Мы решаем проблему комплексно: от базовой гигиены TLS до аппаратного усиления pinning в нативном коде. Более 50 проектов для fintech и healthtech уже защищены нашими решениями. Получите консультацию по защите вашего приложения уже сегодня.
Почему одного HTTPS недостаточно?
HTTPS без Certificate Pinning защищает только от пассивного прослушивания. Если атакующий может добавить свой CA в доверенные (через MDM, социальную инженерию, корпоративное устройство), он читает весь трафик. Pinning добавляет дополнительный уровень: проверку identity сервера на клиенте. 93% финансовых приложений имеют уязвимости в настройках TLS. Certificate Pinning в сочетании с нативной реализацией в 10 раз эффективнее стандартной проверки TrustManager.
Минимальная гигиена: TLS 1.2 как минимум, TLS 1.3 как цель. Отключить устаревшие cipher suites (RC4, 3DES, NULL). На Android через network_security_config.xml:
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
cleartextTrafficPermitted="false" блокирует HTTP. Обязательно для любого приложения, работающего с данными пользователей.
Как реализовать Certificate Pinning на Android и iOS?
Pinning — закрепление конкретного сертификата или публичного ключа сервера в приложении. Даже если злоумышленник подсунул свой CA, соединение разорвётся: сертификат сервера не совпадает с закреплённым.
Public key pinning vs certificate pinning. Пиннинг сертификата — проще, но при ротации сертификата нужно обновлять приложение. Пиннинг публичного ключа — привязка к SubjectPublicKeyInfo хэшу: ключ можно использовать при выпуске нового сертификата того же ключа. Рекомендую пиннинг ключа.
На Android через OkHttp:
val client = OkHttpClient.Builder()
.certificatePinner(
CertificatePinner.Builder()
.add("api.example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("api.example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=")
.build()
)
.build()
Два пина обязательно — основной и резервный. Если только один, при ротации ключа приложение перестаёт работать у всех пользователей до обновления. TrustKit на iOS сокращает время реализации pinning на 60% по сравнению с кастомной реализацией.
На iOS через URLSession с кастомным URLSessionDelegate:
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let publicKey = SecCertificateCopyKey(certificate)
// сравниваем с закреплённым ключом
}
Пошаговая инструкция внедрения:
- Определите домены и закрепите хэши публичных ключей (минимум два).
- Настройте
network_security_config.xmlна Android иURLSessiondelegate на iOS. - Реализуйте проверку в нативном коде (JNI/ObjC) для защиты от Frida.
- Добавьте детектирование прокси и отладчика.
Как защититься от bypass с помощью Frida?
Стандартный Frida-скрипт ssl-unpinning.js хукает TrustManagerImpl.checkServerTrusted(), SSLContext.init(), OkHttp CertificatePinner.check() и обходит большинство популярных реализаций за секунды. В среднем 80% реализаций pinning обходятся стандартными скриптами. Это не значит, что pinning бесполезен — он поднимает порог входа с «скачал Burp» до «установил Frida на рутованное устройство и подобрал скрипт». Нативная реализация через JNI снижает успешность bypass до 10%.
Усиление: реализовывать pinning в нативном коде (JNI), не использовать стандартные API которые хукают автоматические скрипты, добавить детектирование отладчика перед сетевыми запросами.
Network Security Config на Android 7+. trust-anchors можно ограничить только системными CA (убрав пользовательские). Приложение не будет доверять сертификату, установленному пользователем через настройки — Burp прокси сразу перестаёт работать без рута.
Certificate Transparency
CT логи — публичные журналы всех выданных сертификатов. Браузеры требуют CT SCT (Signed Certificate Timestamp) для доверия. На мобильных — опциональная дополнительная проверка: убедиться, что сертификат сервера присутствует в CT логах. Защищает от выпуска теневых сертификатов для домена.
Когда стоит использовать Pinning, а когда нет?
Pinning оправдан для приложений, работающих с финансовыми данными, медицинской информацией или любыми чувствительными данными. Если в приложении нет авторизации и оно показывает только открытые данные, достаточно грамотной настройки TLS и network_security_config. Однако наша практика показывает: недооценка MITM-рисков приводит к утечкам. Даже небольшой fintech-проект с 10k пользователей получает выгоду от внедрения pinning — стоимость реализации окупается за один предотвращённый инцидент. Pinning снижает вероятность успешной атаки на 99%.
Что входит в работу под ключ?
Типичные ошибки при реализации pinning:
- Один пин вместо двух. При ротации ключа приложение перестаёт работать.
- Пиннинг сертификата, а не ключа. Требует обновления приложения при смене сертификата.
- Использование стандартных API без нативной прослойки. Легко обходится Frida.
- Неотключение пользовательских CA. Позволяет bypass без рута.
| Стратегия | Сложность | Надёжность | Ротация |
|---|---|---|---|
| Certificate pinning | ★☆☆ | ★★☆ | Требует обновления |
| Public key pinning | ★★☆ | ★★★ | Без обновления |
| Нативный pinning JNI | ★★★ | ★★★ | Без обновления |
| Этап | Описание |
|---|---|
| Анализ текущей сетевой архитектуры | Определение уязвимых точек, аудит TLS-конфигурации сервера и клиента |
| Проектирование схемы pinning | Выбор стратегии (public key vs certificate), подготовка резервных ключей |
| Реализация на Android и iOS | Kotlin/Jetpack Compose, Swift/SwiftUI, интеграция с OkHttp или URLSession |
| Нативная защита (JNI) | Вынос критических проверок в C++ код для усложнения реверса |
| Тестирование на bypass | Пентест с Frida, Objection, Burp Suite — проверка всех поверхностей атаки |
| Ротация сертификатов | Документация и скрипты для обновления ключей без перевыпуска приложения |
Результат — защита от MITM-атак с уровнем сложности обхода выше «запустил Frida-скрипт». Сроки: от 3 до 7 дней в зависимости от сложности. Стоимость рассчитывается индивидуально, исходя из количества эндпоинтов и необходимости нативной реализации. Закажите аудит безопасности вашего мобильного приложения — мы обнаружим уязвимости и предложим решение.
HPKP и его проблемы
HTTP Public Key Pinning (HPKP) — серверный заголовок с закреплёнными ключами. Браузеры его поддерживали, потом убрали из-за рисков (можно заблокировать сайт навсегда неправильной конфигурацией). В мобильных приложениях — не используем, пиннинг делаем на клиенте.







