4. La sécurité

La sécurisation d'une application va s'appuyer sur plusieurs briques :

    • l'identification : le login de l'utilisateur est vérifié ;
    • l'habilitation : l'utilisateur doit disposer des droits adéquats pour accéder à un module, ou à un sous-ensemble de données définies, par exemple, le chiffre d'affaires de son service ;
    • la cohérence : les données introduites dans le système doivent être conformes à ce qu'on attend ;
    • et enfin, la sécurisation générale : la mise en œuvre de mécanismes adaptés rendront les attaques plus difficiles à mener.

Etre en règle vis à vis de la loi

La CNIL

Tout développeur, avant de concevoir son application, doit vérifier si celle-ci est sujette à déclaration auprès de la CNIL. En effet, le fait de manipuler des informations personnelles, comme le nom ou l'adresse d'une personne, implique un certain nombre de contraintes, comme le droit de rectification et la non divulgation des informations à des tiers non autorisés. De même, le stockage de certaines catégories d'informations peut être refusé, comme celles afférentes à la religion, aux opinions...

Certains traitements informatisés sont exempts de déclaration, comme la comptabilité ou la gestion des fournisseurs. D'autres sont soumis à une déclaration simplifiée, comme la création d'un annuaire téléphonique au sein de l'entreprise ou la mise en place d'un fichier des prospects. Enfin, tous ceux qui ne rentrent pas dans les catégories pré-établies sont soumis à une déclaration normale. Celle-ci doit décrire dans le détail toutes les catégories d'informations manipulées, les échanges avec des tiers, les mesures de sécurité prises...

Le site de la CNIL (http://www.cnil.fr) propose un outil qui permet de savoir dans quel cas le projet se situe, et de préparer sa déclaration en quelques clics.

Les licences d'utilisation des logiciels

Lors de l'écriture d'un logiciel, il est fréquent d'utiliser des composants fournis par des développeurs tiers. Néanmoins, ces composants sont disponibles selon des conditions d'utilisation qui peuvent être contraignantes, sujets à royalties, ou qui peuvent conditionner l'usage qui sera fait du nouveau logiciel conçu.

Sur Internet, il existe pléthore de licences d'utilisation. Les deux plus fréquentes sont la licence GNU GPL (GNU General Public licence) et la licence GNU LGPL (GNU Lesser General Public licence). On trouve également la licence BSD, une des moins restrictives, et les licences CECILL, qui sont une transposition dans le droit français des licences GPL, LGPL et BSD.

La licence GPL (aujourd'hui en version 3) autorise tout utilisateur à recevoir une copie du logiciel publié sous celle-ci. Il est possible de modifier le logiciel, à condition que toutes les modifications, dès lors qu'elles ne sont pas conservées pour un usage privé, soient également publiées sous cette même licence. Elle autorise également l'usage commercial du logiciel. En principe, un logiciel qui inclut un composant GPL doit être publié également sous licence GPL. Ce n'est pas le cas d'un composant sous licence BSD, qui peut être intégré à un logiciel non libre.

La licence LGPL est moins contraignante (Lesser signifie moindre en anglais) : le composant fourni selon celle-ci peut être associé à du code qui n'est pas publié sous cette licence ; l'aspect héritage de la licence GPL n'est plus obligatoire. La seule obligation consiste à publier les modifications du composant sous licence LGPL.

Les licences CeCill ont été créées à l'initiative du CEA, du CNRS et de l'INRIA, pour que les organismes publics puissent publier les logiciels qu'ils ont conçus. Il existe 3 licences CeCill : la licence CECILL-A, compatible avec la licence GPL, la licence CECILL-B, compatible avec la licence BSD, et la licence CECILL-C, destinée aux composants, est compatible avec la licence LGPL.

Certains composants sont fournis selon des licences particulières. Par exemple, certaines bibliothèques graphiques autorisent l'usage gratuit pour des applications destinées au projets humanitaires ou scolaires, mais payant pour tous les autres usages ; il est indispensable, avant d'utiliser un composant, de s'assurer des termes de la licence et de l'usage qui peut en être fait.

Enfin, si le logiciel que vous allez concevoir est destiné à être publié ou transmis à des tiers, pensez également à définir quelles sont les règles d'utilisation que vous souhaitez imposer en choisissant la licence qui vous semble adaptée.

Pour télécharger le texte des licences :

GPL : http://www.gnu.org/licenses/gpl.html, et sa traduction non officielle en français : http://www.april.org/files/groupes/trad-gpl/doc/GPLv3/www.rodage.org/gpl-3.0.fr.html

LGPL : http://www.gnu.org/licenses/lgpl.html et sa traduction non officielle en français : http://www.vadeker.net/humanite/copyleft/lgpl.html

CECILL : http://www.cecill.info/

BSD : http://www.freebsd.org/copyright/license.html

L'identification

Le login, porte d'entrée de l'utilisateur dans l'application, est associé en général à un mot de passe. L'utilisateur va être confronté, dans la majorité des cas, soit lors de l'ouverture de l'application, soit lorsqu'il souhaitera accéder à des informations dont l'accès est protégé, à un écran lui demandant de saisir son login et un mot de passe associé ; il existe néanmoins des identifications basées sur des mécanismes plus complexes, par exemple en utilisant des certificats numériques, ou en demandant à l'utilisateur de saisir des codes complémentaires, lus dans une grille fournie au préalable à l'utilisateur.

Aujourd'hui, trois grands modes d'identification sont utilisés :

    • la base de données contient une table Login, dont un des champs correspond au mot de passe utilisé ;
    • l'identification des utilisateurs est réalisée à partir d'une base de données centrale, et peut être réutilisée entre différentes applications. En entreprise, celle-ci s'appuie en général sur un annuaire, soit Active Directory de Microsoft, soit à la norme LDAP (Lightweight Directory Access Protocol). A noter que l'annuaire Active Directory est compatible LDAP (hormis la toute première version) : nous ne traiterons ici que le cas LDAP ;
    • l'identification des utilisateurs est sous-traitée à une application dédiée à cet effet, un serveur CAS (Central Authentication Service) – service d'authentification centralisé), qui va traiter de manière unique toutes les demandes de vérification de login. C'est en général la méthode la plus fiable et la plus sécurisée pour gérer l'identification dans les applications.

L'identification basée sur le login stocké en base de données

Une table Login :

la classe Login, basée sur ObjetBDD :

class Login extends ObjetBDD
{
function Login($bdd)
{
$this->table="Login";
ObjetBDD::ObjetBDD($bdd);
$this->id_auto = 1;
$this->types=array(
'id'=>1);
}
function verifLogin($login,$password){
$password = hash("sha256",$password);
$sql='select login from LoginGestion where login ="'.$login
.'" and password = "'.$password.'"';
$res=ObjetBDD::lireParam($sql);
if ($res["login"]==$login) {
return TRUE;
}else{
return FALSE;
}
}
}

Il manque à cette classe l'enregistrement du login et du mot de passe. Le mot de passe doit être impérativement crypté, pour éviter qu'il puisse être consulté par qui que ce soit, administrateur ou pirate. Eviter le codage MD5, obsolète, et lui préférer sha256, whirlpool ou RIPEMD-160.

Son implémentation dans l'application :

$login = new Login($instance_adodb);

$res=$login->verifLogin($_REQUEST['login'],$_REQUEST['password']);

if ($res==TRUE){

$_SESSION["login"] = $_REQUEST["login"];

}

L'identification basée sur un annuaire LDAP

La mise en place d'une identification basée sur l'annuaire LDAP est assez simple à réaliser. Elle vise à vérifier qu'il est possible de se connecter à l'annuaire en utilisant le couple login/mot de passe.

La classe LoginLdap :

class LoginLdap {
function __construct($LDAP_address, $LDAP_port,$LDAP_basedn, $LDAP_user_attrib,$LDAP_v3,$LDAP_tls) {
$this->LDAP_address = $LDAP_address;
- le port (par défaut, 389) :
$this->LDAP_port = $LDAP_port;
$this->LDAP_basedn = $LDAP_basedn;
$this->LDAP_user_attrib = $LDAP_user_attrib;
$this->LDAP_v3 = $LDAP_v3;
$this->LDAP_tls = $LDAP_tls;
}
function verifLogin($login,$password){
$ldap = @ldap_connect($this->LDAP_address,$this->LDAP_port)
or die("Impossible de se connecter au serveur LDAP.");
if ($this->LDAP_v3)
{
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
}
if ($this->LDAP_tls)
{
ldap_start_tls($ldap);
}
$dn = $this->LDAP_user_attrib."=".$login.",".$this->LDAP_basedn;
$rep=ldap_bind($ldap,$dn, $password);
if ($rep == 1)
{
return true;
}else{
return false;
}
}
}

Et un script qui permet d'utiliser la classe :

$LDAP_address = "localhost";

$LDAP_port = 389;

$LDAP_rdn = "cn=manager,dc=example,dc=com";

$LDAP_basedn = "ou=people,cn=manager,dc=example,dc=com";

$LDAP_user_attrib = "uid";

$LDAP_v3 = true;

$LDAP_tls = false;

$login = new LoginLdap($LDAP_address, $LDAP_port,$LDAP_basedn, $LDAP_user_attrib,$LDAP_v3,$LDAP_tls);

$res=$login->verifLogin($_REQUEST['login'],$_REQUEST['password']);

if ($res==TRUE){

$_SESSION["login"] = $_REQUEST["login"];

}

Avec cette approche, et si l'annuaire LDAP est celui utilisé pour l'identification dans le domaine Windows (Active Directory Service – ADS - ou domaine Samba/ldap), l'utilisateur n'aura pas besoin de retenir un nouvel identifiant.

L'identification basée sur un serveur d'identification CAS

Les deux méthodes d'identification que nous venons d'étudier, l'identification directe et l'identification via un annuaire LDAP, présentent deux écueils. Le premier, c'est que le mot de passe arrive en clair sur le serveur hébergeant l'application : un développeur peu scrupuleux peut mettre en place un « ramasse-miettes », qui va enregistrer dans un fichier à part tous les couples login/mot de passe, pour les réutiliser par la suite pour son compte personnel. Le second, c'est que si l'utilisateur doit travailler avec plusieurs applications, il est obligé de retaper son mot de passe chaque fois qu'il change de programme.

Avec l'avènement des applications web, un nouveau concept est apparu, le SSO (Single Sign On – identification unique). Son principe est simple : la vérification de l'identité de l'utilisateur est sous-traitée à une application particulière. Si l'utilisateur s'est déjà connecté à une des applications utilisant ce SSO, celui-ci fournit directement le login utilisé : l'utilisateur n'a plus besoin de retaper son mot de passe.

La première identification :

1 : l'utilisateur se connecte à l'application

2 : l'application a besoin d'identifier l'utilisateur : elle redirige le navigateur vers le serveur CAS, qui va être chargé de gérer l'identification. Lors de cette phase, le serveur CAS affiche un écran de saisie du login / mot de passe, en mode sécurisé via le protocole https.

3 : Au retour de la saisie du login/mot de passe, le serveur CAS vérifie l'identification auprès de sa base locale (annuaire LDAP, base de données...). Il retourne au navigateur un cookie de session, spécifique au serveur CAS ; l'échange de ce cookie ne se fait qu'en mode sécurisé (https).

4 : le serveur CAS redirige le navigateur de l'utilisateur vers l'application (paramètre passé lors de la phase 2), en lui joignant un ticket de session, utilisable une seule fois.

5 : l'application interroge le serveur CAS, en lui fournissant le ticket de session, et récupère, en retour, l'identifiant (le login) de l'utilisateur.

Les identifications suivantes :

Une fois que l'utilisateur s'est identifié une première fois, son navigateur contient un cookie provenant du serveur CAS.

Lorsqu'une nouvelle application a besoin de connaître le login de l'utilisateur, elle va, elle aussi, rediriger le navigateur vers le serveur CAS (début de la phase 2). Le serveur CAS détecte sur le navigateur un cookie (celui qui a été téléchargé lors de la première identification). Il le vérifie (il expire au bout d'un certain temps, de quelques minutes à quelques heures selon la politique de sécurité mise en place) : s'il est toujours valide, plutôt que d'afficher la page de saisie du login/mot de passe, il redirige directement le navigateur vers l'application en lui transmettant un nouveau ticket de session (phase 4). L'application n'aura plus qu'à récupérer le login (phase 5).

Le codage en PHP :

Nous allons utiliser la classe phpCAS, téléchargeable sur le site http://www.ja-sig.org/wiki/display/CASC/phpCAS.

Les informations à fournir sont les suivantes :

$CAS_address : adresse web du serveur CAS

$CAS_port : port d'interrogation (en général, 443, c'est le port utilisé par défaut par le protocole https)

$CAS_uri : chemin d'accès dans le serveur (par défaut, vide).

if (!isset($_SESSION["login"])) {
include_once('esup-phpcas/source/CAS/CAS.php');
phpCAS::client(CAS_VERSION_2_0,$CAS_address,$CAS_port,$CAS_uri);
phpCAS::forceAuthentication();
$auth = phpCAS::getUser();
$_SESSION["login"] = $auth;
}

Le login est stocké dans la variable de session $_SESSION["login"].

Deux mécanismes sont ainsi mis en place pour gérer l'identification de l'utilisateur :

    • le login est stocké en variable de session. Tant que celle-ci n'a pas expiré, l'utilisateur est considéré comme connu ;
    • si la session a expirée, ou s'il s'agit de la première connexion, le serveur CAS est interrogé pour connaître le login. Si l'utilisateur s'est déjà connecté sur le serveur CAS, ce dernier transmettra directement l'information à notre application, sans repasser par une phase d'identification.

La gestion de la déconnexion avec phpCAS

Si l'utilisateur souhaite se déconnecter, il faut également en avertir le serveur CAS, qui doit révoquer son cookie d'identification.

L'opération va se dérouler en deux temps : d'abord, la suppression de la session, puis la déconnexion auprès du serveur CAS :

// Destruction de toutes les variables de session
$_SESSION = array();
// On efface également le cookie de session.
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// Finalement, on détruit la session.
session_destroy();
phpCAS::client(CAS_VERSION_2_0,$CAS_address,$CAS_port,$CAS_uri);
phpCAS::logout($adresse_retour);

Crypter la saisie du login/mot de passe

Quoi de plus facile que de capturer le login/mot de passe sur un réseau ! Un simple analyseur des trames IP (les messages échangés entre les ordinateurs) permet à toute personne mal intentionnée de lire en clair les mots de passe échangés entre le navigateur et le serveur.

Pour éviter ce problème, il n'y a qu'une solution : le cryptage. Ce cryptage peut être limité à la saisie du login/mot de passe, si les données saisies dans l'application n'ont pas de caractère confidentiel, ou étendu à l'ensemble de l'application. Avant de décider de la meilleure solution, il faut garder à l'esprit que :

le cryptage ralentit le serveur. Certaines études indiquent qu'un cryptage SSL (Secure Socket Layer, le mécanisme de cryptage utilisé en mode HTTPS) ralentit d'environ 30% le serveur. Il faut toutefois noter que le cryptage comprend deux phases : l'initialisation de la connexion, qui se fait par échange de clés asymétriques, et qui est très gourmande en ressources. Le reste de l'échange est effectué par des clés symétriques, plus efficaces. En principe, l'échange des clés asymétriques ne s'opère qu'à l'initialisation de la connexion SSL, elle ne sera pas rejouée pour le reste de la session ;

les données manipulées dans une application de gestion peuvent avoir une valeur juridique importante. Ainsi, la divulgation d'un relevé d'identité bancaire (RIB) ou de données personnelles pourrait être reproché au gestionnaire de l'application s'il n'a pas pris les mesures nécessaires pour éviter que ces données ne puissent être récupérées facilement.

Le cryptage est, en principe, mise en œuvre systématiquement dans les serveurs CAS. Il est également facile de l'activer sur un serveur web ; voici la procédure à suivre pour un serveur Apache (http://www.apache.org/) :

Dans le dossier où l'on souhaite activer le cryptage, il faut créer un fichier .htaccess, qui comprend les lignes suivantes :

RewriteEngine on
RewriteCond %{REMOTE_PORT} !^443$
RewriteRule ^/(.*) https://%{HTTP_HOST}/%{REQUEST_URI}

Pour que la redirection fonctionne, il faut impérativement que le serveur Apache l'autorise ! Sur un intranet, son fichier de configuration (httpd.conf ou apache2.conf, selon les distributions Linux), doit contenir la directive suivante :

<Directory />

Allowoverride All

</Directory>

Dans le cas où il est souhaitable que la communication soit cryptée pour l'ensemble de l'application, d'autres méthodes peuvent être utilisées pour l'implémenter (utilisation des vhosts notamment).

D.La gestion des droits avec PHPGACL

PhpGACL (http://phpgacl.sourceforge.net/) est un projet de gestion des droits qui s'articule autour de quelques classes, et qui est probablement un des outils les plus complets disponibles en PHP. Il est utilisé dans plusieurs applications, dont dotProject (http://www.dotproject.net/), une application de gestion de projet en mode web qui a été intégrée dans Sourceforge, la forge la plus utilisée pour les projets OpenSource sur le web, et qui permet de générer des diagrammes de Gantt, de gérer les tâches de chaque participant..., et Mambo (http://mambo-foundation.org/), un logiciel de gestion de contenu de site web. Il gère trois types d'objets principaux :

    • les ACO (Access Control Object) : ce sont les objets qui vont permettre de contrôler les accès aux différents modules de l'application ;
    • les ARO (Access Request Object) : ce sont les objets qui vont chercher à accéder aux modules de l'application, dans la pratique, les logins regroupés en groupes ;
    • les ACL, (Access Common List) contiennent les droits d'accès. Ils vont faire la relation entre les ACO et les ARO. A noter qu'ils peuvent être positifs (j'ai le droit d'accéder à tel module) ou négatifs : j'ai le droit d'accéder à tel ensemble de modules, sauf à un en particulier. Cela permet de définir, par exemple, que toutes les personnes de tel service ont accès à tel module (droit positif pour le service), sauf les opérateurs de saisie (droit négatif pour ce groupe particulier).

Les ARO contiennent 2 objets : les logins, et les groupes. Dans cet exemple, François Martin est opérateur de saisie, Pierre Durand gestionnaire. Paul Dupont, chef-comptable, hérite des droits attribués au groupe comptabilité ; il est également administrateur informatique, et pourra ainsi accéder aux modules de paramétrage.

Il faut noter également la gestion arborescente des ARO : les groupes les plus à droite (de niveau plus élevé) comprendront également les droits attribués dans les groupes de niveau inférieur.

Les ACO (dans les ovales) correspondent aux droits qui seront testés dans l'application. Ainsi, pour accéder en écriture au module de Calcul, e programme vérifiera que le login de l'utilisateur a bien les droits attribués à l'ACO Calcul. La relation entre les groupes ARO et les ACO correspond aux ACL.

Le schéma a été volontairement simplifié pour en faciliter la lecture : le groupe Gestionnaire doit avoir les droits également pour Calcul (lecture) et Saisie (lecture), le groupe Opérateur de saisie sur Saisie (lecture), etc.

La saisie des ARO

Les groupes sont organisés de manière hiérarchique. Il ne peut y avoir qu'un seul groupe de niveau 0 (ici, la société).

Il faut faire également attention à la notion de groupe enfant (child) : d'un point de vue des droits de l'application, ils ont un poids plus fort que les groupes parents. Ainsi, un login présent dans le groupe chef_comptable disposera également des droits attribués aux groupes comptable, comptabilité et société.

La colonne Name correspond au nom du groupe tel qu'il apparaîtra dans les autres écrans de l'application : c'est une zone de texte libre. La colonne Value correspond à la valeur que l'on utilise effectivement : elle doit être unique dans le référentiel des droits. Quant à la colonne Objects, elle affiche le nombre de logins présents dans chaque groupe.

Pour chaque groupe, plusieurs actions sont possibles :

    • Assign ARO : c'est l'opération qui va permettre d'attribuer les logins au groupe ;
    • Add child : cela va permettre de créer un sous-groupe ;
    • Edit : permet de modifier les libellés du groupe ;
    • Acl permet de visualiser les droits attribués au groupe.

a) Ajouter un groupe enfant

En cliquant sur Add child, un nouveau groupe enfant va pouvoir être saisi (l'opération Edit arrive au même écran, mais en mode modification).

Il suffit de renseigner les zones Name et Value. Dans la pratique, il est conseillé de mettre les mêmes valeurs.

b) Rattacher un login à un groupe

Depuis l'onglet ARO Group Admin, cliquer sur Assign ARO.

Dans phpGACL, les logins sont regroupés en sections : il est ainsi possible de gérer plusieurs catégories de logins, si l'application le nécessite. Dans la pratique, il vaut mieux se limiter à une seule section, ce qui sera nettement plus simple.

Dans la boite Sections, cliquez sur login (s'il n'est pas déjà sélectionné).

La boite Access Request Objects affiche la liste des logins existants.

Pour créer un nouveau login, cliquez sur Edit dans la boite Access Request Objects.

La partie haute permet de visualiser, voire de modifier, les logins existants. La partie basse permet de rajouter de nouveaux logins (5 maximum à la fois). Pour chaque login, il faut indiquer :

    • value : le login qui sera effectivement testé dans l'application ;
    • Order : l'ordre de tri d'affichage des logins dans l'interface phpGACL ;
    • Name : un libellé plus facilement manipulable. Il est fortement conseillé de mettre d'abord le nom de la personne, puis son prénom (classement alphabétique) : avec plusieurs dizaines ou plusieurs centaines de logins, la recherche n'en sera que plus aisée.

Il est possible également de supprimer un login, en cochant la case située à droite de l'écran, puis en cliquant sur le bouton Delete.

La création des ACO

Maintenant que les logins sont créés et organisés par groupes, nous allons pouvoir définir les objets de contrôle, puis attribuer les droits (ACL).

Cliquez sur l'onglet ACL admin :

Nous accédons à l'écran de manipulation des ACO et des ACL :

Nous allons d'abord nous intéresser aux deux premières boites, en haut à gauche : Sections et Access Control Objects. Ces deux boites vont permettre de définir les droits de l'application.

La première boite, Sections, va permettre de définir des sous-ensembles d'ACO. C'est une possibilité qui sera utilisée pour mettre en œuvre une gestion unique des droits au niveau de l'entreprise : dans cette boite, un item sera créé par application. Dans l'exemple ci-dessus, nous n'avons qu'une application, appelée proto.

Cliquer sur proto :

la liste des ACO déjà créés s'affiche pour cette application.

En cliquant sur Edit, nous pourrons accéder à la saisie des différents ACO ; le mode de saisie est identique à celui des logins.

Attribuer les ACL

Maintenant que nous avons créé d'une part nos logins et que nous les avons rattaché aux groupes, et d'autre part les ACO, il nous reste à les relier ensemble, c'est à dire donner les droits sur les ACO aux groupes ARO.

Cliquer sur l'onglet ACL Admin

Dans la première boite en haut à gauche (Sections), cliquer sur le nom de notre application (ici, proto).

Dans la seconde boite (Access Control Objects), sélectionner l'ACO auquel nous souhaitons rattacher un groupe, puis cliquer sur >>. Il est possible de sélectionner plusieurs ACO si nécessaire

Dans la boite Groups, sélectionner le où les groupes que nous souhaitons rattacher aux ACO sélectionnés

Valider en cliquant sur Submit

Utiliser phpGACL dans l'application

include_once ("plugins/phpgacl/gacl.class.php");
$phpgacl = new gacl();
$res = $phpgacl->acl_check("proto", "calcul", "login", "pierre.durand");

$res contiendra 1 si le login pierre.durand dispose des droits pour accéder au module calcul.

Résister aux attaques

Voici quelques attaques fréquentes :

    • l'injection de code SQL, qui consiste à faire exécuter du script SQL différent de celui prévu dans l'application,
    • le cross-site scripting, qui vise à renvoyer l'internaute vers un autre site
    • le cross-site-request-forgery, qui vise à faire exécuter du script par une personne qui dispose de droits étendus
    • le détournement de session, qui s'appuie sur le vol de l'identifiant de session (en général stocké dans un cookie, un fichier permettant de stocker des informations dans le navigateur du poste client). Une fois l'identifiant de session récupéré, l'attaquant réalise toutes les opérations que peut faire l'utilisateur.

L'attaque par injection de code SQL

Prenons une requête de suppression d'un dossier. La classe Dossier dispose de la méthode suivante :

function supprimer($id) {

$sql = 'delete from '.$table.'

where Id = '.$Id;

$resultat = $this->executeSQL($sql);

}

Si $Id vaut 5, l'enregistrement 5 sera alors supprimé. Par contre, si un attaquant modifie la valeur $Id, en lui substituant la chaîne de caractères Id, la requête va devenir :

delete from Personne where Id = Id;

L'exécution de la requête va alors vider la table Personne...

Dans ce cas de figure, la parade est assez simple : il suffit de vérifier que $id est bien un nombre, et non pas une chaîne de caractères.

Autre exemple, concernant, cette fois ci, la modification du mot de passe :

function setPasswd($login, $motDePasse){

$sql = 'update Login

set MotDePasse = "'.$motDePasse.'"

where Login = "'.$login.'"';

$resultat = $this->executeSQL($sql);

}

Nous allons modifier la valeur $login, en la remplaçant par

jean.dupont" or "administrateur

Le code SQL de la requête devient alors :

update Login set ModDePasse = "AZERTYUIOP"

where Compte = "jean.dupont" or "administrateur";

A l'exécution, la requête va non seulement modifier le mot de passe du login jean.dupont, mais également celui du compte administrateur...

Heureusement, PHP est configuré par défaut pour interdire ce type d'attaques. Le fichier php.ini contient, dans quasiment tous les cas, la valeur suivante :

magic_quotes_gpc = on

Avec cette directive, PHP va préfixer les apostrophes ou les doubles apostrophes avec le caractère \. Notre requête va donc devenir :

update Login set ModDePasse = "AZERTYUIOP"
where Compte = "jean.dupont\" or \"administrateur";

et n'aboutira pas, aucun compte ne s'appelant jean.dupont\" or \"administrateur...

Si l'application fonctionne avec une base de données Sybase, cette directive ne fonctionnera pas, Sybase ne traitant pas correctement le caractère \. Il faudra alors modifier les directives suivantes dans le fichier php.ini :

magic_quotes_gpc = Off
magic_quotes_sybase = On

Si l'accès au fichier php.ini n'est pas possible, ces directives peuvent être introduites dans un fichier .htaccess, qui sera placé à la racine de l'application :

php_value magie_quotes_gpc off
php_value magic_quotes_sybase on

Dans ce cas de figure, l'apostrophe est « échappée » par une seconde apostrophe : Jame's devient Jame''s.

Ces directives ne sont pas modifiables en utilisant la fonction PHP ini_set().

Vérifier le type des données introduites

La première protection consiste à vérifier que les données renvoyées par le navigateur sont bien du type qui est attendu. C'est particulièrement vrai pour les nombres, d'autant plus s'ils sont utilisés comme argument dans une requête (cf. l'attaque par injection de code SQL, ci-dessus).

Vérifier si la donnée est bien un nombre

Par défaut, le navigateur renvoie toutes les données sous forme de chaîne de texte. Pour tester s'il s'agit d'une variable numérique, nous pouvons utiliser le script suivant :

if (strlen($var)>0) {
if (is_numeric($var)) {
// c'est un nombre
...
}
}

A noter qu'il faut commencer par vérifier si la chaîne n'est pas vide.

Il est également possible de tester si la valeur entrée est booléenne ou non, avec la fonction is_bool(mixed var).

Pour les chaînes de caractères, il peut être également opportun de vérifier leur longueur. Ainsi, si un numéro de téléphone est attendu, mais que la chaîne passée par le navigateur dépasse 30 caractères, il y a probablement un problème quelque part (erreur de saisie par exemple). La vérification s'effectue avec la fonction strlen(var).

Vérifier le masque – expressions régulières

Dans un certain nombre de cas de figure, il est préférable de s'assurer que les informations fournies par le navigateur respectent bien une forme prédéfinie. Nous utiliserons alors une fonction de vérification de masque, ou motif (pattern en anglais).

Les fonctions de masque s'appuient sur les expressions régulières, qui se retrouvent dans quasiment tous les langages. Ces masques sont bâtis sur un certain nombre de méta-caractères standards. Néanmoins, chaque langage a rajouté ses propres extensions (shells Unix, norme Posix, langage Perl...).

PHP implémente, dans ses dernières versions, les extensions POSIX et PERL, grâce à sa bibliothèque PCRE (Perl Compatible Regular Expressions). Voici la liste des méta-caractères les plus courants utilisables dans les expressions régulières en PHP :

Le masque suivant pourrait être utilisé pour tester la validité d'une adresse mél :

^.+@.+\.[a-zA-Z]{2,6}$

ce qui signifie :

    • une chaîne qui commence par au moins un caractère (^.+),
    • qui contient le signe @
    • qui contient au moins un caractère (.+),
    • suivi d'un point \. ,
    • et qui se termine par une chaîne de 2 à 6 caractères alphabétiques, en majuscules ou en minuscules ([a-zA-Z]{2,6}$

En PHP, Ce masque va pouvoir être vérifié avec la fonction suivante :

$var = "jean.dupont@monserveur.com";
$pattern = "#^.+@.+\.[a-z]{2,6}$#";
if (preg_match($pattern, $var) == 1) {
//Il s'agit d'une adresse mel
...
}

En PHP, les masques doivent être encadrés par les deux mêmes caractères, qui les délimitent. C'est pourquoi le contenu de la variable $pattern est encadrée par le signe #.

L'attaque par cross-site scripting

Le principe de cette attaque est relativement simple. En HTML, il existe une balise, META http-equiv, qui permet de rediriger une page vers une autre, ou de la rafraîchir. Ainsi, le code suivant va déclencher l'affichage d'une nouvelle page au bout de 10 secondes, vers le site http://pirate.com/ :

<META http-EQUIV='Refresh' CONTENT='10; url=http://pirate.com/'>

Il est également possible d'utiliser les balises javascript pour rediriger l'application vers une autre page :

<script>document.location='http://pirate.com'</script>

Une personne mal intentionnée peut pouvoir introduire ce script dans un champ, par exemple une adresse mél. A l'affichage, le navigateur exécutera l'instruction saisie... Il suffit alors au pirate de construire un site d'aspect identique pour induire l'internaute en erreur et lui faire faire n'importe quoi !

Pour éviter ce type d'attaque, nous allons utiliser la fonction PHP htmlspecialchars, qui va transformer les caractères spéciaux HTML en leur équivalent textuel, et ce, avant l'envoi vers le navigateur :

$var = htmlspecialchars($var);
echo ($var);

Les caractères suivants sont transformés :

Ainsi, le code

<META http-EQUIV='Refresh' CONTENT='10; url=pirate.com/'>

devient :

&lt;META http-EQUIV='Refresh' CONTENT='10; url=http://pirate.com/'$gt;

et ne sera plus traité par le navigateur comme une instruction.

Le Cross site request forgery

Le principe général de cette attaque est de faire déclencher du script par l'utilisateur, dans une application où il dispose de droits élevés. Par exemple, un utilisateur souhaite supprimer une fiche, mais il ne dispose pas des droits adéquats. Pour cela, il va faire exécuter le script par un administrateur, et à son insu. Le plus simple, c'est de lui envoyer un mél contenant un lien de type image. En fait, l'URL n'est pas une image, mais un lien vers le script à exécuter sur le serveur, par exemple :

<href=index.php?module=supprimerFiche&id=10>

L'administrateur disposant des droits d'exécution, le script s'exécutera et la fiche sera supprimée.

Pour se prémunir de ce type d'attaque, il n'y a pas de solution miracle. La première, c'est que l'application vérifie systématiquement la requête de l'utilisateur, en lui demandant de confirmer l'opération. C'est souvent fastidieux, et en général utilisé uniquement lors des opérations de suppression.

La seconde approche vise à générer, dans chaque formulaire, une donnée aléatoire, qui sera vérifiée lors de la validation. C'est la technique du jeton, qui doit, de plus, avoir une durée de vie limitée.

La troisième consiste à s'assurer que la page qui déclenche l'action (Referer) est bien celle qui est attendue. Ainsi, cela évite que l'action soit déclenchée depuis une page quelconque, voire hors de l'application (cas du lien fourni dans un mél).

Le détournement de session

La communication entre un serveur web et un navigateur s'effectue en mode asynchrone : chaque nouvelle requête envoyée vers le serveur s'apparente à une nouvelle demande.

Pour pouvoir gérer la continuité de la connexion, les serveurs web mettent en place un mécanisme de session, et transmettent au navigateur un identifiant de session, soit dans une variable, soit dans un cookie (cas le plus fréquent). La session contient des variables, qui permettent notamment de savoir qui est connecté, les droits dont l'utilisateur dispose, etc.

Si un pirate récupère l'identifiant de session, il a alors la possibilité de faire exécuter du code en se faisant passer pour l'utilisateur. Cette récupération peut s'effectuer en redirigeant, par l'intermédiaire d'un lien, l'utilisateur vers un faux site.

A noter que depuis les points d'accès publics en wifi, il est très facile de récupérer les cookies qui circulent en clair sur le réseau (une extension Firefox permet de récupérer tous les cookies « qui passent » en quelques clics) : le risque de piratage est de fait très grand. Pour éviter ce vol lié à l'écoute du réseau, seul le cryptage complet de la session est nécessaire (et non pas seulement la phase d'identification).

Sans rentrer dans les mécanismes détaillés de ce mode d'attaque, il est fortement conseillé, pour s'en protéger, de régénérer l'identifiant de session juste après que l'utilisateur se soit identifié. La fonction session_regenerate_id() sera alors utilisée.

Il est également possible de vérifier que l'adresse IP de la machine qui a ouverte la session est toujours la même. Ce n'est pas une garantie absolue, mais cela peut limiter les risques.

Protéger les accès à certains dossiers de l'application

Lors de l'écriture d'une application web, un grand nombre de pages sont créées, et sont organisées dans une arborescence. Avec le principe du langage HTML, toute page est accessible nativement, en indiquant le chemin complet d'accès, par exemple :

html://monsite.com/monapplication/parametres/monfichierparam.php.

Dans un certain nombre de cas, il est souhaitable de ne pas autoriser l'accès direct à un dossier, comme celui qui contient les fichiers de paramètres, ou ceux qui reçoivent des fichiers en téléchargement.

En général, il est conseillé de déplacer ces dossiers sur le serveur à un endroit où ils ne sont pas directement accessibles. Malheureusement, ce n'est possible que si le programmeur maîtrise complètement le serveur, ce qui est rarement le cas. De plus, il faut bien connaître la structure de l'application pour savoir quels dossiers déplacer, surtout s'il s'agit d'un logiciel récupéré sur Internet.

Avec le serveur Web Apache, la solution pour gérer cette protection est assez simple. Il suffit de créer un fichier nommé .htaccess à la racine du dossier à protéger, qui comprendra les instructions suivantes :

order deny,all
deny from all

Ces deux lignes vont interdire l'accès direct au dossier depuis le navigateur. Cela n'empêchera pas l'application d'y accéder, par l'intermédiaire de la commande include_once, qui permet de charger le fichier.

Avec le serveur Web de Microsoft (IIS, Internet Information Server), ce mécanisme n'est pas pris en charge. La protection des dossiers s'effectue depuis la console d'administration, en indiquant, pour chaque dossier, les droits à attribuer.

Force est de constater que l'approche d'Apache est la plus simple : un copier-coller de l'application entre deux serveurs intègre également la copie des fichiers .htaccess : sur le nouveau serveur, le mécanisme de protection décidé par le développeur est immédiatement opérationnel.

Avec IIS, l'administrateur doit déclarer les droits dossier par dossier, ce qui n'est pas forcément très simple, et il faut surtout que ceux-ci soient décrits : ce n'est que très rarement le cas pour les applications PHP. Par expérience, c'est une information qui ne figure jamais dans les documentations d'installation.

Il est toutefois possible d'installer des modules complémentaires dans les serveurs IIS pour que les fichiers .htaccess soient pris en compte. Des solutions commerciales existent sur Internet, comme, par exemple, http://www.iistools.com/ ou http://www.isapirewrite.com/ (solutions non testées).

Une autre solution, plus complexe, vise à créer une double arborescence pour l'application. On crée deux dossiers de base, par exemple code et www. Seul le dossier www est accessible depuis un navigateur, et l'ensemble du code de l'application est stocké dans le dossier code. Les pages accessibles, stockées dans www, appellent, par l'intermédiaire de fonctions include(), les pages contenant la logique de l'application. Cette approche impose un paramétrage spécifique du serveur web pour qu'il redirige les requêtes vers le dossier www. Ce mécanisme est très souvent implémenté dans les frameworks modernes.

Quelques rappels concernant le cryptage

Principes généraux

Le cryptage est une opération qui vise à éviter qu'un échange puisse être lu par une personne tierce. Deux types de cryptage existent, le cryptage symétrique et le cryptage asymétrique.

Dans le cryptage symétrique (ou cryptage à clé privée), une même clé est utilisée pour crypter et décrypter le message. C'est une technique rapide à mettre en place, mais elle implique que les deux correspondants aient la même clé. Actuellement, l'algorithme AES256 est largement utilisé pour mettre en place un tel cryptage. Il est notamment utilisé dans les cartes bancaires.

Le cryptage asymétrique est d'invention assez récente. Il est basé sur le calcul du produit de deux nombres premiers. Sa résistance tient à l'impossibilité actuelle de factoriser le nombre produit autrement que par la « force brute », c'est à dire en testant toutes les combinaisons possibles. Le temps de calcul croît de façon exponentielle avec la taille de la clé.

L’algorithme le plus connu est le RSA, décrit en 1977 par Ronald Rivest, Adi Shamir et Leonard Adleman. Son principe est simple : deux clés sont générées, et un message crypté avec une des clés ne peut être décrypté qu'avec la seconde, et vice-versa. Dans la pratique, une des deux clés générées reste en la possession exclusive de son propriétaire (la clé privée), la seconde étant transmise à tous les correspondants (la clé publique). Selon que l'on veuille envoyer un message chiffré ou s'assurer de l'identité de l'expéditeur, on utilisera soit la clé publique du correspondant pour chiffrer le message, soit la clé privée.

Pour de plus amples informations concernant le détail du fonctionnement de l'algorithme, consultez l'article de Wikipedia Rivest, Shamir, Adleman1.

Les fonctions de calcul d'empreinte (hashage)

Le calcul d'empreinte permet de calculer, à partir d'un texte ou d'un fichier, un condensat de longueur fixe, qui a les caractéristiques suivantes :

    • il est unique (il n'existe pas de possibilité pour que deux entrées différentes puisse aboutir à la même empreinte – dans ce cas, on parle de collision) ;
    • le texte ou le fichier d'origine ne peut être retrouvé à partir de l'empreinte.

Ce mécanisme va être utilisé principalement dans deux cas :

    • d'une part, quand on veut s'assurer que la copie d'un fichier est bien identique à l'original, par exemple dans le cas du téléchargement d'une image ISO2 ;
    • d'autre part, pour encoder un mot de passe, qui ne pourra pas être décodé.

Pour vérifier la cohérence d'un fichier téléchargé, nous appliquerons le processus suivant :

    • le fournisseur du fichier calcule une empreinte, et la publie ;
    • une fois le fichier récupéré, l'empreinte de celui-ci est calculée ;
    • si les deux empreintes sont identiques, alors on considère que les deux fichiers sont identiques.

Pour stocker les mots de passe, le mécanisme suivant va être utilisé :

    • lors de la création du mot de passe, son empreinte est calculée, et c'est celle-ci qui va être stockée en base de données ;
    • au moment où le mot de passe est utilisé, c'est à dire quand son détenteur le saisit, le programme de vérification calcule l'empreinte du texte saisi, puis la compare à la valeur stockée dans la base de données. Si les deux empreintes sont identiques, alors le mot de passe est correct.

Voici un exemple de calcul d'empreinte du mot Bonjour en utilisant l'algorithme sha-256 (commande sha256sum) :

8dc2a6966f1be1644ec6b1f7223f47e53de5ad05e1c976736d948e7977a13dd3

Il suffit de modifier une seule lettre, en tapant par exemple bonjour (sans majuscule), pour que le résultat soit totalement différent :

9cec0af545144159bac85c7b908d5e0b9b0ef961497401c5ad8da26f065ad926

Pour qu'un algorithme de hashage soit considéré comme suffisamment sûr, il faut :

    • qu'il ne soit pas possible de créer des collisions (même si, comme le nombre de combinaisons est nécessairement fini – la taille du condensat étant fixe – cette possibilité ne puisse jamais être totalement exclue) ;
    • que la longueur de stockage soit suffisamment élevée pour que l'on ne puisse pas créer de dictionnaire inverse, c'est à dire une base de données qui permettrait, à partir du condensat obtenu, d'obtenir l'original. Un codage sur 256 bits entraîne 1,158x1077 combinaisons possibles (2256)...

Le pseudo-cryptage

Si le chiffrement permet de garantir la confidentialité d'une information échangée, il présente un inconvénient : un fichier crypté se reconnaît très facilement, et certains gouvernements totalitaires pourraient être tentés de bloquer les échanges cryptés, par l'utilisation de logiciels qui vont analyser les messages échangés et repérer ceux dont les chaînes de caractères sont totalement aléatoires.

Pour éviter cela, il est possible de transformer les messages envoyés en appliquant des transformations suffisantes pour les rendre incompréhensibles, mais qui ne seront pas considérés comme aléatoires par les systèmes de surveillance automatiques. Bien sûr, ces messages pourraient être décryptés en quelques jours, à condition qu'ils soient reconnus comme tels, être interceptés, et qu'on y consacre des ressources de calcul importantes, mais cela peut être suffisant : certaines informations n'ont pas besoin de rester confidentielles trop longtemps (scoop journalistique, par exemple). On est typiquement dans le rapport entre les moyens à mettre en œuvre pour décoder une information et sa valeur intrinsèque : dans beaucoup de cas, le « jeu n'en vaudra pas la chandelle ».

De plus, si le cryptage est autorisé en France, ce n'est pas le cas dans un certain nombre de pays, qui tiennent à pouvoir déchiffrer tous les messages échangés (lutte contre le terrorisme, par exemple). Des technologies de chiffrage classique comme AES ne pourront pas être utilisées, seules celles permettant un déchiffrage seront permises3.

La bibliothèque PERSEUS4 répond à ces besoins : elle garantit qu'un message échangé ne peut être déchiffré qu'à condition d'y consacrer des ressources très importantes, hors de portée des pirates habituels.

Concrètement, l'idée est de chiffrer les données échangées à l'aide de codes convolutifs5. Une fois chiffré, le code est brouillé à l'aide d'un « bruit » numérique. Avant transmission, les paramètres nécessaires au déchiffrement, générés aléatoirement pour chaque séquence, sont envoyés lors d'une courte session https standard. Le destinataire commence donc par recevoir ces codes à partir desquels il obtiendra sans difficulté la suite de l'échange.

Pour accéder aux informations transmises, tout observateur placé sur la ligne, doit de son côté commencer par déchiffrer la première séquence, avant d'opérer une seconde opération de déchiffrement. Comme les codes changent en permanence de façon aléatoire, le pirate doit fournir une puissance de calcul importante pour ne rien perdre d'une communication. L'augmentation des ressources consommées finirait alors par trahir la machine infectée. Autrement dit, l'écoute « systématique » deviendrait prohibitive, alors qu'il reste possible d'intervenir ponctuellement sur un échange donné, en allouant à cette tâche des machines dédiées.

En raison de sa faible complexité technique, le pseudo-cryptage peut également être mis en place pour protéger des sauvegardes de données : les temps de calcul ne ralentiront pas significativement l'opération, ce qui pourrait se produire avec un chiffrement classique.

Quel chiffrement utiliser ?

Le chiffrement asymétrique est très gourmand en ressources, en raison du mode de calcul, mais il permet de s'assurer de l'identité du correspondant. A contrario, le chiffrement symétrique s'exécute rapidement, mais impose que la clé de chiffrement/déchiffrement soit partagée entre les deux correspondants.

Plusieurs cas d'utilisation peuvent être identifiés :

    • l'échange de fichiers : le fichier est crypté au préalable, puis envoyé, par exemple par mél. L'important, c'est que seul le destinataire puisse décrypter le fichier, pas les personnes qui pourraient l'intercepter. On utilisera alors le cryptage asymétrique.
    • La connexion permanente, par exemple pour se connecter au système d'informations de l'entreprise. On crée alors un tunnel crypté. La procédure de cryptage va être réalisée en deux étapes :
        • le cryptage asymétrique va être utilisé pour initier la connexion, pour s'assurer de l'identité de chacun des correspondants ;
        • une clé de cryptage symétrique va alors être échangée entre les deux correspondants, qui ne sera donc connue que d'eux seuls ;
        • le reste de la communication est crypté en mode symétrique, ce qui sera plus performant et moins coûteux en temps machine.
    • le stockage de mots de passe, par exemple dans une base de données. Dans ce cas, soit on utilise une fonction de cryptage symétrique classique, qui permet de recouvrer le mot de passe, soit on préférera l'utilisation d'une fonction de calcul d'empreinte (hashage), qui garantira la confidentialité du mot de passe.

Quelques algorithmes de chiffrement

RSA

Cf. le début de ce chapitre.

Blowfish6

Blowfish est un algorithme de chiffrement symétrique (i.e. « à clef secrète ») par blocs conçu par Bruce Schneier en 1993. Il tire son nom du poisson globe japonais (ou fugu), qui en est également l'emblème.

Blowfish utilise une taille de bloc de 64 bits et la clé de longueur variable peut aller de 32 à 448 bits. Elle est basée sur l'idée qu'une bonne sécurité contre les attaques de cryptanalyse peut être obtenue en utilisant de très grandes clés pseudo-aléatoires.

Blowfish présente une bonne rapidité d'exécution excepté lors d'un changement de clé, il est environ 5 fois plus rapide que Triple DES et deux fois plus rapide que IDEA. Malgré son âge, il demeure encore solide du point de vue cryptographique avec relativement peu d'attaques efficaces sur les versions avec moins de tours. La version complète avec 16 tours est à ce jour entièrement fiable et la recherche exhaustive reste le seul moyen pour l'attaquer.

Il a été placé dans le domaine public par son créateur ; il n'est protégé par aucun brevet, et son utilisation n'est pas soumise à licence. Cela explique en partie son succès, car ce fut un des premiers algorithmes de chiffrement dont l'utilisation était libre. Il est utilisé dans de nombreux logiciels propriétaires et libres (dont GnuPG et OpenSSH).

DES et triple DES7

Le Data Encryption Standard (DES) est un algorithme de chiffrement symétrique (chiffrement par bloc) utilisant des clés de 56 bits. Son emploi n'est plus recommandé aujourd'hui, du fait de sa lenteur à l'exécution et de son espace de clés trop petit permettant une attaque systématique en un temps raisonnable. Quand il est encore utilisé c'est généralement en Triple DES, ce qui ne fait rien pour améliorer ses performances. DES a notamment été utilisé dans le système de mots de passe UNIX.

AES8

Advanced Encryption Standard ou AES (soit « standard de chiffrement avancé » en français), aussi connu sous le nom de Rijndael, est un algorithme de chiffrement symétrique. Il remporta en octobre 2000 le concours AES, lancé en 1997 par le NIST et devint le nouveau standard de chiffrement pour les organisations du gouvernement des États-Unis.

Autres...

On peut également citer Serpent et Twofish, que l'on retrouve dans des logiciels de cryptage comme Truecrypt (http://www.truecrypt.org/).

Quelques algorithmes de calcul d'empreintes

Whirlpool9

Whirlpool est une fonction de hachage cryptographique conçue par Vincent Rijmen et Paulo Barreto pour le projet NESSIE. Elle a été nommée d'après la galaxie M51. La fonction utilise une architecture de type Miyaguchi-Preneel connue pour sa résistance à la cryptanalyse, cette structure produit des empreintes de 512 bits (…).

En interne, l'algorithme travaille sur 512 bits grâce à une fonction similaire à celle de l'algorithme de chiffrement symétrique AES (auquel Vincent Rijmen a également participé et qui à l'origine s'appelle Rijndael). L'utilisation d'une version modifiée du bloc de chiffrage de AES (appelée W) garantit un système robuste et fiable.

SHA-25610

SHA-256 (Secure Hash Algorithm) est une fonction de hachage cryptographique conçue par la National Security Agency des États-Unis (NSA), et publiée en 2000. Elle produit un résultat (appelé « hash » ou condensat) de 256 bits et dérive du SHA-1.

SHA-256 est devenu le nouveau standard recommandé en matière de hachage cryptographique après les attaques sur MD5 et SHA-1.

MD511

L'algorithme MD5, pour Message Digest 5, est une fonction de hachage cryptographique qui permet d'obtenir l'empreinte numérique d'un fichier (...). Il a été inventé par Ronald Rivest en 1991.

L'utilisation de cette fonction de hachage dans les signatures numériques peut conduire à de multiples scénarios d'attaque et n'est plus considérée comme un composant fiable de l'infrastructure à clés publiques.

En 2004, une équipe chinoise découvre des collisions complètes. MD5 n'est donc plus considéré comme sûr au sens cryptographique. On suggère maintenant d'utiliser plutôt des algorithmes tels que SHA-256, RIPEMD-160 ou Whirlpool.

Cependant, la fonction MD5 reste encore largement utilisée comme outil de vérification lors des téléchargements et l'utilisateur peut valider l'intégrité de la version téléchargée grâce à l'empreinte. Elle est également utilisée par GNU/Linux pour stocker les mots de passe (en utilisant une fonction complémentaire pour compliquer le déchiffrage).

Algorithme de signature

DSA

Le Digital Signature Algorithm a été inventé alors que le RSA était encore breveté. Il est basé sur le même principe de clés asymétriques, et est utilisé uniquement pour la signature.

En pratique, on le retrouve associé à SSH, notamment pour identifier les serveurs susceptibles de se connecter automatiquement à un autre serveur sans fournir de mot de passe.

Le cryptage asymétrique

Comment s'utilise le cryptage asymétrique ?

Paul et Julie disposent chacun de clés asymétriques, une clé privée, qu'ils conservent en leur possession, et une clé publique, qu'ils transmettent à leurs correspondants12.

Pour crypter un échange

Paul veut envoyer un fichier crypté à Julie. Voici les différentes étapes qu'il va suivre :

    • Julie transmet sa clé publique à Paul ;
    • Paul crypte son fichier avec la clé publique de Julie, puis lui transmet son fichier crypté ;
    • Julie décrypte le fichier avec sa clé privée.

Pour signer un fichier

Paul veut transmettre un message, et Julie veut être sûre que c'est Paul qui lui envoie :

    • Paul transmet sa clé publique à Julie ;
    • Paul crypte son message avec sa clé privée ;
    • Julie reçoit le message, et le décrypte avec la clé publique de Paul : si le décryptage fonctionne, c'est que c'est bien Paul qui a envoyé le message.

Le tiers de confiance

Bien sûr, cela ne peut fonctionner que :

    • si Paul est sûr que la clé publique fournie par Julie est bien la sienne ;
    • si Julie est sûre que la clé publique fournie par Paul lui appartient bien...

Pour cela, Paul et Julie vont demander à un tiers de confiance, c'est à dire quelqu'un dont l'identité est reconnue par tous, de valider leur clé publique. Pour la clé de Paul, ce tiers de confiance va crypter l'empreinte de sa clé publique avec sa propre clé privée. Ce tiers de confiance va donc :

    • récupérer la clé publique de Paul ;
    • s'assurer qu'il s'agit bien de Paul, et pas de quelqu'un d'autre13 ;
    • calculer l'empreinte de la clé de Paul ;
    • crypter cette empreinte avec sa propre clé privée.

Pour s'assurer que la clé de Paul est bien la sienne, Julie va :

    • calculer l'empreinte de la clé de Paul ;
    • utiliser la clé publique du tiers de confiance, pour décrypter l'empreinte cryptée.

Si les deux informations sont identiques, alors Julie sera sûre qu'elle est bien en possession de la clé de Paul.

Le tiers de confiance est donc une autorité reconnue par tous, qui dispose d'une clé privée, et d'une clé publique qu'il va distribuer. Mais comment éviter que quelqu'un crée son propre certificat, en se faisant passer pour un autre ? Après tout, chacun peut facilement créer une clé privée et un certificat, et se faire passer pour une société comme Verisign, par exemple14. Il est possible également d'émettre un certificat comprenant le nom d'une banque, de créer un site ressemblant à s'y méprendre au site institutionnel de celle-ci, puis, au moyen de pages web malicieuses, rediriger les internautes vers ce site pirate.

Normalement, l'internaute devrait avoir ceci :

    • certificat racine Verisign
        • certificat banque XXX
            • site banque XXX

À partir du site pirate, l'architecture sera la suivante :

    • faux certificat Verisign
        • faux certificat de la banque XXX
            • faux site de la banque XXX

C'est sur les « épaules » du navigateur que va porter la responsabilité de valider ou non le certificat racine, c'est à dire toute la chaîne de certification. Si le navigateur ne contient pas le certificat racine, il va émettre une alerte :

Le navigateur a vérifié plusieurs points :

    • est-ce que le nom du site correspond exactement au nom présent dans le certificat ?
    • Est-ce qu'il existe un certificat racine connu pour ce site ?

Les navigateurs modernes intègrent les certificats des tiers de confiance. Vous pouvez les consulter, par exemple dans Firefox, à partir du menu Outils → Options (ou Édition → préférences sous Windows), bouton Avancé, onglet Chiffrement, Afficher les certificats, puis Autorités.

N'intégrez jamais des certificats d'autorités qui ne seraient pas présents, à moins que vous ne soyez sûrs de ce que vous faites (autorité interne à une entreprise, par exemple). De même, ne passez jamais outre les alertes concernant la sécurité d'un site, sauf s'il s'agit d'un site interne à votre entreprise (et qu'on vous en a informé au préalable), ou s'il s'agit d'un site internet où vous n'avez pas besoin de vous identifier (sites d'informations qui utilisent systématiquement le protocole https).

Les certificats chaînés

Nous l'avons vu, le point faible de la chaîne de certification est le certificat racine initial. Dans la pratique, les sociétés de certification n'utilisent (ou ne devraient utiliser) le certificat racine que très rarement, et uniquement pour créer des autorités de certification intermédiaires. Ainsi, générer un certificat pour un serveur ou pour une personne entraîne souvent une chaîne de certification relativement longue. Voici par exemple la chaîne de certification concernant un site du ministère de l'agriculture :

    • IGC/A : certificat racine de l'État français
        • Agriculture AC Racine : certificat racine, validé par l'IGC/A, pour le ministère de l'agriculture
            • Agriculture AC Serveurs : autorité de certification qui délivre les certificats pour les serveurs
                • eap.agriculture.gouv.fr : certificat du site éponyme

Pour vérifier le certificat eap.agriculture.gouv.fr, il faudra donc vérifier chacune des signatures des certificats précédents, jusqu'à remonter au certificat racine IGC/A. Le logiciel qui voudra s'assurer de la validité du certificat devra donc :

    • vérifier l'empreinte du certificat eap.agriculture.gouv.fr, cryptée avec la clé privée de Agriculture AC Serveurs, à l'aide de la clé publique correspondante ; cette clé publique est intégrée dans le certificat Agriculture AC Serveurs ;
    • vérifier de la même façon l'empreinte du certificat Agriculture AC Serveurs, cryptée avec la clé privée de Agriculture AC Racine, à partir de la clé publique contenue dans le certificat correspondant ;
    • enfin, vérifier l'empreinte du certificat Agriculture AC Racine, cryptée avec la clé privée de IGC/A, à partir de la clé publique présente dans le certificat éponyme.

Si un seul des certificats présentés n'est pas valide (expiré, révoqué...), le certificat eap.agriculture.gouv.fr ne pourra pas être considéré comme sûr.

La plus grande difficulté de cette vérification tient au fait qu'il faut disposer de tous les certificats intermédiaires. En général, les certificats racines considérés comme sûrs sont intégrés dans les logiciels, notamment les navigateurs ou les clients de messagerie. Par contre, les certificats intermédiaires doivent être récupérés, soit automatiquement15, soit manuellement, pour que la vérification puisse se faire.

Dans les certificats personnels de type p12, les certificats des autorités intermédiaires sont en principe intégrés. Ce n'est pas toujours le cas pour d'autres certificats : il importe donc soit de les importer manuellement, soit de demander au logiciel qui génère le cryptage (serveur web Apache, par exemple), de présenter la liste des certificats intermédiaires.

Il est également important de mettre à jour régulièrement les logiciels qui utilisent les certificats, pour qu'ils puissent intégrer les nouvelles autorités racines, ou pour qu'ils soient purgés des autorités racines qui ne sont plus considérées comme fiables, suite à une attaque se traduisant par une corruption de la chaîne de certification, par exemple.

La révocation des certificats

Un certificat est émis pour une durée déterminée. Toutefois, il peut arriver que ce certificat ne soit plus sûr : il suffit que la clé privée qui lui est attachée soit divulguée pour qu'il ne puisse plus être utilisé. C'est bien le principe même des clés asymétriques : si la clé privée est détenue par quelqu'un d'autre que son propriétaire, la confidentialité des informations échangées ne peut plus être garantie.

Ainsi, les autorités de certification éditent régulièrement des listes des certificats qui sont révoqués avant leur date d'expiration (fichiers au format crl principalement). L'adresse où l'on peut trouver les listes de révocation est souvent intégrée dans les certificats.

Suite à des attaques informatiques de grande ampleur, il est même arrivé que le certificat racine d'une autorité de certification soit volé, ou utilisé pour générer des certificats frauduleux : ainsi, ce sont tous les certificats émis par cette autorité qui n'ont plus de valeur et qui doivent être révoqués.

En résumé...

Le cryptage asymétrique est basé sur la mise en place d'un couple de clés (également appelé bi-clés) ; une information cryptée avec une clé ne peut être décryptée qu'avec l'autre. Une des deux clés est nommée la clé privée, l'autre la clé publique.

La clé privée est conservée précieusement par son propriétaire, et ne doit en aucun cas être divulguée.

La clé publique est transmise à l'ensemble des correspondants, qui l'utilisent soit pour s'assurer de l'identité de son propriétaire, soit pour lui envoyer des informations cryptées.

Pour garantir l'identité du détenteur de la clé publique, celle-ci est signée par une autorité de certification reconnue. La signature, ainsi que la clé publique, sont stockées dans un certificat numérique.

Un certificat racine est un certificat auto-signé par une autorité de certification, qui contient donc la clé publique de cette autorité.

Pour vérifier un certificat, il faut impérativement disposer du certificat racine de l'autorité de certification, voire des certificats des autorités intermédiaires.

Un certificat a une durée de validité limitée. Il peut être révoqué avant sa date d'expiration ; des listes de certificats révoqués sont régulièrement publiées par les autorités de certification.

1http://fr.wikipedia.org/wiki/Rivest_Shamir_Adleman

2Image d'un disque, qui pourra être reproduit à l'identique

3Mais ça ne signifie pas que le déchiffrage soit facile et à la portée de tous !

4Pour plus d'informations concernant PERSEUS, un article dans Linux Magazine N° 135 : PERSEUS : protéger des communications avec du bruit (http://www.gnulinuxmag.com/index.php/2011/01), ou une page web : http://www.clubic.com/actualite-308400-perseus-chiffrement-donnees-responsable.html

5Un code convolutif est un code qui utilise les valeurs obtenues précédemment pour continuer le codage (effet mémoire). Ils sont très souvent utilisés comme codes de détections d'erreurs, notamment dans les transmissions.

6Source : wikipedia - http://fr.wikipedia.org/wiki/Blowfish

7Source : wikipedia - http://fr.wikipedia.org/wiki/Data_Encryption_Standard

8Source : wikipedia - http://fr.wikipedia.org/wiki/Standard_de_chiffrement_avancé

9Source : wikipedia - http://fr.wikipedia.org/wiki/Whirlpool_(algorithme)

10Source : wikipedia - http://fr.wikipedia.org/wiki/SHA-256

11Source : wikipedia - http://fr.wikipedia.org/wiki/MD5

12Par défaut, les logiciels de messagerie, comme Thunderbird, transmettent systématiquement les clés publiques aux correspondants, ce qui permet d'initier les échanges et de faciliter les échanges cryptés futurs.

13Cela peut être en vérifiant les papiers d'identité, un code fourni dans un document, comme la déclaration d'impôts ou le montant de la dernière facture associé à un numéro de client...

14Il est facile d'intégrer n'importe quelle information dans un certificat auto-généré, et pourquoi pas, le nom d'une société...

15Les serveurs web comme Apache peuvent fournir les certificats intermédiaires, à condition d'être correctement configurés (il faut qu'ils disposent d'un certificat « bundle » comprenant tous les certificats utilisés)