🩁 Narnia 0

🩁 Narnia 0

1 January 2023 Narnia challenges 0

🩁 Narnia

Pour se prémunir des attaques et se rendre compte de leurs enjeux, il est avant tout nécessaire de comprendre leur fonctionnement.

Etant toujours Ă  la recherche de nouveaux dĂ©fis Ă  rĂ©aliser, c’est KĂ©vin qui m’a proposĂ© de me pencher sur ce wargame.

C’est ainsi que je vous propose un guide comprĂ©hensif des challenges Narnia.

Narnia est un wargame disponible sur le site https://overthewire.com/ qui permet d’apprendre les bases de l’exploitation de bugs communs.

En effet, ces challenges permettent de se pencher sur les dangers d’une mauvaise gestion mĂ©moire dans les scripts et posent les bases des attaques de type Buffer OverFlow.

Le wargame se dĂ©coupe en 10 niveaux. Il faut progressivement obtenir les mots de passe des comptes narnia1, narnia2… jusqu’Ă  narnia9. 

Le but de ce guide n’est pas de vous donner la rĂ©ponse, mais plutĂŽt de vous y amener par la comprĂ©hension. Ainsi, il ne contient pas de flag ni de solutions.

Si vous souhaitez ĂȘtre prĂ©venus des nouveaux articles, vous pouvez demander Ă  ĂȘtre inscrit sur notre mailing list depuis la page contact! 

Table des MatiĂšres

Narnia0

DĂ©couverte

Le premier challenge se compose d’un script nommĂ© narnia0 et dont le code source est disponible dans le fichier /narnia/narnia0.c :

				
					#include 
#include 

int main(){
long val=0x41414141;
char buf[20];

printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\\n");
printf("Here is your chance: ");
scanf("%24s",&buf);

printf("buf: %s\\n",buf);
printf("val: 0x%08x\\n",val);

if(val==0xdeadbeef){
    setreuid(geteuid(),geteuid());
    system("/bin/sh");
}
else {
    printf("WAY OFF!!!!\\n");
    exit(1);
}

return 0;

				
			

En lisant le code source, on voit que la variable buf peut contenir 20 caractÚres (char). 

Pour rappel 1 char= 1 octet.

De plus, on nous dit clairement dans le premier printf, que, pour réussir le challenge, il faut que la valeur de la variable val soit égale à 0xdeadbeef.

 

Or, le seul input avec lequel on interagit, n’agit que sur la valeur de buf :

Heureusement pour nous, Ă  la ligne 10 du code source, l’input nous permet d’envoyer 24 caractĂšres Ă  l’intĂ©rieur de buf:

				
					//Lit les 24 premiers caractÚres et les stocke à l'adresse mémoire de buf
scanf("%24s",&buf);
				
			

GrĂące Ă  cette information, on comprend que le but du challenge est de faire un Buffer Overflow.

Qu’est-ce qu’un Buffer OverFlow ?

Il s’agit d’un dĂ©bordement du tampon. Je m’explique :

Lorsque l’on rĂ©dige un programme, les variables sont stockĂ©s dans l’ordre de dĂ©finition sur la pile.

 

Par exemple, je définis :

				
					char a = “Hello”;
int b = 45
				
			

Le programme stocke la valeur de a puis celle de b. Elles ne changeront plus de “place”, mĂȘme si leur valeur est modifiĂ©e.

A chaque variable est attribuée une adresse mémoire.

Les adresses mĂ©moires sont des chiffres hexadĂ©cimaux reprĂ©sentant l’emplacement Ă  laquelle notre variable est stockĂ©e, par exemple :

 

 

Chaque adresse ne pointe que sur une seule valeur.

Le nombre d’adresse disponible dĂ©pend de la taille de la mĂ©moire vive dont dispose votre ordinateur.

En fonction du type de la variable, plus ou moins d’espace mĂ©moire va ĂȘtre rĂ©servĂ©.

 

Quelques exemples de types de variables avec leur taille :

Ainsi, si j’essaye d’écrire dans une variable, une valeur plus grande que ce qu’elle peut recevoir, cela va “dĂ©passer” sur la variable suivante et modifier sa valeur :

C’est de cette maniùre que se produisent les Buffer OverFlow.

Exemple :

				
					#include 
#include 

int main (void){

// a est un type char qui peut accueillir 4 caractĂšres, donc 4 octets
char a[4];
// b est un type int de 2 octets
int b = 4;

printf("Entrez une nouvelle valeur pour a : ");
// le scanf permet de lire les premiers 5 caractĂšres saisis et les stock dans a
scanf("%5s\n", a);

//Afficher les nouvelles valeurs de a et b
printf("a : %s\n", a);
printf("b : %d\n",b);
}
				
			

Résultat du script : 

				
					Entrez une nouvelle valeur pour a : Salut65
a : Salut
b : 116
				
			

On voit que l’on peut modifier la valeur de b en “dĂ©bordant” de la valeur de a.

C’est cette mĂ©thode qu’il faudra exploiter pour rĂ©soudre le challenge.

⚠ Attention ! Pour que ce script fonctionne, il est nĂ©cessaire de baisser toutes les sĂ©curitĂ©s en compilant : gcc -fno-stack-protector exemple.c

N’hĂ©sitez pas Ă  reprendre ce script et Ă  vous amuser avec afin de vous familiariser avec ce concept !

RĂ©flexion

Ainsi, si vous avez compris les explications plus haut, vous vous dĂźtes sĂ»rement qu’il suffit de remplir le tampon avec n’importe quoi puis de mettre deadbeef afin que cela Ă©crive sur valde cette façon : 

Mais ce n’est pas si simple. Nous n’avons que 4 octets de libre (buf en prend 20/24), or la chaine de caractĂšre deadbeef fait 8 octets. La suite ne sera donc pas lu par le programme. En fait, il ne faut pas avoir la chaine de caractĂšre deadbeef, mais une chaine de caractĂšre dont la valeur hexadĂ©cimal est 0xdeadbeef!

C’est maintenant à vous de trouver une solution (sous forme de script ou directement en ligne de commande) pour afficher deadbeef sur 4 octets 😊.

Indice : Jetez un Ɠil à la table ASCII et à sa correspondance avec l’hexa 😉

Indice 2 : Tentez d’écrire 0xDEADBEEF en hexadĂ©cimal avec le langage de votre choix

Indice 3 : Si jamais vous utilisez Python3, il utilise par dĂ©faut l’encodage utf-8 et non l’ASCII…

Une fois que vous avez trouvĂ© une maniĂšre d’afficher deadbeef sur 4 octets et que la valeur de val est bien 0xdeadbeef, il ne vous reste plus qu’à trouver une solution pour que le /bin/sh ouvert par le programme narnia0, ne se referme pas.

Indice :cat – : redirige la sortie de la commande vers le terminal

Les mots de passe se trouvent toujours dans /etc/narnia_pass

Vous avez dĂ©sormais toutes les clĂ©s en main pour rĂ©ussir ce challenge, Ă  vous de jouer ! đŸ’Ș

Ressources