jeudi 8 avril 2010

tutoriel authentification forte Apache2 - openssl - trusted platform module (TPM)

L'administrateur d'un serveur Apache2 peut restreindre l'accès à une partie de son site à des utilisateurs authentifiés. Dans cet article, nous abordons l'authentification mutuelle (authentification forte) par certificat x509 entre un serveur Apache2 et un client. De plus, ici, le certificat du client sera protégé par le trusted platform module (TPM) de son ordinateur.
Avec cette solution, seules les machines autorisées peuvent accéder au site. De plus, il devient très difficile pour un usurpateur d'accéder à la clé d'authentification d'une machine compromise. En effet, celle-ci peut difficilement être copiée ou extraite, celle-ci étant gardée matériellement dans la puce TPM.

introduction

Notre réseau contiendra un serveur qui fera office de serveur Web et d'autorité de certification, et un client.

L'autorité de certification ne sera utilisée que pour signer les clés des clients et du serveur. Ainsi, tout client possédant un certificat signé par l'autorité pourra se connecter au serveur. Inversement, le serveur sera autorisé par les clients dès lors que son certificat a été certifié par l'autorité.

Dans un premier temps, nous créerons un certificat pour le serveur et un pour le client, certifiés par un troisième certificat appartenant à l'autorité de certification.
Puis nous configurerons un serveur Apache2 accessible seulement depuis des clients certifiés par l'autorité.
Enfin, nous testerons l'accès à ce serveur en utilisant s_client d'openSSL et nous verrons que Firefox ne peut pas utiliser actuellement le TPM via la librairie trousers.

prérequis

Le client, tournant sous Linux, possède un TPM activé non initialisé. Les librairies libengine-tpm-openssl et libtspi-dev ont été installées (cf tutoriel infond [1]).
Le client et le serveur seront configurés conformément au labo du tutoriel basics 1 - mise en place du laboratoire VMWare [4].
L'adresse IP du client est 192.168.0.10
L'adresse IP du serveur est 192.168.0.2

création de l'infrastructure de clés

Nous allons créer successivement :
- un certificat autorité pour signer le certificat du client, et celui du serveur,
- un certificat serveur certifié par l'autorité,
- une paire de clés client, dont la partie privée sera gardée dans le TPM, une requête de certification pour la clé publique du client,
- un certificat client certifié par l'autorité, dont la partie privée sera gardée dans le TPM

création du certificat autorité autosigné

Sur le serveur, créons un répertoire ssl
serveur~$ sudo mkdir /etc/apache2/ssl
serveur~$ cd /etc/apache2/ssl
créons le certificat autorité autosigné
serveur:/etc/apache2/ssl$ sudo openssl req -x509 -newkey rsa:1024 -out authority.crt -keyout authority.key

création du certificat serveur signé par l'autorité

créons le certificat du serveur signé par le certificat autorité
serveur:/etc/apache2/ssl$ sudo openssl req -x509 -newkey rsa:1024 -in authority.crt -out server.crt -keyout server.key
serveur:/etc/apache2/ssl$ sudo chmod 440 *.key

création de la paire de clés et de la requête de certificat du client

Rappel: le TPM ici utilisé est virtualisé [1].

lançons le dameon tpmd. Lancons également trousers. Puis, initialisons le tpm (ne pas choisir -u unicode, pour que la commande create_tpm_key reconnaisse ensuite la SRK.)
client~$ sudo tpmd
client~$ sudo tcsd
client~$ tpm_takeownership -y
Enter SRK password: <- "ENTER"
Confirm password: <- "ENTER"
créons la paire de clés du client en utilisant le TPM
client~$ create_tpm_key -a client.key
préparons la requête de certificat. Nous la fournirons au serveur un peu plus tard pour la certifier.
~$ sudo openssl req -keyform engine -engine tpm -key client.key -new -out client.csr
engine "tpm" set.
SRK authorization:
TPM Key Password:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:FR
State or Province Name (full name) [Some-State]:Ile de France
Locality Name (eg, city) []:Paris
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Infond
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:client
Email Address []:client@infond.blogspot.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Nous venons de créer une requête de certificat dont la clé privée est gardée dans le tpm.

certification du certificat du client par le serveur

Installons un serveur SSH sur la machine serveur pour permettre l'envoi de la clé de manère sécurisée. Il serait normalement nécessaire de sécuriser les accès au serveur SSH, ce qui dépasse le propos de cet article.
serveur~$ sudo apt-get install openssh-server
envoyons la requête de certificat du client au serveur
client~$ scp client.csr utilisateur@192.168.0.2:~

le serveur certifie la requête de certificat du client avec le certificat de l'autorité
serveur~$ sudo openssl x509 -req -in client.csr -CA /etc/apache2/ssl/authority.crt -CAkey /etc/apache2/ssl/authority.key -CAcreateserial -out client.crt
voyons le certificat obtenu
serveur~$ openssl x509 -in client.crt -noout -text
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            e1:5e:ee:64:7b:d8:6b:67
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=FR, ST=Ile de France, L=Paris, O=Infond, CN=authority/emailAddress=authority@infond.blogspot.com
        Validity
            Not Before: Apr  8 12:01:14 2010 GMT
            Not After : May  8 12:01:14 2010 GMT
        Subject: C=FR, ST=Ile de France, L=Paris, O=Infond, CN=client/emailAddress=client@infond.blogspot.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:e5:85:29:a7:62:69:08:f3:af:35:4b:0e:47:0e:
                    0b:7f:08:77:71:fb:0b:02:01:e6:2b:aa:76:6d:da:
                    1d:41:d3:e0:66:cf:de:2d:1c:b4:ed:92:48:49:59:
                    b8:ef:e2:89:9a:ec:0a:89:2a:c2:c1:28:06:54:87:
                    00:17:0a:e2:d3:d0:82:f7:2a:b8:c9:91:74:e2:89:
                    ea:f6:2b:d9:f2:e6:bc:90:e1:d9:07:a3:26:18:14:
                    e9:eb:66:ab:69:a9:ca:30:32:b9:c3:2a:36:92:f2:
                    02:ce:52:c0:74:f7:e4:c2:71:36:a5:4e:b6:33:34:
                    b0:90:28:c9:bf:67:36:6c:f0:c0:9d:07:7a:f5:96:
                    64:3d:1b:86:12:79:a2:d0:2f:a7:52:a3:69:81:81:
                    3c:7e:d7:86:58:75:82:e4:bf:ab:6a:9f:cf:85:88:
                    30:f7:96:8a:32:9a:f1:28:c9:0e:02:52:a8:21:c8:
                    ec:4c:5e:d2:e8:30:78:f2:7b:ea:c5:da:b4:85:dd:
                    fd:73:8d:ed:cd:22:1e:48:f7:9a:56:2a:08:5e:49:
                    3a:16:51:57:cc:de:24:6a:16:ed:47:28:7d:83:11:
                    63:3a:92:af:8a:8a:e0:93:d8:61:48:b5:41:24:2f:
                    90:15:80:a4:c8:d7:cd:8d:d9:1e:62:4f:f0:be:dd:
                    00:ef
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
        57:f1:e5:24:9b:0d:e3:90:1c:52:6e:85:b5:a0:bd:07:1b:cb:
        f6:a4:34:e3:1a:87:e8:1e:16:6f:8c:b2:01:89:6b:90:bb:20:
        71:66:c8:88:fe:2c:16:b6:e2:cd:69:57:f9:f0:bc:19:c8:0f:
        03:99:48:97:50:03:9b:f8:a5:07:d8:02:41:fd:9b:81:e1:dd:
        5e:33:e8:82:16:9c:65:01:3b:81:84:f4:c3:19:79:1c:6e:50:
        c3:e3:c0:97:c3:d1:9e:15:d2:7e:50:39:61:f5:38:d6:61:39:
        c3:8d:4f:48:39:3e:55:cd:f1:73:59:7f:9a:1b:15:22:17:70:
        c9:f8
depuis le client, récupérons le certificat
client~$ scp utilisateur@192.168.0.2:~/client.crt ~
A ce stade, le client possède un certificat signé par l'autorité, dont la clé privée est placée dans le TPM.

configuration du serveur Apache2

installons le serveur apache2
serveur~$ sudo apt-get install apache2
Installons le module ssl:
serveur~$ sudo a2enmod ssl
serveur~$ sudo /etc/init.d/apache2 restart
remarque: la directive Listen 443 a été ajoutée à l'installation du module ssl:
serveur$ cat /etc/apache2/ports.conf

NameVirtualHost *:80
Listen 80


# SSL name based virtual hosts are not yet supported, therefore no
# NameVirtualHost statement here
Listen 443
activons le ssl pour notre site. Dans cette configuration:
- toute requête sur le port 80 est redirigée vers le port 443 (https),
- la page qui s'affichera sera /var/www/index.html,
- le serveur s'authentifie auprès du client avec le certificat du serveur,
- le client s'authentifie auprès du serveur avec un certificat signé par l'autorité uniquement.
serveur$ sudo cat /etc/apache2/sites-enabled/000-default
NameVirtualHost 192.168.0.2:443


redirect / https://192.168.0.2:443



DocumentRoot /var/www

SSLEngine on
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCACertificateFile /etc/apache2/ssl/authority.crt
SSLVerifyClient Require
relancons le serveur:
serveur$ sudo /etc/init.d/apache2 restart
vérifions que le serveur est actif. Bien sûr, notre certificat étant autosigné, firefox affiche que la connexion n'est pas certifiée. Depuis le client:


Jetons un oeil au détail du certificat:


de plus, même si le client accepte le certificat du serveur, le serveur, lui, refuse le client


Hélas! Pour intégrer le certificat du client dans Firefox, il est nécessaire d'utiliser l'API pkcs #11 de trousers, qui n'est pas compatible avec Firefox. Nous verrons cela un peu plus tard.

Se connecter au serveur Apache2 avec openSSL

Sur le client, openssl est configuré pour interagir avec le TPM. Tachons de nous connecter au serveur Apache2

récupérons le certificat publique de l'autorité.
Sur le serveur
serveur~$ sudo cp /etc/apache2/ssl/authority.crt ~
Depuis le client
client~$ mkdir ~/CAvalides
client~$ scp utilisateur@192.168.0.2:~/authority.crt ~/CAvalides/
Enfin connectons nous au serveur. Ca marche!
client~$ openssl s_client -connect 192.168.0.2:443 -keyform engine -engine tpm -key client.key -cert client.crt -CAfile /home/utilisateur/CAvalides/authority.crt
engine "tpm" set.
SRK authorization:
TPM Key Password:
CONNECTED(00000004)
depth=0 /C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
verify return:1
---
Certificate chain
 0 s:/C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
   i:/C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDbzCCAtigAwIBAgIJANpuDO+rjUfaMA0GCSqGSIb3DQEBBQUAMIGCMQswCQYD
VQQGEwJGUjEWMBQGA1UECBMNSWxlIGRlIEZyYW5jZTEOMAwGA1UEBxMFUGFyaXMx
DzANBgNVBAoTBkluZm9uZDEPMA0GA1UEAxMGc2VydmVyMSkwJwYJKoZIhvcNAQkB
FhpzZXJ2ZXJAaW5mb25kLmJsb2dzcG90LmNvbTAeFw0xMDA0MDgxMTI5NTBaFw0x
MDA1MDgxMTI5NTBaMIGCMQswCQYDVQQGEwJGUjEWMBQGA1UECBMNSWxlIGRlIEZy
YW5jZTEOMAwGA1UEBxMFUGFyaXMxDzANBgNVBAoTBkluZm9uZDEPMA0GA1UEAxMG
c2VydmVyMSkwJwYJKoZIhvcNAQkBFhpzZXJ2ZXJAaW5mb25kLmJsb2dzcG90LmNv
bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAot1fyBinTZuuCwM1NkIZultU
XX5LIs3aslESgMwo9uZC/4u1bki4zcd671ozLp4LEcXsMNgxgH/YOfvMt8BmdEpe
3ds/mAsTkWC5cIXP68N1+jk+EaiUYJSRVyF7vuwuLkaBA6Sibct07W3YtKAIxbSv
v+WhRJkPr1UCvvoYv98CAwEAAaOB6jCB5zAdBgNVHQ4EFgQU1l9uOA7reg9eMi2M
3ztKcKjpamEwgbcGA1UdIwSBrzCBrIAU1l9uOA7reg9eMi2M3ztKcKjpamGhgYik
gYUwgYIxCzAJBgNVBAYTAkZSMRYwFAYDVQQIEw1JbGUgZGUgRnJhbmNlMQ4wDAYD
VQQHEwVQYXJpczEPMA0GA1UEChMGSW5mb25kMQ8wDQYDVQQDEwZzZXJ2ZXIxKTAn
BgkqhkiG9w0BCQEWGnNlcnZlckBpbmZvbmQuYmxvZ3Nwb3QuY29tggkA2m4M76uN
R9owDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAimT51u6DvrhaYvLOG
9NNLbbBDGCN/q5dqWPRqkGjfD1i4FU7v1ll8pY6eWl6gHRERJVDOaVsUy0Itnj11
do0MhPQ9DuUQeeHGMsiWkXvHF6rPdEaCZdWycg3Hw3q9gTjTEiRNl2aKfQR1Hl/h
LzvlBfkjDu+Rf8VEEwrnzneyQg==
-----END CERTIFICATE-----
subject=/C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
issuer=/C=FR/ST=Ile de France/L=Paris/O=Infond/CN=server/emailAddress=server@infond.blogspot.com
---
Acceptable client certificate CA names
/C=FR/ST=Ile de France/L=Paris/O=Infond/CN=authority/emailAddress=authority@infond.blogspot.com
---
SSL handshake has read 1600 bytes and written 2281 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES256-SHA
    Session-ID: B51E5ADFCD1D299F05ADE97E2597F183D5792453A8053B148011D148DB4008DB
    Session-ID-ctx:
    Master-Key: 4D1ACC567E193FA5E4A82D8BA69EBF6743916B6729222A012617D9796FA72B2C8005AC63F0D5F81112BE78472BC0BFE6
    Key-Arg   : None
    Start Time: 1270734784
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
^C

A ce stade, nous avons réussi à configurer un serveur Apache2 qui n'accepte que les clients qui possèdent un certificat qu'il a certifié et dont la partie privée est protégée dans un TPM.

et se connecter avec Firefox au serveur Apache2 ?

Trousers ne fonctionne pas avec Firefox à l'heure actuelle.

Pour que Firefox puisse utiliser le certificat dont la clé privée est conservée dans le TPM, il est nécessaire d'ajouter un module PKCS #11 dans Firefox. PKCS #11 est une norme qui définit une API permettant à une application d'utiliser le pilote du TPM.
Il est très facile de connecter Firefox à un module PKCS11. Cependant, celui fourni par trousers présente une incompatibilité. Ce paragraphe montre la procédure.

activation du module pkcs11 de trousers

Sur le client, ajoutons utilisateur au groupe pkcs11
client~$ sudo usermod -a -G pkcs11 utilisateur
client~$ sudo reboot
lancons le dameon tpmd (si le tpm est virtualisé). Lancons également trousers. Puis, initialisons le tpm. Pour utiliser pkcs11, il est nécessaire que la SRK soit initialisée vide:
client~$ sudo tpmd
client~$ sudo tcsd
client~$ tpm_takeownership -y
Enter SRK password: <- "ENTER"
Confirm password: <- "ENTER"
initialisons l'interface pkcs11 du TPM
utilisateur@TPM:~$ tpmtoken_init
A new TPM security officer password is needed. The password must be between 6 and 127 characters in length.
Enter new password:
Confirm password:
A new TPM user password is needed. The password must be between 6 and 127 characters in length.
Enter new password:
Confirm password:
vérifions si le token a bien été initialisé:
utilisateur@TPM:~$ pkcsconf -t -c 0
Token #0 Info:
    Label: IBM PKCS#11 TPM Token         
    Manufacturer: IBM Corp.                     
    Model: TPM v1.1 Token
    Serial Number: 123           
    Flags: 0x44D (RNG|LOGIN_REQUIRED|USER_PIN_INITIALIZED|CLOCK_ON_TOKEN|TOKEN_INITIALIZED)
    Sessions: -1/-1
    R/W Sessions: -1/-1
    PIN Length: 6-127
    Public Memory: 0xFFFFFFFF/0xFFFFFFFF
    Private Memory: 0xFFFFFFFF/0xFFFFFFFF
    Hardware Version: 1.0
    Firmware Version: 1.0
    Time: 17:05:38
Remarque: les clés publiques et privées générées lors de l'initialisation de l'interface pkcs11 du TPM sont sauvegardées sur le disque. La clé privée est chiffrée avec le TPM user password. La clé publique est chiffrée avec le TPM security officer password.


Nous les supprimons avec la méthode d'effacement sécurisé de Guttman
client~$ sudo apt-get install wipe
client~$ sudo wipe -f /var/lib/opencyptoki/tpm/*.pem
Remarque: si un token a déjà été (mal) initialisé, il peut être nécessaire de le supprimer de la base token, puis de recommencer:
client~$ rm -rf /var/lib/opencryptoki/tpm
A ce stade, l'interface PKCS #11 de trousers est fonctionnelle.

configurer Firefox pour accéder au module PKCS #11


Sur le client, la méthode est triviale: Dans Firefox, aller dans Outils -> Options -> Avancé -> périphériques de sécurité -> charger
Le module est l'un des fichiers .so situé dans /usr/lib/opencryptoki/ ou /usr/lib/pkcs11.



conclusion


Dans cet article, nous avons configuré un serveur Apache2 utilisant une authentification forte basée sur le TPM de ses clients.

références

1) infond - tutoriel TPM - http://infond.blogspot.com/2010/03/tutoriel-tutoriel-trusted-platforms-tpm.html
2) ubuntu - tutoriel sécuriser Apache2 - http://doc.ubuntu-fr.org/tutoriel/securiser_apache2_avec_ssl
3) sécuriser par mot de passe les accès à un serveur Apache2 - http://www.linux-france.org/prj/edu/archinet/systeme/ch16s02.html
4) infond - tutoriel mise en place du laboratoire VMWare - http://infond.blogspot.com/2010/03/basics-1-mise-en-place-du-labo.html
5) tutoriel openssl - http://www.herongyang.com/crypto/openssl_verify.html
6) pkcs11 - ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-11/pkcs11v2.doc
7) tuto pkcs11 (polonais) - http://blog.4zal.net/2009/06/12/kryptografia-trusted-platform-module-i-ubuntu/
8) doc trousers pkcs11 - http://trousers.sourceforge.net/pkcs11.html
9) authentification mutuelle forte dans apache2 - https://www.ateliers.modernisation.gouv.fr/ministeres/ae/interops/public/documents-annexes/interops-a1/downloadFile/file/Standard%20Interops1.0_GuideMiseEnOeuvre_v1.0.pdf?nocache=1223646135.91

1 commentaire: