Académique Documents
Professionnel Documents
Culture Documents
7 novembre 2022
| 7 novembre 2022 | PAGE 1/97
Première partie I
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
3 OS Hardening
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Algorithmique
Les algorithmes sont optimisés pour avoir la complexité la plus faible
possible, parfois en se basant sur des hypothèses de fonctionnement
normal.
Propriété
Une table de hashage est une structure de données permettant
l’insertion et la lecture efficace d’un item.
⇒ Utilisation d’une fonction de hashage
Propriété
Une table de hashage est une structure de données permettant
l’insertion et la lecture efficace d’un item.
⇒ Utilisation d’une fonction de hashage
L’efficacité d’une table de hashage se montre donc dans une distribution
uniforme des items.
Par définition, il y aura toujours des collisions. Des attaques ont été
montées contre :
Bro : 78% de perte de paquet à 160 Kb/s
Squid : ajout de 1.7 ms de latence par accès
Perl : explosion exponentielle du temps de traitement
1 import datetime as d
2
3 bad_re = r e . c o m p i l e ( r " (^[ −!# $%&’∗+/=?^_‘ { } | ~ 0 − 9A−Z]+(\.[ −!# $%&’∗+/=?^_‘ { }
4 r ’ | ^ " ( [ \0 0 1 −\ 0 1 0 \ 01 3 \ 0 1 4 \ 0 1 6 −\ 0 3 7 ! # −\ [ \ ] −\ 1 7 7 ] | \ \[ \ 0 0
5 r ’ )@ ( ? : [ A−Z0 −9]+(?: −∗[A−Z0 − 9 ] + )∗ \ . ) + [A−Z ] { 2 , 6 } $$ ’ , r e
6
7 def bench_regex ( regexp , data ) :
8 a=d . d a t e t i m e . now ( )
9 r e g e x p . match ( d a t a )
10 r e t u r n d . d a t e t i m e . now() − a
11
12 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbb ’ )
13 datetime . t i m e d e l t a (0 , 0 , 203858)
14 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbb ’ )
15 datetime . t i m e d e l t a (0 , 0 , 397430)
16 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbbb ’ )
17 datetime . t i m e d e l t a (0 , 0 , 781776)
18 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbbbb ’ )
19 datetime . t i m e d e l t a (0 , 1 , 569782)
20 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbbbbb ’ )
21 datetime . t i m e d e l t a (0 , 3 , 116798)
22 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbbbbbb ’ )
23 datetime . t i m e d e l t a (0 , 6 , 240200)
24 >>> b e n c h _ r e g e x ( bad_re , ’ aaaaaa@bbbbbbbbbbbbbbbbbbbbbbbbbb ’ )
25 datetime . t i m e d e l t a (0 , 12 , 420262)
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Problème
On a besoin d’une clef RSA 2048 bits
Mais elle est générée en utilisant gen_prime()
Le générateur d’aléa a une graine de 32 bits.
La clef peut être devinée après 232 essais au lieu de 21024
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
time-of-check-to-time-of-use, TOCTTOU
C’est faire l’hypothèse qu’une ressource ne sera pas modifiée entre sa
vérification et son utilisation.
(Mauvaises) Hypothèses :
Une séquence d’instruction n’est pas atomique
Une ligne de code source n’est pas atomique
Le flot de programme peut être ralenti ou interrompu par un
attaquant.
Vulnérable
1 s t=o s . s t a t ( ’ /tmp/ t o t o ’ )
2 i f s t . s t _ u i d != o s . g e t u i d ( ) :
3 r a i s e Exception ( ’ Erreur ’ )
4 f d=open ( ’ /tmp/ t o t o ’ )
5 ...
Vulnérable
1 s t=o s . s t a t ( ’ /tmp/ t o t o ’ )
2 i f s t . s t _ u i d != o s . g e t u i d ( ) :
3 r a i s e Exception ( ’ Erreur ’ )
4 f d=open ( ’ /tmp/ t o t o ’ )
5 ...
Version correcte
1 f d = open ( ’ /tmp/ t o t o ’ )
2 s t = os . f s t a t ( fd . f i l e n o ( ) )
3 i f s t . s t _ u i d != o s . g e t u i d ( ) :
4 fd . c l o s e ()
5 r a i s e Exception ( ’ Erreur ’ )
Sendmail
1 v o i d s i g h n d l r ( i n t dummy) {
2 s y s l o g (LOG_NOTICE , u s e r _ d e p e n d e n t _ d a t a ) ;
3 free ( global_ptr2 ) ;
4 free ( global_ptr1 ) ;
5 e x i t (0) ;
6 }
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Définition
En language C, une chaîne de caractères n’est qu’un ensemble de
caractères terminé par NULL.
⇒ Il n’y a pas de notion de taille !
1 char buf [ 5 1 2 ] ;
2 s n p r i n t f ( buf , s i z e o f buf , "/ v a r / app/%s . t x t " , u s e r n a m e ) ;
3 i n t f d = open ( buf , O_RDONLY) ;
1 char buf [ 5 1 2 ] ;
2 s n p r i n t f ( buf , s i z e o f buf , "/ v a r / app/%s . t x t " , u s e r n a m e ) ;
3 i n t f d = open ( buf , O_RDONLY) ;
1 char buf [ 5 1 2 ] ;
2 s n p r i n t f ( buf , s i z e o f buf , "/ v a r / app/%s . t x t " , u s e r n a m e ) ;
3 i n t f d = open ( buf , O_RDONLY) ;
1 char buf [ 5 1 2 ] ;
2 s n p r i n t f ( buf , s i z e o f buf , "/ v a r / app/%s . t x t " , u s e r n a m e ) ;
3 i n t f d = open ( buf , O_RDONLY) ;
Code supposé retirer tous les ../ dans une chaîne de caractères :
1 i =0
2 w h i l e i +3 <= l e n ( b u f ) :
3 i f b u f [ i ] == ’ . ’ and b u f [ i +1] == ’ . ’ and b u f [ i +2] == ’ / ’ :
4 buf = buf [ : i ] + buf [ i +3:]
5 i += 1
Code supposé retirer tous les ../ dans une chaîne de caractères :
1 i =0
2 w h i l e i +3 <= l e n ( b u f ) :
3 i f b u f [ i ] == ’ . ’ and b u f [ i +1] == ’ . ’ and b u f [ i +2] == ’ / ’ :
4 buf = buf [ : i ] + buf [ i +3:]
5 i += 1
Et si buf == ”....//” ?
Code supposé retirer tous les ../ dans une chaîne de caractères :
1 i =0
2 w h i l e i +3 <= l e n ( b u f ) :
3 i f b u f [ i ] == ’ . ’ and b u f [ i +1] == ’ . ’ and b u f [ i +2] == ’ / ’ :
4 buf = buf [ : i ] + buf [ i +3:]
5 i += 1
Et si buf == ”....//” ?
Dépassement de tampon
Écriture en dehors de la zone allouée.
1 Introduction
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
1 <?php
2 $color = ’ blue ’ ;
3 i f ( _ _ i s s e t ( $_GET [ ’COLOR ’ ] ) )
4 $ c o l o r = $_GET [ ’COLOR ’ ] ;
5 r e q u i r e ( $ c o l o r . ’ . php ’ ) ;
6 ?>
1 <?php
2 $ u s e r=$_GET [ ’ u s e r n a m e ’ ] ;
3 $ p a s s=$_GET [ ’ p a s s w o r d ’ ] ;
4
5 $ r e q = " s e l e c t ␣ p a s s w o r d ␣ from ␣ u s e r "
6 . " w h e r e ␣ u s e r =\" " . $ u s e r . " \" " ;
7 mysql_query ( $req , $ctx ) ;
8 ?>
1 <?php
2 $ u s e r=$_GET [ ’ u s e r n a m e ’ ] ;
3 $ p a s s=$_GET [ ’ p a s s w o r d ’ ] ;
4
5 $ r e q = " s e l e c t ␣ p a s s w o r d ␣ from ␣ u s e r "
6 . " w h e r e ␣ u s e r =\" " . $ u s e r . " \" " ;
7 mysql_query ( $req , $ctx ) ;
8 ?>
man 3 system
system() executes a command specified in command by calling
/bin/sh -c command
man 3 system
system() executes a command specified in command by calling
/bin/sh -c command
Caractères dangereux
: > ‘ * ( " " ^ "\\" "\r"
; & ! / ) [ ~ ’ "\n"
< | - ? . ] \ " $
Caractères dangereux
: > ‘ * ( " " ^ "\\" "\r"
; & ! / ) [ ~ ’ "\n"
< | - ? . ] \ " $
Vraie solution
Utilisation directe de execve()
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Appel de fonction
1 c a l l myfunc
2 prologue
3 c o d e de l a f u n c t i o n
4 epilogue
5 ret
6 ...
Prologue
1 pu sh ebp ; ; C r e e r une n o u v e l l e s t a c k f r a m e
2 mov ebp , e s p ; ; I n s t a l l e r l a n o u v e l l e s t a c k frame
Épilogue
1 mov esp , ebp
2 pop ebp ; ; Restaure l a s t a c k frame
Buffer overflow
Un overflow est un débordement de tableau. Par exemple, une chaîne de
caractère qui est copiée au delà de sa zone allouée.
Cela arrive quand :
On utilise des fonctions non-sûre telles que strcpy, sprintf car
elles n’ont pas la notion de taille maximale.
Problème arithmétique : on calcule mal la longueur d’une chaîne de
caractères.
Problème d’algorithme qui boucle.
Code
1 char buf [ 1 2 8 ] ;
2
3 s t r c p y ( buf , a r g v [ 1 ] ) ;
Ou à la main :
1 char buf [ 1 2 8 ] ;
2 i n t len = a t o i ( argv [ 1 ] ) ;
3
4 for ( int i = 0 ; i < len ; i ++)
5 b u f [ i ] = ’A ’ ;
0x00000000 local1
local2
ebp
ret addr
arg1
0xffffffff arg2
0x00000000 local1
local2
ebp
ret addr
arg1
0xffffffff arg2
0x00000000 local1
local2
ebp
ret addr
arg1
0xffffffff arg2
0x00000000 local1
local2
ebp
ret addr
arg1
0xffffffff arg2
unlink()
1 #d e f i n e u n l i n k ( P , BK, FD ) { \
2 BK = P−>bk ; \
3 FD = P−>f d ; \
4 FD−>bk = BK ; \
5 BK−>f d = FD ; \
6 }
1 #d e f i n e f r o n t l i n k ( A , P , S , IDX , BK, FD ) { \
2 i f ( S < MAX_SMALLBIN_SIZE ) { \
3 ... \
4 } else { \
5 IDX = b i n _ i n d e x ( S ) ; \
6 BK = b i n _ a t ( A , IDX ) ; \
7 FD = BK−>f d ; \
8 i f ( FD == BK ) { \
9 m a r k _ b i n b l o c k (A , IDX ) ; \
10 } else { \
11 w h i l e ( FD != BK && S < c h u n k s i z e (FD) ) { \
12 FD = FD−>f d ; \
13 } \
14 BK = FD−>bk ; \
15 } \
16 P−>bk = BK ; \
17 P−>f d = FD ; \
18 FD−>bk = BK−>f d = P ; \
19 } \
20 }
Erreur fréquence
Utilisation de mauvaises bornes pour le parcours de tableau ;
Écriture d’un ’\0’ trop loin ;
Utilisation de strncat.
Exemple :
Avant : saved_ebp == 0x804d5f4
Après : saved_ebp == 0x804d500
Si 0x804d500 pointe dans notre buffer, c’est gagné !
Rien d’infini
En C, il n’existe pas de type permettant d’avoir des nombres de tailles
« maléables ».
⇒ Débordement de capacité
0xFFFFFFFF + 1 = 0 (1)
0x 40000020 ∗ 4 = 0x 80 (2)
0 − 1 = 0xFFFFFFFF (3)
1 unsigned i n t n ;
2 s t r u c t r e q _ h d r ∗ hdr , ∗∗ r e q s ;
3
4 n = get_number_of_requests ( buf ) ;
5 r e q s = m a l l o c ( n∗ s i z e o f ( ∗ h d r ) ) ; /∗ i n t e g e r o v e r f l o w ∗/
6
7 f o r ( i n t i = 0 ; i < n ; i ++) { /∗ on e c r i t d a n s l e t a b l e a u ∗/
8 reqs [ i ] = foo_bar ( . . . ) ; /∗ de t a i l l e i n s u f f i s a n t e ∗/
9 }
1 i n t l e n g t h = get_from_network ( buf ) ;
2
3 b u f = m a l l o c ( BUFSIZE ) ;
4
5 i f ( l e n g t h < 0 | | l e n g t h +1 > BUFSIZE )
6 r e t u r n −ERR ;
7 else
8 r e a d ( f d , buf , l e n g t h ) ;
1 i n t l e n g t h = get_from_network ( buf ) ;
2
3 b u f = m a l l o c ( BUFSIZE ) ;
4
5 i f ( l e n g t h < 0 | | l e n g t h +1 > BUFSIZE )
6 r e t u r n −ERR ;
7 else
8 r e a d ( f d , buf , l e n g t h ) ;
1 i n t l e n g t h = get_from_network ( buf ) ;
2
3 b u f = m a l l o c ( BUFSIZE ) ;
4
5 i f ( l e n g t h < 0 | | l e n g t h +1 > BUFSIZE )
6 r e t u r n −ERR ;
7 else
8 r e a d ( f d , buf , l e n g t h ) ;
1 i n t f o o = −1;
2
3 i f ( foo < s i z e o f ( i n t )) {
4 /∗ t o u j o u r s v r a i ? ∗/
5 }
1 i n t f o o = −1; 1 i n t f o o = −1;
2 2
3 i f ( foo < s i z e o f ( i n t )) { 3 i f (0 x f f f f f f f f < s i z e o f ( i n t ) ) {
4 /∗ t o u j o u r s v r a i ? ∗/ 4 /∗ t o u j o u r s f a u x ∗/
5 } 5 }
man 3 printf
1 int p r i n t f ( co n s t char ∗ format , ...);
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Roadmap
Identifier :
1 Les ressources ;
2 Les acteurs ;
3 Les relations entre les ressources et les acteurs.
Compromis
Un algorithme simple peut être préférable à une table de hashage même
si les performances ne sont pas les meilleures.
⇒ Savoir relativiser les besoins est important.
Compromis
Un algorithme simple peut être préférable à une table de hashage même
si les performances ne sont pas les meilleures.
⇒ Savoir relativiser les besoins est important.
Design de qmail
Combattez les idées reçues aussi ! Par exemple, qmail lance un
programme uniquement pour le parsing d’une adresse mail. Et il fait
partie des logiciels passant le mieux à l’échelle.
En cas de plantage. . .
En fonction du contexte, différentes actions peuvent être utilisées :
Fail open : plus de protection, tout est autorisé
Fail closed : on bloque tout.
Design conservateur
Un design « conservateur » est un design qui a été écrit en se demandant
pourquoi les objets sont accessibles plutôt que pourquoi ils ne le sont
pas.
⇒ Même principe qu’un firewall !
Exemple : l’authentification UNIX.
En théorie, les tests unitaires devraient être écrit avant l’écriture du code
par une autre personne.
Ils permettent principalement de se forcer à réfléchir à tous les cas
possibles.
Mode de développement
Un audit permanent est toujours indispensable.
Pendant le développement, l’intégration de modifications devrait être
relues par un nombre minimum de personnes.
Cela assure :
La documentation des modifications (commentaire, messages de
logs) ;
Une certaine cohérence dans le code ;
Une relecture attentive.
Mode de développement
Un audit permanent est toujours indispensable.
Pendant le développement, l’intégration de modifications devrait être
relues par un nombre minimum de personnes.
Cela assure :
La documentation des modifications (commentaire, messages de
logs) ;
Une certaine cohérence dans le code ;
Une relecture attentive.
vsftpd est un serveur FTP considéré comme l’un des plus sécurisé.
Audit rigoureux
Chaque fichier a une note de confiance ;
À chaque audit du fichier, sa note est augmentée ;
À chaque moditication du fichier, sa note revient à 0.
L’observateur
A une vision globale du projet ;
Joue le rôle de Bernard Pivot ;
Lit la documentation pour vérifier les effets de bords ;
Le programmeur
Code.
La confrontation des deux points de vue est intéressante.
1 Introduction
2 Attaque
3 OS Hardening
La part de l’administrateur
Protections
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Définition
Un système d’exploitation a la charge d’abstraire le matériel aux
applications en se basant sur des niveaux de privilège.
Il permet de faire tourner de multiples applications en même temps, de
permettre son usage par plusieurs utilisateurs, etc.
Inter-Process Communication
Signaux ;
Valeur de retour ;
Socket UNIX ou réseau ;
Mémoire partagée ;
Sémaphore.
chroot()
Le chrootage permet de modifier la racine (/) d’un processus donné.
Ainsi, il lui est impossible d’accéder en dehors de cet espace.
chroot()
Le chrootage permet de modifier la racine (/) d’un processus donné.
Ainsi, il lui est impossible d’accéder en dehors de cet espace.
Ce n’est pas un outil de sécurité !
chroot()
Le chrootage permet de modifier la racine (/) d’un processus donné.
Ainsi, il lui est impossible d’accéder en dehors de cet espace.
Ce n’est pas un outil de sécurité !
Sauf si vous utilisez un patch de sécurité comme grsecurity
Pour se protéger :
Changer d’UID ;
Se tracer soit-même.
Des patches noyau (grsecurity) permettent d’empêcher les processus à
l’intérieur de chroot d’envoyer des signaux en dehors.
1 Introduction
Règles du jeux
Vulnérabilités cryptographiques
Vulnérabilités logiques
Manipulation des chaînes de caractères
2 Attaque
Injections
Corruption mémoire
Programmation sécurisée
3 OS Hardening
La part de l’administrateur
Protections
Fonctionnalité du processeur
L’arrivée de l’architecture 64 bits par AMD a vu l’introduction d’un
nouveau bit, le bit « no execute » qui marque chaque page.
Chat et la souris
À cause des protections précédentes, il n’est plus possible d’exécuter
aussi facilement du code depuis le buffer en train d’être exploiter.
⇒ Car les pages ne sont pas exécutables.
Le jeu est maintenant d’exécuter des instructions « légitimes ». Réussir à
sauter dans les fonctions de la libc par exemple.
Stack overflow
Les variables sont réordonnancées pour éviter qu’un overflow puisse
déborder dans des pointeurs de données utilisés plus tard.
Off-by-one
Pour des raisons d’optimisation des accès mémoire, les variables sont
alignées en utilisant du padding.
Il y a désormais un peu de place entre deux variables si nécessaire.
GNU libc
Des vérifications supplémentaires sont désormais effectuées avant de
supprimer un chunk.
Toutes les méthodes classiques d’exploitations sont caduques.
Dans Microsoft Vista, toutes les adresses sont XORées avec un nombre
aléatoire.
Disclaimer
Chaque technique prise indépendamment est contournable, mais
l’utilisation de toutes ces techniques permet d’assurer un niveau de
sécurité suffisant.
⇒ Défense en profondeur
RBAC
Lors d’un appel système, le noyau vérifie que le processus en cours (qui
tourne sous un rôle donné) a l’autorisation d’effectuer l’opération.
C’est fini.