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, апликација наставља да проверава сертификат према сопственој белој листи.
Процес SSL Pinning-а се састоји од три фазе: преузимање отиска, провера при повезивању и обрада грешке. У фази развоја, инжењер добија SHA-256 отисак сертификата сервера (openssl x509 -fingerprint -sha256) и уграђује га у код апликације или конфигурациони фајл. При сваком HTTPS захтеву, апликација израчунава отисак примљеног сертификата и упоређује га са сачуваним — ако се вредности не поклапају, веза се прекида.
Прва фаза — pinning у фази изградње: програмер унапред зна сертификате сервера и уграђује њихове хешеве. Друга фаза — pinning при првом повезивању (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
Разликују се два основна приступа имплементацији pinning-а: везивање за цео сертификат (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) без искључивања pinning-а. Ово отежава отклањање грешака мрежних захтева у фази развоја. Решење — условна компилација: у debug издању pinning је искључен, у 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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође