Le certificate pinning est une technique de sécurité avancée qui va au-delà de la validation TLS standard. Elle attache les applications à des certificats ou clés publiques spécifiques.
Cette technique fournit une protection supplémentaire mais introduit des complexités opérationnelles significatives.
Qu'est-ce que le Certificate Pinning
Dans la validation TLS normale, un client accepte tout certificat valide émis par une CA de confiance. Avec le pinning, le client n'accepte que des certificats correspondant à des valeurs prédéfinies.
Niveaux de pinning
- Pinning de certificat : pine le certificat exact - tout changement nécessite une mise à jour de l'application
- Pinning de clé publique : pine la clé publique - permet les renouvellements tant que la même paire de clés est utilisée
- Pinning de CA : pine la CA émettrice - permet n'importe quel certificat de cette CA
Comparaison des approches
| Approche | Flexibilité | Sécurité | Risque opérationnel |
|---|---|---|---|
| Certificat | Faible | Maximale | Élevé |
| Clé publique | Moyenne | Élevée | Moyen |
| CA | Élevée | Modérée | Faible |
Avantages de Sécurité du Pinning
Le pinning protège contre plusieurs vecteurs d'attaque sophistiqués.
Attaques mitigées
- CA compromise : un attaquant qui compromet une CA et émet des certificats frauduleux sera bloqué
- Interception d'entreprise : les CAs internes installées pour intercepter le trafic sont ignorées
- Man-in-the-middle : les certificats dérivés de CAs compromises ou malveillantes sont rejetés
Cas d'usage pertinents
Le pinning est particulièrement utile pour :
- Applications mobiles où l'environnement du périphérique est moins contrôlé
- Applications manipulant des données hautement sensibles
- Communications serveur à serveur critiques
Comment Implémenter le Pinning
L'implémentation varie selon la plateforme et l'approche choisie.
Applications iOS
// Exemple avec URLSession
class PinningDelegate: NSObject, URLSessionDelegate {
let pinnedPublicKeyHash = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
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
}
// Vérifier le hash de la clé publique
let publicKey = SecCertificateCopyKey(certificate)
// ... validation du hash
}
}
Applications Android
// Exemple avec OkHttp
val certificatePinner = CertificatePinner.Builder()
.add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.add("example.com", "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=") // Backup
.build()
val client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build()
Obtenir le hash de la clé publique
# Extraire le hash SHA256 de la clé publique
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | \
openssl x509 -pubkey -noout | \
openssl pkey -pubin -outform DER | \
openssl dgst -sha256 -binary | \
base64
HPKP (déprécié)
HTTP Public Key Pinning existait pour les applications web mais a été déprécié :
# Ne plus utiliser - pour référence historique uniquement
Public-Key-Pins: pin-sha256="base64=="; max-age=5184000; includeSubDomains
Bonnes Pratiques et Risques
Si vous implémentez le pinning, suivez ces recommandations pour minimiser les risques.
Règles essentielles
- Pinez toujours des pins de secours : au moins un pin de backup non utilisé actuellement
- Préférez le pinning de clé publique : permet le renouvellement des certificats
- Implémentez du reporting : sachez quand les échecs de pin se produisent
- Planifiez la rotation : procédures documentées et testées régulièrement
Mécanismes de récupération
- Prévoyez un court-circuit de sécurité pour une récupération d'urgence
- Évitez les durées de pin trop longues qui compliquent la récupération
- Testez les procédures de rotation avant d'en avoir besoin
Alternatives modernes
Pour de nombreuses applications, le pinning peut ne pas être justifié :
- Certificate Transparency : fournit de la visibilité sur les émissions frauduleuses
- CAA Records : limitent quelles CAs peuvent émettre pour vos domaines
- Surveillance de CA : alertes sur les changements de certificat
; Enregistrement CAA DNS
example.com. CAA 0 issue "letsencrypt.org"
example.com. CAA 0 iodef "mailto:security@example.com"
Conclusion
Le certificate pinning fournit une sécurité améliorée contre certaines attaques sophistiquées. Mais il introduit une complexité opérationnelle significative et un risque de pannes auto-infligées.
Pour les applications de haute sécurité où le modèle de menace inclut des CAs compromises, le pinning peut être justifié. Pour la plupart des applications, les pratiques modernes comme Certificate Transparency offrent une protection adéquate avec moins de risque.