426 lines
18 KiB
Markdown
426 lines
18 KiB
Markdown
---
|
|
title: Howto SSL
|
|
categories: security web
|
|
...
|
|
|
|
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/>
|
|
* <https://wiki.mozilla.org/Security/Server_Side_TLS>
|
|
|
|
## Installation
|
|
|
|
~~~
|
|
# apt install openssl
|
|
|
|
$ openssl version
|
|
OpenSSL 1.0.2h 3 May 2016
|
|
~~~
|
|
|
|
## Gestion clé privée / certificat
|
|
|
|
### 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
|
|
~~~
|
|
|
|
À 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
|
|
~~~
|
|
|
|
Pour générer une demande de certificat à partir d'un certificat existant (certificat.crt) :
|
|
|
|
~~~
|
|
$ 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
|
|
|
|
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 :
|
|
|
|
~~~
|
|
$ 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
|
|
~~~
|
|
|
|
### Convertir P7B vers CER
|
|
|
|
~~~
|
|
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
|
|
~~~
|
|
|
|
### Convertir DER vers PEM
|
|
|
|
~~~
|
|
openssl x509 -inform der -in certificate.cer -out certificate.pem
|
|
~~~
|
|
|
|
### Utilisation de Let's Encrypt
|
|
|
|
Voir [notre HowtoLetsEncrypt](https://wiki.evolix.org/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 :
|
|
|
|
~~~
|
|
$ 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 chaîne 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
|
|
~~~
|
|
|
|
Dans le cas où un proxy filtrant est utilisé, il faut bien penser à autoriser les domaines/IP des serveurs OCSP en question, sinon on récupère une erreur 403 et la requête OCSP n'est pas validée.
|
|
|
|
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.example.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
|
|
~~~
|
|
|
|
**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>
|
|
|
|
* Pour une vérification par divers scanners : <https://observatory.mozilla.org/>
|
|
|
|
## Louer un certificat auprès d'une autorité de certificat
|
|
|
|
Pour louer un certificat lié à **UN** enregistrement DNS :
|
|
|
|
* 0 EUR/an : Let's Encrypt <https://letsencrypt.org/>
|
|
* 0 EUR/an : StartCom/StartSSL Free : <https://www.startssl.com/Support?v=1> (attention, [cela pose des soucis avec Firefox](HowtoSSL#à-propos-de-startcomstartssl))
|
|
* 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/>
|
|
|
|
Pour louer un certificat « wildcard » (pour une infinité de sous-domaines du type `*.example.com`) :
|
|
|
|
* 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 :
|
|
|
|
* 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 par SAN/an : Thawte SSL123 avec SAN : <http://www.thawte.fr/ssl/ssl123-ssl-certificates/>
|
|
|
|
Pour louer un certificat EV :
|
|
|
|
* 249 EUR/an : Thawte SSL Web Server avec EV : <https://www.thawte.fr/ssl/extended-validation-ssl-certificates/>
|
|
|
|
### À propos de StartCom/StartSSL
|
|
|
|
Il faut noter que l'offre *StartStartSSL Free* de StartCom est bien gratuite mais il y a plusieurs inconvénients :
|
|
|
|
* 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)
|
|
* 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 [notre HowtoLetsEncrypt](https://wiki.evolix.org/HowtoLetsEncrypt)
|
|
|
|
## Sécurité et qualité des certificats
|
|
|
|
### Failles de sécurité
|
|
|
|
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.
|
|
Nous détaillons ci-dessous quelques failles célèbres, une liste de toutes les failles étant [disponible sur le wiki de Mozilla](https://wiki.mozilla.org/Security/Server_Side_TLS#Attacks_on_SSL_and_TLS).
|
|
|
|
#### Faille POODLE
|
|
|
|
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`
|
|
|
|
#### Faille FREAK
|
|
|
|
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 :
|
|
|
|
~~~
|
|
$ 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.
|
|
|
|
### Avoir A+ sur SSL LABS
|
|
|
|
L'outil <https://www.ssllabs.com/ssltest/analyze.html> permet d'avoir une note **symbolique** sur la configuration d'un serveur HTTPS.
|
|
|
|
Voici quelques critères pour avoir une bonne note :
|
|
|
|
- la taille de la clé privée est d'au moins 2048 bits (4096 bits est recommandé mais cela impacte les performances) ;
|
|
- le certificat et le(s) certificat(s) intermédiaire(s) utilisent des fonctions de hashage en SHA-2 (et non plus en SHA-1 qui est déprécié) ;
|
|
- le serveur HTTPS n'autorise pas l'utilisation d'algorithmes de chiffrement « faibles » avec le client (comme RC4, MD5, etc.) ;
|
|
- pour implémenter le principe de *Forward Secrecy*, le serveur HTTPS utilise des [paramètres DH (Diffie-Hellman) d'au moins 2048 bits](https://weakdh.org/) (ou 4096 bits si c'est la taille de la clé privée) ;
|
|
- le serveur HTTPS autorise le protocole TLS 1.2 ;
|
|
- le serveur HTTPS permet la [réutilisation des sessions SSL](https://vincent.bernat.im/fr/blog/2011-sessions-ssl-rfc5077.html) ;
|
|
- le serveur HTTPS support l'*OCSP stapling* ;
|
|
- un [entête *Strict-Transport-Security*](http://www.bortzmeyer.org/6797.html) indique que le site n'est consultable qu'en HTTPS pendant au moins 180 jours.
|
|
|
|
Plus généralement, on utilisera la documentation de référence <https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations> et notamment le [générateur de configuration SSL de Mozilla](https://mozilla.github.io/server-side-tls/ssl-config-generator/).
|
|
|
|
|
|
#### Configuration Apache
|
|
|
|
En pratique avec Apache (sous Debian 8), voici une configuration SSL avancée :
|
|
|
|
~~~{.apache}
|
|
SSLProtocol All -SSLv2 -SSLv3
|
|
SSLCipherSuite AES128+EECDH:AES128+EDH
|
|
SSLHonorCipherOrder On
|
|
SSLCompression off
|
|
#SSLSessionTickets off
|
|
SSLSessionCache shmcb:/var/log/apache2/ssl_sessioncache(10240000)
|
|
SSLUseStapling yes
|
|
SSLStaplingReturnResponderErrors off
|
|
SSLStaplingCache shmcb:/var/log/apache2/ssl_staplingcache(2048000)
|
|
Header always set Strict-Transport-Security "max-age=15552000"
|
|
~~~
|
|
|
|
#### Configuration Nginx
|
|
|
|
En pratique avec Nginx (sous Debian 8), voici une configuration SSL avancée :
|
|
|
|
~~~
|
|
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
|
ssl_ciphers "AES128+EECDH:AES128+EDH";
|
|
ssl_prefer_server_ciphers on;
|
|
#ssl_session_tickets off;
|
|
ssl_session_cache shared:SSL:10m;
|
|
ssl_session_timeout 1d;
|
|
ssl_stapling on;
|
|
ssl_stapling_verify on;
|
|
add_header Strict-Transport-Security "max-age=15552000";
|
|
ssl_dhparam /etc/ssl/dhparam.pem;
|
|
~~~
|
|
|
|
Note : il faut générer ses propres paramètres Diffie-Hellman ; pour des paramètres de 2048 bits (attention, c'est un peu long), on fera:
|
|
|
|
~~~
|
|
$ openssl dhparam -out /etc/ssl/dhparam.pem 2048
|
|
~~~
|
|
|
|
#### Désactiver SSLv3
|
|
|
|
Voici un lien qui donne la configuration à appliquer pour désactiver SSLv3 pour chaque service :
|
|
|
|
http://disablessl3.com/
|
|
|
|
## FAQ
|
|
|
|
### Erreur "The OCSP server has no status for the certificate" avec StartSSL
|
|
|
|
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>
|
|
|
|
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…
|
|
|
|
### 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
|
|
~~~
|