Tag Archive: apache

Standard TLS sessions have a big issue: they are vulnerable to the « wiretap then crack » attack scheme: any intercepted communication can be stored and deciphered when you’ll have/find/factorize the server private key. Network traffic analysers often provide an option to perform such an operation for debug/protocol validation purposes. « Perfect » forward secrecy has been designed to fight against this issue: when two peers want to establish a TLS tunnel with PFS, after performing the server (or the mutual) authentication, they agree on an ephemeral session key.

TLS perfect forward secrecy can be supported in all recent browsers with Apache 2.3+. Version 2.4 has recently been migrated to Debian Jessie. The configuration you will find below has been made with the Qualys SSL Server Test. This test suite is quite useful to review the configuration of your TLS server: it checks the validity of your certificates, the strength of the cipher suite your server offers and gives you information on how common browsers will behave on your website.

Though the grade I get is not perfect, the configuration that I posted below seems to be, at this i’m writing this post, both the most interoperable and the most robust configuration you can create with Apache.

Replace (or add if applicable) the following configuration directives in your SSL module configuration file (most likely to be found in /etc/apache2/mods-enabled/ssl.conf).

SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLHonorCipherOrder on

then restart your apache server.

Please refer to the configuration at the bottom of this post

UPDATE: Qualys has updated its browser test suite, integrating Opera 12.15 and Firefox 21 on fedora 19, which are both known for not supporting TLS_ECDHE_RSA_WITH_RC4_128_SHA (0xC011).

Fedora community is well known for building FIPS 140-2 compliant cryptographic modules, and FIPS 140-2 happens not to support TLS_ECDHE_RSA_WITH_RC4_128_SHA.

This federal standard is known to only whitelist some cipher suites. In fact FIPS 140-2 doesn’t allow the use of « next » generation algorhithms (such as ECDHE for ephemeral key exchange, or as Galois/Counter Mode for block ciphers) despite the fact they bring significant improvements in terms of bandwidth and computing overhead.

Considering nowadays cryptographic ecosystem, this standard is to be considered as obsolete, except if you plan to sell any cryptographic product to the US goverment.

Ignoring that fact, today’s main security issue is caused by Apple Safari that still has not mitigated the BEAST vulnerability using the (1/n-1) split record trick.

So here is quite embarassing tradeoff you have to deal with: 1. Let your apple clients be vulnerable to BEAST while supporting PFS for any other browser by recommending CBC modes block ciphers and refusing use of RC4 (this will enhance the security for every browser except Safari), 2. Protect everyone against BEAST by using a crippled stream cipher and support PFS with a best-effort policy.

Bonus reminder: even if 3DES-EDE cipher suites use a 168 bit key, real key strength is 112 bits because of its vulnerability to the meet-in-the-middle attack. You may advertise for legacy support purposes, but if you do so, put these suites at the bottom of your server cipherlist, but do not add export or ADH suites are they are respectively weak and vulnerable.

UPDATE 2: After some browser behaviour analysis, I have achieved to get full PFS support for modern browsers, as shown on the pictures below. To do so, you need to properly enable some Diffie-Hellman ciphers. Doing so doesn’t trip the BEAST vulnerability flag and enables PFS for FIPS-compliant browsers that were not supported. The « Key exchange » subgrade in the Qualys SSL Server Test will decrease because DH parameters length are not great, even if they give a sufficient level of security for now.

This grade deterioration is an apache-specific issue: Apache developpers currently assumes that (EC)DH parameter choice is to be build-specific. According to me, this is not an acceptable solution as it makes long term support more difficult. You should consider bumping (voting for) this bugtracker feature request to get a more flexible way to control DH/ECDH parameters in the future.

Replace (or add if applicable) the following configuration directives in your SSL module configuration file (most likely to be found in /etc/apache2/mods-enabled/ssl.conf).

SSLProtocol +TLSv1.2 +TLSv1.1 +TLSv1
SSLCompression off
SSLHonorCipherOrder on

then restart your apache server.

Here is the grade I’ve got with the last configuration:

Below, you can see which cipher suites are selected by your clients.

Expert tip: The (1/n-1) split record trick is implemented in Firefox since a while. Thus, you can safely disable RC4 on Firefox in the advanced configuration menu. To do so, enter ‘about:config’ in your address bar, then search for ‘rc4’ and toggle all the found values to ‘false’. If you experience connections issues, toggle back those parameters to true.

An updated version of these cipher suites has been posted in the post 2015, an overview of TLS


Au cours de mes différentes expérimentations, j’ai voulu renforcer l’authentification de certains de mes services en m’appuyant sur une infrastructure à clés publiques dont je disposais déjà. Étant donné que la configuration du VirtualHost sur Apache n’a pas forcément été simple à mettre en place, je vous propose par la suite un template de Virtualhost que j’ai conçu. Les aspects relatifs à la gestion d’une PKI ou de la génération de certificats ne sera pas traitée dans ce billet.


La présente configuration suppose que vous disposiez au préalable:

  • d’un serveur Apache fonctionnel avec un virtualhost qui vous permettra de accueillir les utilisateurs dont l’authentification a échoué
  • des modules apache suivants (liste non exhaustive): mod_ssl, mod_rewrite, mod_headers
  • de certificats SSL serveurs et clients valides.

Gestion des erreurs

Un des problèmes principaux de l’authentification SSL repose sur le fait que le client se retrouve sur une page d’erreur du navigateur et non sur une page d’erreur de votre site web. La configuration suivante vous permettra de rediriger le client vers une autre page lui proposant éventuellement d’autres modes d’authentification (forte de préférence). La redirection mise en place est de type HTTP/307 et est complètement standard.

Pour notre exemple, je vous fournis une mire d’échec très simpliste en PHP qui permettra au client de relancer la procédure d’authentification vers le bon site une fois les problèmes corrigés de son côté. Pour la suite de ce billet, on supposera cette page accessible via l’URL suivante: https://login.yourdomain.com/sslfail.php

        <p>SSL authentication failed. <?php
                echo("<a href=\"https://". $_GET["from"] .".yourdomain.com/\">Try Again.</a>");

Le fichier VirtualHost

Pour la suite, on va considérer que le service à protéger sera accessible aux clients sur secureservice.yourdomain.com.

<IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerName secureservice.yourdomain.com
        DocumentRoot /var/secureservice-wwws

        # Configuration SSL côté serveur
        SSLEngine on
        SSLCertificateFile    /path/to/ca/certs/secureservice.pem
        SSLCertificateKeyFile /path/to/ca/private/secureservice.key
        SSLCertificateChainFile /path/to/ca/keystore/ca.crt

        # Configuration SSL côté client
        SSLCACertificateFile /path/to/ca/certs/ca.pem
        SSLCARevocationFile /path/to/ca/crl/ca-crl.crl
        SSLVerifyDepth  10

        <IfModule mod_rewrite.c>
            # If mod_rewrite is available, redirect clients on failure
            SSLVerifyClient optional

            <IfModule mod_headers.c>
                Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
                Header set Pragma "no-cache"
                Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
            RewriteEngine On
            RewriteCond %{SSL:SSL_CLIENT_VERIFY} !^SUCCESS$
            RewriteRule .* https://login.yourdomain.com/sslfail.php?from=secureservice [r=307]
        <IfModule !mod_rewrite.c>
            # If mod_rewrite is not available, just deny clients on failure
            SSLVerifyClient require

        BrowserMatch "MSIE [2-6]" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
        # MSIE 7 and newer should be able to use keepalive
        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

Concernant les attributs côté client, je tiens à vous préciser quelque points: en plus de la configuration classique du certificat serveur, 3 lignes sont impératives pour mettre en place l’authentification SSL:

  • La ligne qui dit au serveur où chercher les certificats des CA qui ont signé les certificats client (SSLCACertificateFile). Le chemin doit impérativement pointer sur un fichier encodé au format PEM. Si vous avez plusieurs CA à prendre en compte, concaténez vos différents fichiers PEM et faites pointer cette ligne sur le fichier résultant.
  • La ligne qui indique combien de niveaux de validation sont supportés pour les certificats clients (SSLVerifyDepth).  Si la valeur associée vaut zéro, le certificat client doit être auto-signé. Si la valeur vaut 1, le certificat doit être validé par le certificat d’une autorité présente dans le fichier des autorité client. Si la valeur vaut 2 ou plus, le certificat peut avoir été signé par une autorité intermédiaire valide. Avec 2, le client peut avoir été signé par une CA signée par une CA présente dans le fichier des autorités.
  • La ligne qui va spécifier le comportement à tenir en cas d’échec. Lorsque SSLVerifyClient est positionné sur require, la négociation SSL/TLS sera annulée si le certificat de l’utilisateur n’est pas validé par le serveur. Le client sera informé par son navigateur que l’opération a échoué. Si par contre SSLVerifyClient est positionné sur optional, et que le certificat de l’utilisateur n’est toujours pas valide, la connexion s’établit quand même, mais il sera, dans notre cas, redirigé vers la page d’échec (http://login.tourdomain.com/sslfail.php?from=secureservice) par le biais d’une réponse HTTP/307. À ce sujet, il est très important d’ajouter le module headers à apache, car les navigateurs ont tendance à mettre en cache les redirections. Si une redirection est mise en cache, votre client pourrait croire que son authentification échoue en permanence, ce qui n’est pas souhaitable.

La spécification d’une liste de révocation de certificats n’est pas toujours nécessaire, mais il reste préférable de l’utiliser car elle vous permettra d’assurer une gestion des droits d’accès plus propre. La ligne avec SSLCARevocationFile doit pointer sur un fichier qui contient la concaténation de toutes les listes de révocation des autorités client encodées au format PEM.

Attention! La technique présentée dans cette brève ne vous dispense en aucun cas d’assurer une sécurisation correcte de votre site et/ou de vos applications web.

Un jour, je me suis rendu compte que des gars pas très malins s’amusaient à scanner des listes de versions vulnérables d’outils. J’ai également remarqué que ces scans étaient réalisés à l’aide d’outils tout fait qui n’ont pas honte de s’annoncer avec un beau User-Agent. N’étant pas spécialement amateur de ce genre de méthodes, j’ai décidé de blacklister ces outils avec un  joli fichier htaccess dont voici un extrait:

SetEnvIfNoCase User-Agent ZmEu getout
SetEnvIfNoCase User-Agent Xenu getout
SetEnvIfNoCase User-Agent dragostea getout
SetEnvIfNoCase User-Agent Morfeus getout
order allow,deny
allow from all
deny from env=getout
deny from
# et ainsi de suite...

Ce fichier .htaccess est situé à la racine de mon site. La variable getout correspond à un groupe de visiteur qui ont un User-Agent douteux et qui ont l’honneur de se faire expulser de manière systématique.

Nota: Ce blog est hébergé par WordPress, l’astuce décrite ci-dessus n’est donc pas appliquée. Allez plutôt casser vos propres jouets ;-þ


Le pré-requis pour ce tutoriel est une connaissance basique d’Apache 2, et des virtualhosts.

J’ai récemment fait l’acquisition d’une caméra de surveillance IP, et je voulais pouvoir y accéder depuis l’extérieur sans que l’on ne puisse m’observer.

Mon réseau domestique est structuré en plusieurs VLAN. 3 de ces VLANs nous intéresseront pour la suite de cet article:

  • Le VLAN Interconnexion Internet:  zone où mon modem et mon firewall sont connectés.
  • Le VLAN DMZ: tous mes équipements devant être accessibles depuis l’Internet y sont connectés.
  • Le VLAN Serveurs internes: tous les équipements dont j’ai besoin, mais qui ne doivent pas être directement accessibles depuis l’Internet.

Ci-dessous, l’extrait de la politique de sécurité qui nous intéresse (valable autant en IPv4 qu’en IPv6).

  • Internet peut initier des connexions TCP et envoyer des paquets UDP dans la DMZ et vice-versa.
  • Internet ne peut pas joindre directement les serveurs internes. L’usage d’un reverse proxy dans la DMZ est obligatoire.
  • Le reverse proxy est l’unique machine de la DMZ autorisée à accéder aux serveurs internes.
  • Les connexions SSH du reverse proxy sont bloquées depuis internet et la DMZ.

Dans cette configuration, pour sécuriser correctement la webcam, j’ai installé cette dernière dans mon VLAN des serveurs internes, et j’ai configuré le reverse-proxy pour qu’il effectue une authentification.

Configuration d’Apache 2 en reverse-proxy

Tout d’abord, j’ai choisi d’utiliser l’authentification HTTP-Digest, qui est simple à mettre en place depuis apache, et qui est un tantinet plus sûre que l’authentification basique, où le mot de passe transite en clair sur le réseau.

Pour concrétiser l’exemple, la racine Web de la webcam est accessible en faisant depuis le reverse-proxy. La webcam sera accessible depuis http://services.example.com/webcam/ depuis l’Internet (les noms ont été changés pour protéger les innocents).

Vous devez activer les modules apache suivant pour réussir votre configuration:

  • mod_auth_digest
  • mod_proxy
  • mod_proxy_http
  • mod_proxy_connect
  • mod_proxy_ftp

LoadModule ou a2enmod sont vos amis ;-þ

Séance gratte papier fichiers

Ensuite, il va falloir générer le fichier avec les mots de passes pour l’authentification HTTP Digest (souvent .htdigest). Pour cela, effectuez la commande suivante:

htdigest -c /chemin/vers/htdigest webcam toto

Le mot de passe de ‘toto‘ vous sera demandé interactivement.

L’argument ‘webcam‘ correspond à ce qu’on appelle un realm ou plus communément Domaine de connexion. Avec l’authentification HTTP-Digest, vous pouvez gérer un utilisateur sur plusieurs domaines (avec des mots de passes naturellement différents).

Une fois le fichier htdigest généré, posé au bon endroit, en veillant que www-data puisse y accéder en lecture, on s’attaque à la configuration des sites.

Rendez-vous dans /etc/apache2/sites-enabled et ajoutez les lignes suivantes, par précaution, si vous n’utilisez pas de forward proxy sur la machine:

ProxyRequests Off

Order deny,allow
        Allow from all

Ces lignes vont interdire l’utilisation des fonctions forward-proxy sur la machine, qui sont testées régulièrement par des petits malins qui s’amusent à scanner votre IPv4 ou votre subnet IPv6.

Dans le fichier contenant le(s) virtualhost(s) correspondant à services.example.com, ajoutez les lignes suivantes dans le bloc virtualhost adéquat:

    <Location /webcam/>
        AuthType Digest
        AuthName "webcam"
        AuthDigestDomain /webcam
        AuthUserFile /chemin/vers/htdigest
        Require valid-user

La chaîne après le mot-clé AuthName doit être impérativement celle du Realm que vous avez choisi lors de la génération du fichier htdigest.

Stress du passage en production

Rechargez votre démon apache. Normalement, à cette étape, lorsque vous tapez http://services.example.com/webcam/ (ne pas oublier le ‘/’ à la fin), un prompt d’authentification devrait s’afficher. Après avoir entré les identifiants valides, vous devriez pouvoir accéder à l’interface de votre webcam.