SSL Pinning — техніка безпеки, за якої додаток перевіряє сертифікат сервера за заздалегідь відомим відбитком або сертифікатом, а не покладається на ланцюжок довіри CA. На відміну від стандартної перевірки, pinning запобігає перехопленню трафіку через підмінені кореневі центри сертифікації. За даними OWASP Mobile Security Testing Guide (2025), ця техніка входить до топ-3 рекомендованих засобів контролю для захисту від MITM-атак. Без pinning атакуючий із підміненим кореневим сертифікатом може розшифрувати весь HTTPS-трафік додатка.
Головне
SSL Pinning — це механізм безпеки, за якого мобільний або веб-додаток запам'ятовує довірений сертифікат або відкритий ключ сервера та відхиляє будь-які з'єднання, сертифікат яких не збігається зі збереженим. У стандартній схемі HTTPS клієнт перевіряє сертифікат через ланцюжок довіри до кореневого CA — будь-який CA може підписати сертифікат для будь-якого домену. SSL Pinning усуває це слабке місце: замість довіри сотням CA додаток довіряє лише одному конкретному сертифікату.
Проблема стандартної перевірки в тому, що будь-який із сотень кореневих CA може випустити дійсний сертифікат для вашого домену — випадково або за примусом. Атакуючий, який отримав доступ до корпоративного проксі з власним кореневим сертифікатом, може проводити MITM-атаку без попередження браузера. SSL Pinning закриває цю вразливість: навіть якщо CA випустив підмінений сертифікат, додаток його відхилить, оскільки відбиток не збігається із зафіксованим.
У мобільних додатках SSL Pinning особливо важливий, тому що пристрої часто працюють у незахищених мережах — громадський Wi-Fi, корпоративні проксі з інспекцією трафіку, заражені точки доступу. За даними Verizon Mobile Security Index (2025), понад 60% витоків даних у мобільних додатках пов'язані з перехопленням трафіку на транспортному рівні.
Мобільні додатки передають чутливі дані — токени автентифікації, платіжну інформацію, персональні дані користувачів. Без додаткового захисту HTTPS може бути скомпрометований через підміну кореневого сертифіката на пристрої — наприклад, після встановлення корпоративного профілю або шкідливого додатка. SSL Pinning гарантує, що навіть якщо на пристрої встановлено підмінений кореневий CA, додаток продовжить перевіряти сертифікат за власним whitelist.
Процес SSL Pinning складається з трьох етапів: захоплення відбитка, перевірка при з'єднанні та обробка помилки. На етапі розробки інженер отримує SHA-256 відбиток сертифіката сервера (openssl x509 -fingerprint -sha256) і вбудовує його в код додатка або конфігураційний файл. При кожному HTTPS-запиті додаток обчислює відбиток отриманого сертифіката та порівнює його зі збереженим — якщо значення не збігаються, з'єднання розривається.
Перший етап — піннінг на етапі збірки: розробник заздалегідь знає сертифікати сервера та вбудовує їх хеші. Другий етап — піннінг при першому з'єднанні (trust on first use, TOFU): додаток запам'ятовує сертифікат при першому запиті та використовує його для перевірки всіх наступних. TOFU зручний для динамічних середовищ, але вразливий при першій атаці — якщо перше з'єднання вже перехоплено, підмінений сертифікат буде прийнято як довірений.
Критична деталь — резервні відбитки (backup pins). Сертифікати мають термін дії, і при їх заміні додаток без оновлення втратить з'єднання з сервером. Інженери закладають 2–3 додаткових відбитки — наприклад, відбиток резервного сертифіката та відбиток кореневого CA. Якщо основний сертифікат змінюється, додаток перевіряє за backup pins, і з'єднання продовжує працювати.
# Отримання SHA-256 відбитка сертифіката
openssl s_client -connect example.com:443 </dev/null 2>/dev/null | \
openssl x509 -pubkey -noout | \
openssl pkey -pubin -outform der | \
openssl dgst -sha256 -binary | \
base64
Розрізняють два основних підходи до реалізації піннінгу: прив'язка до сертифіката цілком (certificate pinning) та прив'язка до відкритого ключа (public key pinning). Кожен підхід має свої сильні сторони та обмеження, що впливають на безпеку та зручність супроводу.
| Тип | Об'єкт фіксації | Гнучкість | Безпека |
|---|---|---|---|
| Certificate Pinning | Весь сертифікат X.509 | Низька — при зміні сертифіката потрібне оновлення | Висока — точна прив'язка |
| Public Key Pinning | Відкритий ключ сертифіката | Середня — ключ може бути в новому сертифікаті | Висока — менш чутливий до деталей сертифіката |
| Hash Pinning | SHA-256 хеш сертифіката або ключа | Висока — можна міняти сертифікати без зміни ключа | Середня — залежить від стійкості хеша |
Прив'язка до сертифіката — найсуворіший метод. Додаток зберігає копію довіреного сертифіката або його SHA-256 відбиток і порівнює з сертифікатом сервера при кожному HTTPS-з'єднанні. Цей метод забезпечує максимальну безпеку, але створює проблеми при ротації — сертифікати зазвичай діють 1–2 роки, після чого потрібне примусове оновлення додатка. Рекомендується для критичних систем із контрольованим циклом оновлення.
Фіксація відкритого ключа — більш гнучкий підхід. Замість цілого сертифіката додаток запам'ятовує лише відкритий ключ RSA або ECDSA сервера. Ключ може залишатися незмінним при перевипуску сертифіката, якщо компанія використовує ту саму ключову пару. Це знижує частоту оновлень додатка. Однак якщо ключ скомпрометовано, знадобиться каскадна заміна на всіх клієнтах.
На платформі Apple SSL Pinning реалізується через делегат URLSession. Розробник створює клас, що реалізує протокол URLSessionDelegate, і перевизначає метод didReceive challenge, де вручну перевіряє сертифікат сервера проти збережених відбитків. Альтернативний підхід — використання Alamofire з ServerTrustManager, який спрощує конфігурацію.
class SSLPinningDelegate: NSObject, URLSessionDelegate {
let pinnedHash = "sha256/Wi24BE7j5qLk0iLvPq6ePEsVRqZ1yW0F6wLg="
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust
else { return completionHandler(.cancelAuthenticationChallenge, nil) }
if validate(serverTrust, pinnedHash) {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
У прикладі делегат отримує запит на автентифікацію від URLSession, витягує serverTrust із challenge та порівнює SHA-256 відбиток сертифіката зі збереженим. Якщо відбиток збігається — з'єднання продовжується, інакше challenge відхиляється. Для продакшену варто додати перевірку кількох backup pins та логування помилок для моніторингу.
Починаючи з iOS 14, Apple додала вбудовану підтримку Certificate Pinning через Info.plist. Розробник вказує довірені сертифікати в ключі NSAppTransportSecurity з підсловником NSPinnedDomains. Цей підхід не потребує написання коду, але менш гнучкий — неможливо динамічно змінювати pins або логувати помилки перевірки.
На Android існує три основних способи реалізації SSL Pinning: через CertificatePinner бібліотеки OkHttp, через Network Security Config у XML та через кастомну перевірку в HttpsURLConnection. OkHttp — найпопулярніший і рекомендований підхід, що використовується в Retrofit та інших HTTP-клієнтах.
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com",
"sha256/Wi24BE7j5qLk0iLvPq6ePEsVRqZ1yW0F6wLg=")
.add("api.example.com",
"sha256/FiPq6ePEsVRqZ1yW0F6wLgWi24BE7j5qLk0iL=") // резервний пін
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
У конфігурації OkHttp розробник вказує домен та один або кілька SHA-256 відбитків. При першому відбитку OkHttp порівнює сертифікат сервера з вказаними pins. Якщо збігу немає, клієнт викидає SSLPeerUnverifiedException. Backup pin обов'язковий — без нього при зміні сертифіката API-запити одразу почнуть падати.
Android підтримує декларативний Certificate Pinning через XML-конфігурацію починаючи з API 24. Файл res/xml/network_security_config.xml містить список доменів та їх відбитків. Цей метод зручний для статичних конфігурацій, але не дозволяє реалізувати TOFU або кастомну логіку перевірки з логуванням аномалій.
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2027-12-31">
<pin digest="SHA-256">
Wi24BE7j5qLk0iLvPq6ePEsVRqZ1yW0F6wLg=</pin>
<pin digest="SHA-256">
FiPq6ePEsVRqZ1yW0F6wLgWi24BE7j5qLk0iL=</pin>
</pin-set>
</domain-config>
</network-security-config>
SSL Pinning значно підвищує безпеку мобільного додатка, але вводить операційні складнощі. Головний плюс — захист від MITM-атак навіть при компрометації кореневих CA. Додаток довіряє лише тим сертифікатам, які явно вказані розробником, а не всій інфраструктурі публічних центрів сертифікації. Це особливо критично для фінансових додатків, месенджерів та додатків із чутливими даними.
Основний мінус — складність ротації сертифікатів. Якщо сертифікат закінчується або відкликається, користувачі без оновлення додатка втрачають з'єднання. Вирішується через backup pins та механізм поступового оновлення: новий додаток знає старий і новий сертифікати, а після повного оновлення користувачів старий pin видаляється з коду. Рекомендується закладати мінімум 2 backup pins — один для поточного сертифіката, один для майбутнього.
Ще один компроміс — неможливість використовувати публічні проксі для налагодження трафіку (Charles Proxy, Burp Suite) без відключення піннінгу. Це ускладнює налагодження мережевих запитів на етапі розробки. Рішення — умовна компіляція: у debug-збірці піннінг вимкнено, у release — увімкнено. OWASP рекомендує використовувати прапорець BuildConfig.DEBUG для перемикання.
| Аспект | Перевага | Недолік |
|---|---|---|
| Безпека | Захист від MITM через підмінені CA | Складність при компрометації ключа |
| Супровід | Явний контроль довіри | Ротація потребує оновлення додатка |
| Налагодження | Гарантія з'єднання з правильним сервером | Блокування налагоджувальних проксі |
Часті запитання
Стандартна перевірка HTTPS довіряє будь-якому сертифікату, підписаному відомим кореневим CA. SSL Pinning довіряє лише конкретному сертифікату або ключу — якщо CA випустить підмінений сертифікат, додаток його відхилить.
Сертифікати зазвичай діють 1–2 роки. Рекомендується оновлювати pins за 3–6 місяців до закінчення поточного сертифіката, додаючи новий відбиток як backup pin, а після ротації видаляти старий.
Так, але потрібно враховувати, що CDN може змінювати сертифікати при перемиканні між edge-серверами. Рекомендується прив'язуватися до відкритого ключа, а не до конкретного сертифіката, та використовувати кілька backup pins.
З'єднання розривається з помилкою — на Android це SSLPeerUnverifiedException, на iOS challenge відхиляється з .cancelAuthenticationChallenge. Додаток повинен коректно обробити цю помилку та повідомити користувача.
Ні, але OWASP рекомендує його для додатків, що працюють із чутливими даними: банкінг, медицина, корпоративні системи. Для простих read-only додатків стандартної HTTPS-перевірки з сертифікатами EV зазвичай достатньо.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також