wiki/HowtoSSL.md

400 lines
17 KiB
Markdown
Raw Normal View History

---
title: Howto SSL
categories: security web
...
2016-10-21 00:33:21 +02:00
SSL (*Secure Sockets Layer*) est un protocole de sécurisation des échanges réseau.
Cela se base sur un principe de clé privée et clé publique (certificat) signée par une autorité de certification.
On parle désormais de **SSL/TLS** car les normes récentes ont renommé SSL en TLS (*Transport Layer Security*).
<https://www.openssl.org/docs/>
## Gestion clé privée / certificat
2016-10-21 00:33:21 +02:00
### Générer une demande de certificat (CSR)
Pour générer une clé privée non chiffrée (private.key) et sa demande de certificat associé (demande.csr) à transmettre à une autorité de certification :
~~~
$ openssl req -newkey rsa:2048 -sha256 -nodes -keyout private.key -out demande.csr
~~~
2016-10-21 00:33:21 +02:00
À des fins pédagogiques, on peut découper la cette génération en 2 étapes, à savoir la génération de la clé privée et la demande de certificat :
~~~
$ openssl genrsa -out private.key 2048
$ openssl req -new -sha256 -key private.key -out demande.csr
~~~
2016-10-21 00:33:21 +02:00
Pour générer une demande de certificat à partir d'un certificat existant (certificat.crt) :
~~~
2016-10-21 00:33:21 +02:00
$ openssl x509 -x509toreq -sha256 -in certificat.crt -out demande.csr -signkey private.key
~~~
### Générer un certificat auto-signé
1. Prérequis : avoir généré une clé et une demande de certificat (voir ci dessus)
2. Génération du certificat avec expiration dans 1000 jours :
~~~
$ openssl x509 -req -sha256 -days 1000 -in demande.csr -signkey private.key -out certificat.crt
~~~
Note : sous Debian, pour regénérer le certificat *snakeoil* (certificat autogénéré à l'installation) :
~~~
# make-ssl-cert generate-default-snakeoil --force-overwrite
~~~
### Générer un certificat multi-domaines avec subjectAltName
2016-10-21 00:33:21 +02:00
Un certificat avec **subjectAltName** permet d'ajouter des noms de domaine secondaires (*subjectAltName*) en plus du nom de domaine principal (*Common Name*), ce qui est supporté par 99.9% des navigateurs récents (mais cela coûte cher chez les autorités de certification).
Modifier une copie du fichier `/etc/ssl/openssl.cnf` avant de générer le certificat pour :
* Décommenter *req_extensions = v3_req*
* Dans la *section v3_req* mettre *subjectAltName = DNS:test1.example.com,DNS:test2.example.com,DNS:example.com*
Puis générer la clé privée et le certificat associé (avec expiration dans 1000 jours) :
~~~
$ openssl req -newkey rsa:2048 -nodes -x509 -sha256 -days 1000 -config openssl.cnf -extensions v3_req -keyout private.key -out certificat.crt
~~~
Si l'on veut plutôt une demande de certificat (pour transmettre à une autorité de certification) :
~~~
$ openssl req -newkey rsa:2048 -nodes -sha256 -days 1000 -config openssl.cnf -extensions v3_req -keyout private.key -out demande.csr
~~~
### "Déprotéger" une clé privée
Si une clé privée a été chiffrée (private.pem), on peut générer une version non chiffrée (private.key) ainsi :
~~~
$ openssl rsa -in private.pem -out private.key
$ rm private.pem
~~~
### Ajouter un mot de passe à une clé privée
~~~
$ openssl rsa -in private.pem -des3 -out private.key
writing RSA key
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
~~~
### Changer le mot de passe d'une clé privée
Il suffit de répéter les 2 étapes ci-dessus :
2016-10-21 00:33:21 +02:00
~~~
$ openssl rsa -in private.pem -out private.key
$ openssl rsa -in private.key -des3 -out private-new.pem
$ rm private.pem private.key
$ mv private-new.pem private.pem
~~~
### Convertir un certificat PEM vers d'autres formats
Voir <http://security.ncsa.illinois.edu/research/grid-howtos/usefulopenssl.html>
Notamment pour PKCS 12 (ou PFX) vers PEM :
~~~
$ openssl pkcs12 -in private.pfx -out private.pem
~~~
S'il s'agit de la clé :
~~~
$ openssl pkcs12 -in private.pfx -nocerts -out private.pem
~~~
### Utilisation de Let's Encrypt
Voir <http://trac.evolix.net/infogerance/wiki/HowtoLetsEncrypt>
## Vérifications
### Voir le contenu d'un certificat
Pour voir le contenu d'un certificat (certificat.crt) :
~~~
$ openssl x509 -text -in certificat.crt
~~~
Pour voir le contenu d'un certificat d'un service réseau :
~~~
$ openssl s_client -connect ssl.example.com:443
~~~
Pour voir le contenu d'une demande de certificat (demande.csr) :
~~~
$ openssl req -text -in demande.csr
~~~
Pour lire le format PFX :
~~~
2016-10-21 00:42:47 +02:00
$ openssl pkcs12 -info -in certificat.pfx
~~~
### Vérifier la correspondance entre clé privée / certificat / .csr
Pour s'assurer qu'un certificat est bien issu d'un clé privée, ou d'une demande de certificat (.csr), on peut vérifier la correspondance grâce au *modulus* que l'on peut extraire et comparer :
~~~
$ openssl x509 -noout -modulus -in certificat.crt | openssl md5
$ openssl rsa -noout -modulus -in private.key | openssl md5
$ openssl req -noout -modulus -in demande.csr | openssl md5
~~~
Si toutes les empreintes MD5 sont identiques, on est sûr que c'est issu de la clée privée.
Pour vérifier en une seule commande :
~~~
$ diff <(openssl rsa -in private.key -modulus | grep Modulus) <(openssl x509 -in certificate.crt -modulus | grep Modulus)
~~~
### Vérifier qu'un certificat n'est pas révoqué
Il faut d'abord trouver quel serveur OCSP est déclaré :
~~~
$ openssl x509 -noout -ocsp_uri -in certificate.crt
http://ocsp.example.com
~~~
Puis, interroger le serveur OCSP obtenu (ici http://ocsp.example.com) avec la chaine de certification (chainfile.pem) et le certificat (certificat.crt) à vérifier :
~~~
$ openssl ocsp -issuer chainfile.pem -cert certificat.crt -text -url http://ocsp.example.com -header "HOST" "www.example.com"
~~~
Dans le cas d'un certificat révoqué on verra les lignes suivantes :
~~~
Cert Status: revoked
Revocation Time: Nov 2 09:30:00 2014 GMT
~~~
### Vérifier la conformité d'un certificat en ligne de commande
*La vérification en ligne de commande nécessite une machine GNU/Linux.*
Pour vérifier un fichier de certificat en ligne de commande :
~~~
$ openssl verify -CApath /etc/ssl/certs certificat.crt
~~~
Pour vérifier la conformité d'un certificat d'un service réseau en ligne de commande :
~~~
$ openssl s_client -CApath /etc/ssl/certs -connect ssl.example.com:443
~~~
Pour un service réseau en STARTTLS (exemple avec SMTP, valable aussi pour POP3/IMAP/FTP) :
~~~
$ openssl s_client -CApath /etc/ssl/certs -connect mail.site.com:25 -crlf -starttls smtp
~~~
Pour un service en HTTPS avec l'option SNI qui permet d'envoyer un nom de domaine au sein du protocole SSL/TLS (supporté par 99.9% des navigateurs récents) :
~~~
$ openssl s_client -CApath /etc/ssl/certs -servername ssl.example.com -connect 192.0.2.42:443
~~~
2016-10-21 00:33:21 +02:00
**Le certificat est conforme avec votre base locale de certificats CA si vous obtenez `Verify return code: 0 (ok)` **
Si le code de retour est différent de 0, le certificat n'est pas conforme pour différentes raisons :
* *Verify return code: 21 (unable to verify the first certificate)* : le certificat distant est signé par un certificat CA qui n'est pas dans votre base locale *ou* utilise un certificat intermédiaire inconnu (Note: il peut y avoir toute une chaîne de certification avec plusieurs certificats intermédiaires)
Un script Bash permet également d'effectuer des vérifications : <https://github.com/drwetter/testssl.sh>
### Vérifier la conformité d'un certificat via des services externes
Nous conseillons d'utiliser l'outil complet SSL LABS : <https://www.ssllabs.com/ssltest/analyze.html>
D'autres outils également utiles :
* Pour une vérification simple (conforme ou non): <https://ssltools.thawte.com/checker/views/certCheck.jsp>
* Pour une vérification de la châine de certification : <https://whatsmychaincert.com/>
* Pour une vérification avancée : <https://ssldecoder.org/>
* Pour une vérification SSL/TLS orientée SMTP : <https://tls.imirhil.fr>
## Louer un certificat auprès d'une autorité de certificat
État du marche en 2015 : <http://www.netcraft.com/internet-data-mining/ssl-survey/>
2016-10-21 00:33:21 +02:00
Pour louer un certificat lié à **UN** enregistrement DNS :
* 0 EUR/an : Let's Encrypt <https://letsencrypt.org/>
2016-10-26 19:02:12 +02:00
* 0 EUR/an : StartCom/StartSSL Free : <https://www.startssl.com/Support?v=1> (attention, [cela pose des soucis avec Firefox](HowtoSSL#à-propos-de-startcomstartssl))
2016-10-21 00:33:21 +02:00
* 8.20 EUR/an : Comodo PositiveSSL : <http://www.namecheap.com/ssl-certificates/comodo/positivessl-certificate.aspx>
* 12 EUR/an : Gandi SSL standard : <http://www.gandi.net/ssl/standard#single>
* 129 EUR/an : Thawte SSL123 : <http://www.thawte.fr/ssl/ssl123-ssl-certificates/>
2016-10-21 00:33:21 +02:00
Pour louer un certificat « wildcard » (pour une infinité de sous-domaines du type `*.example.com`) :
2016-10-21 00:33:21 +02:00
* 85.62 EUR/an : Comodo PositiveSSL : <http://www.namecheap.com/ssl-certificates/comodo/positivessl-wildcard-certificate.aspx>
* 120 EUR/an : Gandi SSL standard : <http://www.gandi.net/ssl/standard#wildcard>
* 449 EUR/an : Thawte SSL Web Server Wildcard : <http://www.thawte.fr/ssl/wildcard-ssl-certificates/>
Pour louer un certificat multi-domaines :
2016-10-21 00:33:21 +02:00
* 40 EUR/an (pour 3 enregistrements DNS) et jusqu'à 210 EUR/an (30 enregistrements DNS) : <https://www.gandi.net/ssl/standard#multi>
* 129 EUR + <99 EUR/an : Thawte SSL123 avec SAN : <http://www.thawte.fr/ssl/ssl123-ssl-certificates/>
Pour louer un certificat EV :
2016-10-21 00:33:21 +02:00
* 249 EUR/an : Thawte SSL Web Server avec EV : <https://www.thawte.fr/ssl/extended-validation-ssl-certificates/>
2016-10-21 00:33:21 +02:00
### À propos de StartCom/StartSSL
2016-10-21 00:33:21 +02:00
Il faut noter que l'offre *StartStartSSL Free* de StartCom est bien gratuite mais il y a plusieurs inconvénients :
2016-10-21 00:33:21 +02:00
* StarCom/StartSSL a été [racheté en 2016 par l'autorité de certification chinoise WoSign](https://www.wosign.com/english/News/WoSign_completed_equity_investment_to_StartCom_CA.htm) qui [a de nombreux problèmes selon la fondation Mozilla](https://wiki.mozilla.org/CA:WoSign_Issues)... ce qui a pour conséquence que [Mozilla envisage de retirer les certificats CA de StartSSL](https://groups.google.com/forum/?nomobile=true#!topic/mozilla.dev.security.policy/BV5XyFJLnQM), notamment [Firefox 51 devrait bannir les certificats émis par StartCom/StartSSL à partir du 21 octobre 2016 !!](https://bugzilla.mozilla.org/show_bug.cgi?id=1311832)
* les certificats gratuits mentionnent les informations personnelles de la personne physique qui a créé le compte
* la gestion du renouvellement est lourde (votre compte expire tous les ans, et vous ne pouvez le renouveler que quelques jours avant...)
* vous pouvez créer uniquement des certificats liés à la personne physique qui a créé le compte (nom de domaine qui vous appartient personnellement ou appartient à votre société) : si vous créez plusieurs certificats pour le compte d'autres sociétés (vos clients par exemple) StartSSL finira pas rejeter vos demandes et vous devrez créer un compte pour chaque société
* la révocation d'un certificat est payante (environ 20 EUR)
2016-10-21 00:33:21 +02:00
* différents problèmes et bugs, voir [#FAQ]()
L'avantage de StartSSL est que pour 150 EUR/an, vous pouvez obtenir la validation « Organization » (après une lourde procédure de vérifications) et créer ensuite une infinité de certificats Wildcard valables 3 ans.
### À propos de Let's Encrypt
Let's Encrypt est un jeune projet qui a pour but de démocratiser l'usage de SSL/TLS pour le web en fournissant facilement des certificats gratuits.
Pour plus de détails voir <http://trac.evolix.net/infogerance/wiki/HowtoLetsEncrypt>
## Sécurité et qualité des certificats
2016-10-21 00:33:21 +02:00
### Failles de sécurité
2016-10-26 19:02:12 +02:00
Plusieurs failles de sécurité ont touché SSL/TLS ou le logiciel OpenSSL ces dernières années,
il convient donc de traiter avec attention la question de la configuration au sein des différents logiciels.
2016-10-21 00:33:21 +02:00
#### Faille PODDLE
2016-10-26 19:02:12 +02:00
La faille POODLE (adding Oracle On Downgraded Legacy Encryption) est une vulnérabilité touchant le protocole SSL version 3.0 permettant une attaque *man-in-the-middle*. Elle a été révélée en octobre 2014 et il y a eu une vague de désactivation du protocole SSLv3, voir <http://disablessl3.com/>.
* Désactiver SSL 3.0 pour Apache : `SSLProtocol all -SSLv2 -SSLv3`
* Désactiver SSL 3.0 pour Nginx 0.7 : `ssl_protocols TLSv1;`
* Désactiver SSL 3.0 pour Nginx 1.2 : `ssl_protocols TLSv1 TLSv1.1 TLSv1.2;`
* Désactiver SSL 3.0 pour Postfix : `smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3 smtp_tls_mandatory_protocols=!SSLv2,!SSLv3 smtpd_tls_protocols=!SSLv2,!SSLv3 smtp_tls_protocols=!SSLv2,!SSLv3`
2016-10-21 00:33:21 +02:00
#### Faille FREAK
2016-10-26 19:02:12 +02:00
La faille FREAK (Factoring RSA Export Keys) est une vulnérabilité dans OpenSSL permettant une attaque *man-in-the-middle* pour renégocier
un chiffrement faible. Cela se base sur des chiffrements « EXPORT » introduits dans les années 2000 par les USA pour pouvoir déchiffrement les communications. Voir <http://blog.cryptographyengineering.com/2015/03/attack-of-week-freak-or-factoring-nsa.html>, <https://freakattack.com/#sysadmin> et <https://www.smacktls.com/>.
On peut tester si un serveur accepte les chiffrements EXPORT avec la commande suivante :
~~~{.bash}
$ openssl s_client -connect example.com:443 -cipher EXPORT
~~~
Si on obtient *error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:749* c'est que le serveur n'accepte pas les chiffrements EXPORT.
Debian [a corrigé cette faille en janvier2015](https://security-tracker.debian.org/tracker/CVE-2015-0204), ce qui est surtout important pour les clients (navigateurs, etc.). On peut vérifier que sa machine ne tolère pas de chiffrements « EXPORT » via la commande `openssl ciphers | tr -s ':' '\n' | sort | grep EXP`. Sous Debian, par défaut Apache et Nginx n'ont pas été impactés car leur liste de chiffrement n'incluait pas EXPORT.
2016-10-21 00:33:21 +02:00
### Avoir A+ sur SSL LABS
2016-10-26 19:38:58 +02:00
L'outil https://www.ssllabs.com/ssltest/analyze.html permet d'avoir une note symbolique sur la configuration de son serveur HTTPS.
Voici les principaux critères sur une installation classique :
- Il faut que le certificat et le certificat intermédiaire soit signé en SHA256, le SHA1 est déprécié ;
Astuce pour StartSSL, le certificat intermédiaire signé en SHA256 est disponible ici : https://www.startssl.com/certs/class1/sha2/pem/sub.class1.server.sha2.ca.pem (class1) ou https://www.startssl.com/certs/class2/sha2/pem/sub.class2.server.sha2.ca.pem (class2)
- Il faut désactiver les chiffrements dits « faibles », et ajouter un header Strict-Transport-Security pour indiquer que le site n'est consultable qu'en HTTPS.
- paramètres DH au moins 2048 (impossible en Debian 7/Apache)
- Activer le cache pour la reprise de session.
*-Avoir un certificat de >=4096 bits, ou un DH de >=4096 bits.
Générer le dhparam.pem ainsi (attention ça prend un temps fou) :
# openssl dhparam -out /etc/ssl/dhparam.pem 4096
2016-10-21 00:33:21 +02:00
#### Configuration Apache
2016-10-26 19:38:58 +02:00
En pratique avec Apache :
~~~
SSLCipherSuite AES128+EECDH:AES128+EDH
SSLProtocol All -SSLv2 -SSLv3
SSLHonorCipherOrder On
SSLCompression off
#Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
SSLSessionCache shm:/var/log/apache2/ssl_gcache_data(512000) ???
SSLSessionCacheTimeout 600 ???
~~~
Si votre Apache est trop vieux????, mettre le SSLCipherSuite suivant :
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4
2016-10-21 00:33:21 +02:00
#### Configuration Nginx
2016-10-26 19:38:58 +02:00
En pratique avec Nginx :
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "AES128+EECDH:AES128+EDH";
ssl_dhparam /etc/ssl/dhparam.pem;
#add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
ssl_session_cache shared:SSL:10m; ???
~~~
avec :
~~~
$ openssl dhparam -out /etc/ssl/dhparam.pem 2048
~~~
## FAQ
2016-10-21 00:33:21 +02:00
### Erreur "The OCSP server has no status for the certificate" avec StartSSL
2016-10-21 00:33:21 +02:00
Suite à la mise en place d'un nouveau certificat délivré par StartSSL, vous obtenez une erreur du type "An error occurred during a connection to ssl.example.com. The OCSP server has no status for the certificate. (Error code: sec_error_ocsp_unknown_cert) ?
StartSSL semble mettre entre 6 et 12h à propager ses nouveaux certificats sur son serveur OCSP. Il faut donc patienter…
### Bug avec Firefox et l'interface d'administration de StartSSL
Il y a un bug avec l'interface d'administration StartSSL avec Firefox (Firefox embarque un mauvais certificat). Voir le bug report <https://bugzilla.mozilla.org/show_bug.cgi?id=1037080> et une solution temporaire : <https://forum.startcom.org/viewtopic.php?p=8204#p8204>
2016-10-21 00:33:21 +02:00
Il faut supprimer le certificat "StartCom? Certification Authority" de l'autorité StartCom de type "Securité personne" (Software Security Device) dans les préférences de Firefox (Avancée --> Certificat). Voir <https://lut.im/EPSYOXoy/ckEgJEwU>
Une autre "astuce" est d'utiliser un autre navigateur…
2016-10-21 00:33:21 +02:00
### Ajouter des certificats CA sous Debian
Afin d'ajouter des certificats CA il faut copier les fichiers .crt dans `/usr/local/share/ca-certificates/` puis exécuter :
~~~
# dpkg-reconfigure ca-certificates
~~~