Journal Debug SSL/TLS avec OpenSSL - partie 1

Posté par (page perso) . Licence CC by-sa
Tags :
30
21
juil.
2015

Sommaire

Si tu es en pleine session de dé/bug SSL/TLS, cet article peut t'éviter quelques désagréments ;-)

SSL Labs, l'incontournable

On ne le présente plus, le site de Qualys permet de tester la configuration de son serveur facilement avec une interface web bien faite. Le test permet d'avoir un rapport concernant les points suivants :

  • Authentification : validité du certificat (nom du site, période de validité…),
  • présence et validité de la chaîne de certificat (chain)
  • Protocoles disponibles (SSLv2, SSLv3, TLS 1.0, 1.1 et 1.2),
  • Cipher suites disponibles,
  • Simulations de connexions avec de nombreux clients (Android, Firefox, IE, Java, Safari, …),
  • détails (Forward Secrecy, HSTS, utilisation du protocole RC4, etc etc…).

Le tout avec des notes allant de A à F et les pistes à suivre pour améliorer sa connexion. Si vous ne l'avez pas encore fait c'est la première étape parfaite. À noter que SSL Labs permet aussi de tester son navigateur et fournit de la data sur l'écosystème HTTPS sur Internet.

Création d'un .csr et d'un .key

Pour créer une Certificate Signing Request (.csr) et une nouvelle clé privée (.key):

openssl req -sha256 -out /etc/ssl/private/exemple.csr -new -newkey rsa:2048 -nodes -keyout /etc/ssl/private/exemple.key

Détaillons (il parait que c'est mieux pour comprendre) :

  • req : permet de créer et de gérer les CSR
  • -sha256 : Vous avez normalement vue les annonces concernant le passage de SHA1 à SHA2. Pour l'inclure dans votre CSR (Certificate Signing Request), il suffit de rajouter l'option -sha256 à OpenSSL
  • -out /etc/ssl/private/exemple.csr : indique le fichier où sera enregistrée la CSR
  • -new : génère une nouvelle CSR et demande à l'utilisateur les valeurs qu'il souhaite
  • -newkey rsa:2048 : crée une nouvelle clé privée, de type rsa et d'une taille de 2048 bits
  • -nodes : la clé privée n'aura pas de mot de passe
  • -keyout /etc/ssl/private/exemple.key : indique le fichier où sera enregistrée la clé privée

c'est pourquoi déjà ce certificat ?

Quand soudainement (enfin disons quelques temps plus tard), le drame ! Vous ne savez plus quel certificat fait quoi et pour qui, ou jusqu'à quand il est valide :

openssl x509 -text -in VotreCertificat.crt -noout

et les deux fichiers, là, ils vont ensemble ?

Pour la clé privée :

openssl rsa -noout -modulus -in server.key | md5sum

Pour le certificat :

openssl x509 -noout -modulus -in server.crt | md5sum

Si le résultat est le même pour les deux commandes, alors votre clé privée et votre certificat sont bien pour le même nom de domaine, avec les mêmes caractéristiques (validité…)

configuration SSL/TLS sous Apache2 :

Lors de la présence de plusieurs vhosts différents sur un même serveur Apache2, il arrive que l'on puisse avoir des résultats étranges dans les algos de chiffrement, par exemple la présence de SSLv3 alors que l'on a bien mis (et vérifié beauc… trop de fois) que l'on a bien SSLProtocol all -SSLv2 -SSLv3 dans sa configuration.

Il faut savoir que l'on peut mettre sa configuration SSL/TLS dans deux fichiers différents :

Le premier (/etc/apache2/mods-enabled/ssl.conf) sera le choix par défaut pour l'ensemble des vhosts, alors que le second (/etc/apache2/sites-enabled) concernera seulement le vhost pour lequel la configuration est présente dans son fichier de configuration. L'idée est donc de mettre la configuration générale dans ssl.conf et les points de configuration propre à chaque vhost dans sites-enabled (ou dans sites-enabled selon votre configuration), comme les certificats ou encore HSTS (Strict-Transport-Security) avec lequel je vous conseille de faire TRÈS attention.

  • configuration générale : /etc/apache2/mods-enabled/ssl.conf
SSLCipherSuite ALL:!aNULL:!eNULL:!LOW:!EXP:!RC4:!3DES:+HIGH:+MEDIUM
SSLHonorCipherOrder on
SSLProtocol all -SSLv2 -SSLv3

NOTE de non bas de page : mon extrémiste préféré pour le ssl/tls aeris vous propose cette configuration un poil extrême (mais ô combien efficace) à la place de la précédente :

SSLCipherSuite EECDH+AES:+AES128:+AES256:+SHA
  • configuration propre à un vhost : etc/apache2/sites-enabled/ (entre les balises <VirtualHost> et </VirtualHost>) :
SSLEngine on
SSLCertificateKeyFile /etc/ssl/private/libwalk.key
SSLCertificateFile /etc/ssl/private/libwalk.crt
SSLCertificateChainFile /etc/ssl/private/libwalk.chain
SSLCompression off
Header set Strict-Transport-Security "max-age=31622400
</VirtualHost>

.chain ? késako

La directive SSLCertificateChainFile d'Apache2 permet d'indiquer l'emplacement du fichier comportant les certificats chaînés (merci mozilla pour l'explication), c'est à dire votre certificat ET les certificats de votre CA (comme startssl, gandi, comodo).

Quand vous faites une requêtes (CSR) chez une CA, cette dernière, au moment de vous fournir votre certificat (.crt), vous indique (normalement) où se trouvent ses certificats à prendre dans votre cas.

Nous allons prendre comme exemple ici startssl vu qu'ils permettent d'avoir des certificats gratuits assez facilement. Une fois que j'ai fait ma requête via le formulaire en envoyant ma CSR et qu'ils m'ont fournit ma clé, je peux faire la manipulation suivante :

IMPORTANT : l'ordre dans le fichier doit commencer par le certificat le plus bas (nous), puis remonter progressivement vers le plus haut.

Imaginons que nous avons déjà notre clé privée (exemple.tld.key) et notre certificat (exemple.tld.crt) :

  • télécharger le certificat intermédiaire de startssl :
wget https://www.startssl.com/certs/sub.class1.server.ca.pem
  • puis le certificat root :
wget https://www.startssl.com/certs/ca.pem

puis on forge le certificat chaîné (ne pas oublier les 2 >>) :

cat exemple.tld.crt >> /etc/ssl/private/exemple.tld.chain
cat sub.class1.server.ca.pem >> /etc/ssl/private/exemple.tld.chain
cat ca.pem >> /etc/ssl/private/exemple.tld.chain

Et le tour est joué* \o/

si vous n'avez pas oublié de rajouter la ligne suivante dans le fichier de configuration de votre vhost :

SSLCertificateChainFile /etc/ssl/private/exemple.tld.chain

s_client

Permet de faire des tests grâce à un client SSL (cf wiki.openssl.org)

openssl s_client -servername www.libwalk.so -connect www.libwalk.so:443

Attention à ne pas oublier -servername et le nom du site que vous voulez tester, sinon la commande prendra le certificat présenté par défaut sur le serveur (et donc pas forcément le bon…).

Exemple :

  • avec -servername www.libwalk.so
openssl s_client -servername www.libwalk.so -connect www.libwalk.so:443

CONNECTED(00000003)
depth=1 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Class 1 Primary Intermediate Server CA
[...]
 0 s:/description=clwEqu9Rv2hyAXKy/C=FR/CN=www.libwalk.so/emailAddress=postmaster@libwalk.so
  • sans -servername www.libwalk.so
openssl s_client -connect www.libwalk.so:443

CONNECTED(00000003)
[...]
0 s:/OU=Domain Control Validated/OU=PositiveSSL Wildcard/CN=*.octopuce.fr

Pour plus de précisions, vous pouvez lire "Using OpenSSL’s s_client command with web servers using Server Name Indication (SNI)" pour faire connaissance avec notre ami le SNI (Server Name Indication).

OpenSSL sur mon système :

openssl ciphers -v 'ALL:COMPLEMENTOFFALL'

Ce qui est activé par défaut (vous pouvez noter la présence des suites d'EXPort) :

openssl ciphers -v 'DEFAULT'
openssl ciphers -v 'ALL:!aNULL:!eNULL'
openssl list-cipher-commands
openssl list-message-digest-commands

Vous pouvez "créer" votre suite avec les critères suivants (algo de chiffrement, de hashage, d'authentification…), la question que vous allez poser devrait donc être "ok, mais on fait comment ?".

Note : vous pouvez à tout moment regarder ce que contient un ensemble d'algos avec la commande que l'on vient de voir. Si par exempke vous voulez voir ce que EXP contient, vous pouvez le faire avec la commande openssl ciphers -v 'EXP'.

On prend tout (ALL), on enlève les algos qui ne permettent pas ni l'authentification (!aNULL), ni chiffrement (!eNULL), on continue en enlevant !LOW (chiffrement avec 56 ou 64 bits, la norme est de 128 bits de nos jours), les algos d'export (!EXP) et l'algo RC4 (!RC4) qui est considéré comme dangereux.

pour aller plus loin (mais vraiment très, très loin) :

  • # Précisions et corrections

    Posté par (page perso) . Évalué à 9.

    Création d'un .csr et d'un .key

    Pour créer une Certificate Signing Request (.csr) et une nouvelle clé privée (.key):

    openssl req -sha256 -out /etc/ssl/private/exemple.csr -new -newkey rsa:2048 -nodes -keyout /etc/ssl/private/exemple.key
    

    Détaillons (il parait que c'est mieux pour comprendre) :

    • -sha256 : Vous avez normalement vue les annonces concernant le passage de SHA1 à SHA2. Pour l'inclure dans votre CSR (Certificate Signing Request), il suffit de rajouter l'option -sha256 à OpenSSL

    Il ne semble pas que ce soit nécessaire. En tout cas, chez moi, sans cette option et sans rien à ce sujet dans la configuration, openssl req me sort spontanément des signatures avec hachage SHA-256.

    c'est pourquoi déjà ce certificat ?

    C'est pour quoi, comme dans « pour quoi faire » : c'est une question sur la finalité d'une action ou d'un objet. C'est pourquoi, c'est une question sur la cause d'une action, et c'est inapplicable à un objet, qui peut avoir une finalité mais en aucun cas de cause.

    openssl x509 -text -in VotreCertificat.crt -noout
    

    À noter que cette commande, qui permet de décrire un certificat, a un équivalent avec une demande de signature de certificat :

    openssl req -in VotreDemand.csr -noout -text

    .chain ? késako

    IMPORTANT : l'ordre dans le fichier doit commencer par le certificat le plus bas (nous), puis remonter progressivement vers le plus haut.

    Imaginons que nous avons déjà notre clé privée (exemple.tld.key) et notre certificat (exemple.tld.crt) :

    Non. Ça ne sert à rien, de mettre le certificat racine, auto-signé, de l'autorité de certification. La chaîne de certification, fournie par le serveur au navigateur client, doit lui permettre de remonter jusqu'à un certificat racine, et deux cas se présentent :

    • soit le navigateur en question connaît et fait confiance ce certificat racine, auquel cas il acceptera la connexion ;
    • soit il ne le connaît pas, ou le connaît mais ne lui fait pas confiance, auquel cas il refusera la connexion.

    Dans les deux cas, fournir le certificat racine au navigateur, dans la chaîne de certification, n'apporte rien du tout, en effet :

    • s'il le connaît déjà, eh bien, à l'évidence ça ne sert à rien ;
    • s'il ne le connaît pas, il le considèrera comme ce qu'il est, un certificat auto-signé inconnu, et refusera toujours la connexion.
    • [^] # Re: Précisions et corrections

      Posté par (page perso) . Évalué à 8.

      Non. Ça ne sert à rien, de mettre le certificat racine, auto-signé, de l'autorité de certification.

      Ça peut servir dans le cas où ce certificat est épinglé comme trust anchor dans un enregistrement TLSA de type DANE-TA (RFC 6698), pour que le navigateur puisse comparer le certificat racine envoyé par le serveur avec le condensat publié dans le DNS.

      • [^] # Re: Précisions et corrections

        Posté par (page perso) . Évalué à 6.

        Joliment observé, je n'avais pas pensé à ça. Ceci dit, aucun navigateur Web ne prend en charge DANE à ma connaissance, et étant donné l'état de fossilisation avancé du Web, je doute que ça arrive jamais de mon vivant.

        • [^] # Re: Précisions et corrections

          Posté par (page perso) . Évalué à 7.

          Aucun navigateur ne le prend en charge de base (ce qui est regrettable et probablement pas près de changer, malheureusement).

          Mais l’extension DNSSEC/TLSA Validator permet d’ajouter cette prise en charge à Mozilla Firefox, Internet Explorer, Chrome/Chromium, Opera et Safari — et je ne sais pas pour les quatre derniers, mais ça fonctionne très bien pour Firefox.

          (Et j’ai aussi un plugin de mon cru pour uzbl, mais il faut mettre les mains dans le cambouis.)

    • [^] # Re: Précisions et corrections

      Posté par (page perso) . Évalué à 3.

      En tout cas, chez moi, sans cette option et sans rien à ce sujet dans la configuration, openssl req me sort spontanément des signatures avec hachage SHA-256.

      Ça dépend des versions (et/ou peut-être des options à la compilation). Chez moi, c’est du SHA-1 par défaut avec OpenSSL 1.0.1p sur Slackware, mais SHA-256 par défaut avec OpenSSL 1.0.1k sur Debian…

      Mais attention, ce n’est pas parce que la requête de certificat est signée sur un condensat SHA-256 que le certificat le sera forcément. C’est l’autorité de certification qui décide seule de l’algorithme de condensation qu’elle utilise pour signer le certificat : elle peut très bien utiliser SHA-1 même si la CSR a été générée avec SHA-256.

    • [^] # Re: Précisions et corrections

      Posté par (page perso) . Évalué à 2.

      C'est pour quoi, comme dans « pour quoi faire » : c'est une question sur la finalité d'une action ou d'un objet. C'est pourquoi, c'est une question sur la cause d'une action, et c'est inapplicable à un objet, qui peut avoir une finalité mais en aucun cas de cause.

      Bon, je sais que ce n'est pas vraiment le cœur de la discussion mais au vu du ton péremptoire de cette affirmation, je me permets de revenir dessus. De mon côté, je dirais qu'un objet possède forcément une cause (à sa création ou fabrication) mais qu'il n'a une finalité que s'il a été fabriqué. De plus, répondre à la question pourquoi un objet a été fabriqué répond souvent à la question pour quoi un objet a été fabriqué, la cause et la finalité étant souvent très proche dans nos raisonnements. Les objets résultant d'un processus «naturel» ne sont pas liés à une finalité, à moins de croire au supernaturel ou au divin.

      L'étape d'après : citations et exemples (voire terrain) et dissertation ;)

      • [^] # Re: Précisions et corrections

        Posté par (page perso) . Évalué à 3.

        Bon, ma remarque ne valait probablement pas grand chose lue sous un angle philosophique, j'étais plutôt sur le sujet de la langue française, où seuls des actions, des verbes donc, peuvent avoir une cause : on ne peut pas demander pourquoi un objet, seulement pourquoi un objet existe, par exemple. On peut demander à quoi il sert, mais ce n'est pas la même chose, notamment pour les objets détournés de leur fonction originale !

  • # SSLCertificateChainFile obsolète à partir d’Apache 2.4.8 + HPKP

    Posté par (page perso) . Évalué à 9.

    Juste une précision, la directive SSLCertificateChainFile est obsolète à partir d’Apache httpd 2.4.8. La chaîne de certificat(s) intermédiaire(s) doit désormais être concaténée à la suite du certificat du serveur dans le fichier indiqué par la directive SSLCertificateFile.

    À part ça, on peut (doit ?) considérer aussi l’utilisation de HPKP (épinglage des clefs publiques dans les en-têtes HTTP, RFC 7469). Il suffit d’une ligne supplémentaire (ici, toujour pour Apache httpd) :

    Header always set Public-Key-Pins "max-age=5184000; includeSubDomains; pin-sha256=\"condensat_de_la_clef_active\"; pin-sha256=\"condensat_de_la_clef_de_secours\" env=HTTPS

    Le condensat d’une clef peut s’obtenir ainsi :

    $ openssl x509 -in libwalk.crt -noout -pubout | \   # Extraction de la clef publique depuis le certificat
      openssl rsa -pubin -outform DER | \               # Conversion en DER
      openssl dgst -sha256 -binary | \                  # Condensation
      openssl enc -base64                               # Encodage en Base64

    Attention, l’épinglage d’une clef de secours n’est pas optionnel : le RFC 7469 dit clairement qu’un navigateur doit ignorer tout en-tête HPKP qui ne mentionnerait pas de clef de secours.

  • # Question sur s_client

    Posté par (page perso) . Évalué à 2.

    Merci pour le journal,

    J'en profite pour faire part d'un problème rencontré derrière un serveur proxy. s_client ne semble pas respecter les variables d'environnement HTTP_PROXY et HTTPS_PROXY. J'ai pu contourner le problème en ouvrant la connexion vers le serveur à travers le proxy, puis laisser la main à s_client pour tester la validité, mais ça n'est pas vraiment très simple..

    Est-ce qu'il me manque quelque chose ou bien bien est-ce un manque dans l'appli ?

    • [^] # Re: Question sur s_client

      Posté par (page perso) . Évalué à 3. Dernière modification le 21/07/15 à 15:50.

      s_client n’a effectivement aucun support pour HTTPS_PROXY. Ce n’est pas très étonnant si on considère que c’est un client TLS générique, alors que HTTPS_PROXY (comme son nom l’indique) est spécifique à HTTPS.

      Une option -proxy host:port a été ajoutée à la version de développement il y a quelques semaines.

  • # Autre outil intéressant

    Posté par (page perso) . Évalué à 2.

    testssl.sh, disponible sur https://testssl.sh/.

    Remarque : à compiler sur un OpenSSL brut de décoffrage !

  • # LibreSSL

    Posté par . Évalué à 5.

    Qu'en est-il de libre ssl ? et de la qualité du code d'openssl ?

  • # SNI / Multiple certificat

    Posté par (page perso) . Évalué à 1.

    Pendant longtemps, cela n'a pas marché d'avoir plusieurs certificats mais j'ai fait un essai il y a un mois de cela et cela fonctionne très bien (sauf avec les vieux navigateurs mais on s'en fiche).

    Pour avoir un certificat par virtual host par exemple, il suffit de mettre en global la directive

    # Multiple certificate / Only SNI https client
    SSLStrictSNIVHostCheck on
    Et c'est tout ! Dans chaque virtual host, on peut ensuite mettre des certificats différents avec les directives classiques SSLCertificateFile, SSLCertificateKeyFile et SSLCertificateChainFile…

    • [^] # Re: SNI / Multiple certificat

      Posté par (page perso) . Évalué à 3.

      Euh non. Cette variable de configuration, c'est pour interdire aux clients non SNI d'accéder à un hôte virtuel par nom en TLS.

      Pour activer le SNI, c'est en fait le NameVirtualHost *:443, sous Apache 2.2.

      • [^] # Re: SNI / Multiple certificat

        Posté par (page perso) . Évalué à 2.

        Si ton client est non SNI, il ne peut pas accéder aux différents certificats. Donc si on veut avoir plusieurs certificats et que cela marche, il faut bien limiter aux seuls clients SNI ?

        • [^] # Re: SNI / Multiple certificat

          Posté par . Évalué à 3.

          Si le client supporte le SNI, dans tous les cas il recevra bien le certificat correspondant au servername qu'il a demandé.

          Si le client ne supporte pas le SNI
          - avec SSLStrictSNIVHostCheck no (par défaut), il recevra le certificat du vhost TLS par défaut.
          - avec SSLStrictSNIVHostCheck yes, il est rejeté

  • # Avoir une meilleure note

    Posté par (page perso) . Évalué à 2.

    Afin de limiter le protocole SSL/TLS, supprimer les trucs moyens et avoir une bonne note au test Qualys, voila un début de configuration pour Apache. Si vous avez des recettes de meilleures qualités et facilement maintenables, c'est le moment de les partager.

    SSLEngine On
    SSLHonorCipherOrder On
    SSLProtocol -all +TLSv1.2 +TLSv1.1 +TLSv1
    SSLCipherSuite HIGH:MEDIUM:!DH:!aNULL:!RC4

  • # Un bonne source deconfiguration

    Posté par (page perso) . Évalué à 3.

    https://cipherli.st/ propose des conf SSL blindées pour les principaux serveurs web ansi que d'autres softs tels que Postfix ou Dovecot.

  • # HSTS

    Posté par . Évalué à 2.

    HSTS (Strict-Transport-Security) avec lequel je vous conseille de faire TRÈS attention

    Pourquoi ? Je serais intéressé d'avoir plus de détails.

    • [^] # Re: HSTS

      Posté par (page perso) . Évalué à 4.

      Parce que si tu l'active sur un site où tu ne devrais pas (parce qu'il n'y a pas de certificat valide, parce le serveur n'écoute pas sur le 443…), tu vas avoir de gros problème avec tes utilisateurs parce qu'il n'est pas possible de le désactiver avant la fin du TTL spécifié (qui peut valoir plusieurs mois).

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.