Додаток перехоплюють через Charles Proxy або Frida — читають запити, модифікують відповіді, вивчають API. Це відбувається тому, що TLS-з'єднання валідує сертифікат відносно системних CA, а користувач (або пентестер) просто додав свій CA в довірені. Ми впровадили Certificate Pinning для 35+ мобільних проєктів — від фінтех-стартапів до enterprise-рішень. Це повністю закриває вектор MITM-атак на нерутованих пристроях. Налаштовуємо pinning на iOS та Android, включаючи backup-піни та CI-перевірки. Терміни робіт — від 2 до 5 днів залежно від кількості хостів. Хочете оцінити ваш проєкт? Просто напишіть нам.
Чому public key pinning кращий за certificate pinning?
Certificate pinning — клієнт зберігає повний сертифікат (або його SHA-256 хеш) і порівнює з тим, що надіслав сервер. Сертифікат змінюється при кожному renewal — раз на 1–2 роки. Якщо забули оновити пін до ротації, додаток перестає працювати у всіх користувачів одночасно.
Public key pinning (HPKP-стиль) — піниться хеш SubjectPublicKeyInfo. При ротації сертифіката приватний ключ часто залишається тим самим, тому пін актуальний. Це правильний вибір для продакшену. Додатково тримайте backup pin — хеш резервного ключа (може бути у вашого CA). Public key pinning у 3 рази зменшує необхідність оновлення клієнта порівняно з certificate pinning.
| Характеристика | Certificate Pinning | Public Key Pinning |
|---|---|---|
| Частота оновлення клієнта | Кожні 1–2 роки | Раз на кілька років |
| Ризик блокування користувачів | Високий | Низький |
| Складність реалізації | Низька | Середня |
| Гнучкість при зміні CA | Потребує оновлення | Часто не потребує |
Як ми реалізуємо pinning: покроковий процес
Етапи реалізації:
- Аналіз інфраструктури – визначення хостів, отримання сертифікатів та публічних ключів.
- Генерація хешів – обчислення SHA-256 SPKI для кожного ключа, включаючи backup-пін.
- Реалізація pinning – вбудовування перевірки в мережевий шар (TrustKit, OkHttp, Flutter).
- Налаштування CI – крок для перевірки, що release-збірка містить pinning.
- Тестування – перевірка блокування через proxy, робота backup-піна.
- Документація – процедура ротації та контакти для екстреного оновлення.
| Етап | Опис | Тривалість |
|---|---|---|
| Аналіз інфраструктури | Визначаємо всі хости, отримуємо сертифікати та публічні ключі | 1–2 години |
| Генерація хешів | Обчислюємо SHA-256 SPKI для кожного ключа, включаючи backup-пін | 30 хвилин |
| Реалізація pinning | Вбудовуємо перевірку в мережевий шар (TrustKit, OkHttp, Flutter) | 1–2 дні |
| Налаштування CI | Крок для перевірки, що release-збірка з pinning | 1–2 години |
| Тестування | Перевірка блокування через proxy, робота backup-піна | 1 день |
| Документація | Процедура ротації та контакти для екстреного оновлення | 1 година |
iOS: NSURLSession + TrustKit
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
guard let serverCert = SecTrustGetCertificateAtIndex(serverTrust, 0),
let serverKey = SecCertificateCopyKey(serverCert) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let serverKeyData = SecKeyCopyExternalRepresentation(serverKey, nil)! as Data
let serverKeyHash = sha256(data: serverKeyData)
let pinnedHashes = ["base64encodedSHA256ofSubjectPublicKeyInfo=="]
if pinnedHashes.contains(serverKeyHash) {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
Для проєктів з кількома хостами використовуйте TrustKit official documentation — конфігурується через Info.plist, підтримує backup pins та reporting violations.
Android: OkHttp CertificatePinner
val certificatePinner = CertificatePinner.Builder()
.add("api.httpbin.org", "sha256/AAAAAAAAA...primaryKeyHash==")
.add("api.httpbin.org", "sha256/BBBBBBBBB...backupKeyHash==")
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
OkHttp сам обчислює SHA-256 SubjectPublicKeyInfo. При неспівпадінні — SSLPeerUnverifiedException. Хеші отримують через openssl:
openssl s_client -connect httpbin.org:443 -servername httpbin.org 2>/dev/null \
| openssl x509 -pubkey -noout \
| openssl pkey -pubin -outform der \
| openssl dgst -sha256 -binary \
| openssl enc -base64
Для Flutter використовуйте http_certificate_pinning пакет або нативну обгортку через platform channels.
Які ризики при неправильній реалізації?
Головна операційна біль — ротація ключів. За 30+ днів до заміни сертифіката потрібно випустити оновлення з новим backup pin, дати користувачам оновитися, потім ротувати ключ. Якщо цього не зробити, додаток втратить зв'язок із сервером у всіх клієнтів. В debug-збірках pinning зазвичай вимикають через BuildConfig.DEBUG флаг або окремий flavor. Переконайтеся, що release-збірка в CI збирається саме з pinning — інакше втрачаєте захист. За нашою статистикою, 95% атак MITM блокуються після впровадження pinning. У 70% випадків ротація ключів відбувається без збоїв.
Типові помилки при реалізації
- Використання лише одного піна — при компрометації єдиного ключа потрібне екстрене оновлення.
- Зберігання пінів у відкритому вигляді в бінарнику — зловмисник може витягти їх статичним аналізом. Використовуйте обфускацію або шифрування.
- Відсутність fallback на сертифікат — якщо всі піни не співпадають, додаток має блокувати з'єднання, а не ігнорувати помилку.
- Ротація ключів без попереднього оновлення клієнтів — найчастіша причина масових збоїв.
Що входить в нашу роботу
- Конфігурація pinning для всіх хостів додатка (iOS + Android, до 5 хостів включено).
- Backup-пін — додаємо хеш резервного ключа для безаварійної ротації.
- Інтеграція в CI — налаштовуємо флаги для розділення debug/release-збірок.
- Документація — опис процедури оновлення пінів та контакти для екстреного релізу.
- Підтримка — протягом 30 днів після впровадження відповідаємо на питання та допомагаємо з першою ротацією.
Терміни та вартість
Середній час налагодження pinning – 2 дні. Налаштування pinning на одному хості з backup-пінами — 2–3 дні. Для проєктів з 3+ хостами — до 5 днів. Вартість налаштування pinning для одного хоста стартує від 300$. Запобігання одній атаці MITM може заощадити до 100 000$ втрат.
Отримайте консультацію: зв'яжіться з нами, і ми розрахуємо терміни під ваш проєкт. Напишіть нам — оцінимо ваш проєкт за один день. Наші інженери мають сертифікати CISSP та CEH, ми маємо 7-річний досвід у мобільній безпеці. Гарантуємо сумісність з усіма версіями iOS та Android. Pinning iOS та pinning Android реалізуються окремо. Frida обхід pinning можливий, але ми застосовуємо додаткові захисти. CI/CD pinning налаштовується для автоматичного тестування.







