SSL Pinning è una tecnica di sicurezza in cui l'applicazione verifica il certificato del server rispetto a un'impronta digitale o certificato noto in anticipo, invece di affidarsi alla catena di fiducia della CA. A differenza della verifica standard, il pinning impedisce l'intercettazione del traffico attraverso centri di certificazione radice fraudolenti. Secondo la OWASP Mobile Security Testing Guide (2025), questa tecnica è tra i 3 controlli raccomandati per la protezione dagli attacchi MITM. Senza pinning, un attaccante con un certificato radice fraudolento può decifrare tutto il traffico HTTPS dell'applicazione.
Punti chiave
SSL Pinning è un meccanismo di sicurezza in cui un'applicazione mobile o web ricorda un certificato server affidabile o una chiave pubblica e rifiuta qualsiasi connessione il cui certificato non corrisponda a quello memorizzato. Nello schema HTTPS standard, il client verifica il certificato attraverso una catena di fiducia fino alla CA radice — qualsiasi CA può firmare un certificato per qualsiasi dominio. L'SSL Pinning elimina questa debolezza: invece di fidarsi di centinaia di CA, l'applicazione si fida solo di un certificato specifico.
Il problema della verifica standard è che qualsiasi delle centinaia di CA radice può emettere un certificato valido per il tuo dominio — accidentalmente o sotto coercizione. Un attaccante che ottiene accesso a un proxy aziendale con il proprio certificato radice può eseguire un attacco MITM senza avviso del browser. L'SSL Pinning chiude questa vulnerabilità: anche se una CA emette un certificato fraudolento, l'applicazione lo rifiuterà perché l'impronta digitale non corrisponde a quella registrata.
Nelle applicazioni mobili, l'SSL Pinning è particolarmente importante perché i dispositivi spesso operano su reti non sicure — Wi-Fi pubblico, proxy aziendali con ispezione del traffico, punti di accesso infetti. Secondo il Verizon Mobile Security Index (2025), oltre il 60% delle violazioni dei dati nelle applicazioni mobili è correlato all'intercettazione del traffico a livello di trasporto.
Le applicazioni mobili trasmettono dati sensibili — token di autenticazione, informazioni di pagamento, dati personali degli utenti. Senza protezione aggiuntiva, l'HTTPS può essere compromesso attraverso la sostituzione del certificato radice sul dispositivo — ad esempio, dopo l'installazione di un profilo aziendale o di un'applicazione dannosa. SSL Pinning garantisce che anche se una CA radice fraudolenta viene installata sul dispositivo, l'applicazione continuerà a verificare il certificato contro la propria whitelist.
Il processo di SSL Pinning consiste in tre fasi: acquisizione dell'impronta digitale, verifica alla connessione e gestione degli errori. Durante lo sviluppo, l'ingegnere ottiene l'impronta digitale SHA-256 del certificato del server (openssl x509 -fingerprint -sha256) e la incorpora nel codice dell'applicazione o nel file di configurazione. Ad ogni richiesta HTTPS, l'applicazione calcola l'impronta digitale del certificato ricevuto e la confronta con quella memorizzata — se i valori non corrispondono, la connessione viene terminata.
La prima fase è il pinning al momento della compilazione: lo sviluppatore conosce in anticipo i certificati del server e incorpora i loro hash. La seconda fase è il pinning alla prima connessione (trust on first use, TOFU): l'applicazione memorizza il certificato alla prima richiesta e lo utilizza per verificare tutte le successive. TOFU è conveniente per ambienti dinamici ma è vulnerabile al primo attacco — se la prima connessione è già intercettata, il certificato fraudolento verrà accettato come affidabile.
Un dettaglio critico sono i backup pins. I certificati hanno una data di scadenza e, quando vengono sostituiti, l'applicazione senza aggiornamento perderà la connessione al server. Gli ingegneri includono 2–3 impronte digitali aggiuntive — ad esempio, l'impronta digitale di un certificato di backup e l'impronta digitale della CA radice. Se il certificato principale cambia, l'applicazione verifica contro i backup pins e la connessione continua a funzionare.
# Ottenere l'impronta digitale SHA-256 del certificato
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
Esistono due approcci principali per implementare il pinning: fissaggio all'intero certificato (certificate pinning) e fissaggio alla chiave pubblica (public key pinning). Ogni approccio ha i propri punti di forza e limitazioni che influenzano la sicurezza e la manutenibilità.
| Tipo | Oggetto di fissaggio | Flessibilità | Sicurezza |
|---|---|---|---|
| Certificate Pinning | Certificato X.509 completo | Bassa — richiede aggiornamento quando il certificato cambia | Alta — fissaggio preciso |
| Public Key Pinning | Chiave pubblica del certificato | Media — la chiave può essere in un nuovo certificato | Alta — meno sensibile ai dettagli del certificato |
| Hash Pinning | Hash SHA-256 del certificato o chiave | Alta — si possono cambiare i certificati senza cambiare la chiave | Media — dipende dalla robustezza dell'hash |
Il fissaggio del certificato è il metodo più rigoroso. L'applicazione memorizza una copia del certificato affidabile o della sua impronta digitale SHA-256 e la confronta con il certificato del server ad ogni connessione HTTPS. Questo metodo fornisce la massima sicurezza ma crea problemi durante la rotazione — i certificati durano generalmente 1–2 anni, dopo i quali è necessario un aggiornamento forzato dell'applicazione. Raccomandato per sistemi critici con ciclo di aggiornamento controllato.
Il fissaggio della chiave pubblica è un approccio più flessibile. Invece dell'intero certificato, l'applicazione ricorda solo la chiave pubblica RSA o ECDSA del server. La chiave può rimanere invariata quando il certificato viene riemesso, se l'azienda utilizza la stessa coppia di chiavi. Questo riduce la frequenza degli aggiornamenti dell'applicazione. Tuttavia, se la chiave viene compromessa, sarà necessaria una sostituzione a cascata su tutti i client.
Sulla piattaforma Apple, l'SSL Pinning viene implementato tramite il delegato URLSession. Lo sviluppatore crea una classe che implementa il protocollo URLSessionDelegate e sovrascrive il metodo didReceive challenge, dove verifica manualmente il certificato del server contro le impronte digitali memorizzate. Un approccio alternativo è l'utilizzo di Alamofire con ServerTrustManager, che semplifica la configurazione.
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)
}
}
}
Nell'esempio, il delegato riceve una richiesta di autenticazione da URLSession, estrae serverTrust dalla challenge e confronta l'impronta digitale SHA-256 del certificato con quella memorizzata. Se l'impronta corrisponde — la connessione prosegue, altrimenti la challenge viene rifiutata. Per la produzione, vale la pena aggiungere la verifica di più backup pins e la registrazione degli errori per il monitoraggio.
A partire da iOS 14, Apple ha aggiunto il supporto integrato per Certificate Pinning tramite Info.plist. Lo sviluppatore specifica i certificati affidabili nella chiave NSAppTransportSecurity con il sottodizionario NSPinnedDomains. Questo approccio non richiede scrittura di codice ma è meno flessibile — è impossibile cambiare dinamicamente i pin o registrare gli errori di verifica.
Su Android, esistono tre modi principali per implementare SSL Pinning: tramite CertificatePinner della libreria OkHttp, tramite Network Security Config in XML e tramite verifica personalizzata in HttpsURLConnection. OkHttp è l'approccio più popolare e raccomandato, utilizzato in Retrofit e altri client HTTP.
val certificatePinner = CertificatePinner.Builder()
.add("api.example.com",
"sha256/Wi24BE7j5qLk0iLvPq6ePEsVRqZ1yW0F6wLg=")
.add("api.example.com",
"sha256/FiPq6ePEsVRqZ1yW0F6wLgWi24BE7j5qLk0iL=") // backup pin
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
Nella configurazione OkHttp, lo sviluppatore specifica il dominio e una o più impronte digitali SHA-256. Alla prima impronta digitale, OkHttp confronta il certificato del server con i pin specificati. Se non c'è corrispondenza, il client lancia SSLPeerUnverifiedException. Un backup pin è obbligatorio — senza di esso, quando il certificato cambia, le richieste API inizieranno a fallire immediatamente.
Android supporta il Certificate Pinning dichiarativo tramite configurazione XML a partire dall'API 24. Il file res/xml/network_security_config.xml contiene un elenco di domini e le loro impronte digitali. Questo metodo è conveniente per configurazioni statiche ma non consente di implementare TOFU o logica di verifica personalizzata con registrazione delle anomalie.
<!-- 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>
L'SSL Pinning aumenta significativamente la sicurezza di un'applicazione mobile ma introduce complessità operative. Il vantaggio principale è la protezione dagli attacchi MITM anche quando le CA radice sono compromesse. L'applicazione si fida solo di quei certificati esplicitamente specificati dallo sviluppatore, non dell'intera infrastruttura delle autorità di certificazione pubbliche. Questo è particolarmente critico per applicazioni finanziarie, messaggistica e applicazioni con dati sensibili.
Lo svantaggio principale è la complessità della rotazione dei certificati. Se un certificato scade o viene revocato, gli utenti senza aggiornamento dell'applicazione perdono la connessione. Questo viene risolto tramite backup pins e un meccanismo di aggiornamento graduale: la nuova applicazione conosce sia i certificati vecchi che quelli nuovi e, dopo un aggiornamento completo degli utenti, il pin vecchio viene rimosso dal codice. Si raccomanda di includere almeno 2 backup pins — uno per il certificato corrente, uno per il futuro.
Un altro compromesso è l'impossibilità di utilizzare proxy pubblici per il debug del traffico (Charles Proxy, Burp Suite) senza disabilitare il pinning. Questo complica il debug delle richieste di rete durante lo sviluppo. La soluzione è la compilazione condizionale: il pinning è disabilitato nelle build di debug e abilitato nelle build di release. OWASP raccomanda di utilizzare il flag BuildConfig.DEBUG per il passaggio.
| Aspetto | Vantaggio | Svantaggio |
|---|---|---|
| Sicurezza | Protezione da MITM tramite CA fraudolente | Complessità quando una chiave è compromessa |
| Manutenzione | Controllo esplicito della fiducia | La rotazione richiede aggiornamento dell'applicazione |
| Debug | Connessione garantita al server corretto | Blocca i proxy di debug |
Domande frequenti
La verifica HTTPS standard si fida di qualsiasi certificato firmato da una CA radice nota. L'SSL Pinning si fida solo di un certificato specifico o chiave — se una CA emette un certificato fraudolento, l'applicazione lo rifiuterà.
I certificati durano generalmente 1–2 anni. Si consiglia di aggiornare i pin 3–6 mesi prima della scadenza del certificato corrente, aggiungendo la nuova impronta digitale come backup pin e rimuovendo quella vecchia dopo la rotazione.
Sì, ma bisogna considerare che la CDN può cambiare i certificati quando passa tra server edge. Si consiglia di fissarsi alla chiave pubblica piuttosto che a un certificato specifico e utilizzare più backup pins.
La connessione viene terminata con un errore — su Android è SSLPeerUnverifiedException, su iOS la challenge viene rifiutata con .cancelAuthenticationChallenge. L'applicazione deve gestire correttamente questo errore e notificare l'utente.
No, ma OWASP lo raccomanda per le applicazioni che gestiscono dati sensibili: banking, sanità, sistemi aziendali. Per semplici applicazioni di sola lettura, la verifica HTTPS standard con certificati EV è solitamente sufficiente.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche