dimanche 9 mars 2008

Les erreurs de codages avec str*cpy et str*cat

Dans cet article je vais vous parlez des erreurs de codage fréquemment rencontrés avec les fonctions str*cpy et str*cat, ces erreurs sont généralement dû à une mauvaise utilisation des fonctions en question et amènent à un stack overflow.

Tout le monde sait que la meilleure façon de faire un stack overflow, c'est d'utilisé strcpy() ou strcat() car elle ne vérifie pas la longueur des variables et écrivent sans aucun remord dans des zones ne leur appartenant pas généralement une sauvegarde de ebp et eip mais si ils continuent ils peuvent écraser encore plus de données. C'est généralement l'écrasement de eip qui conduit à une redirection des instructions vers un shellcode seulement un écrasement de ebp est tout aussi dangereux.

Les programmeurs pour éviter les stack overflow utilisent donc leur équivalent un peu plus sécurisé ( pas entièrement sinon c'est pas marrant ) strncpy() et strncat() en leur passant en troisième paramètre la taille du buffer.
Cependant les deux fonctions n'ont pas le même comportement, dans la page de man de strncpy() on nous dit que le \0 final n'est pas compter et il faut donc en tenir compte alors que dans la page de man de strncat() on nous dis que le \0 final est rajouter par la fonction elle même.
Cette différence entraine généralement des erreurs de codage.

strncpy(dest, src, sizeof(dest)-1);

au lieu de
strncpy(dest, src, sizeof(dest)-1);
dest[sizeof(dest)-1] = 0;


En général, le stack overflow ne vient pas de cette ligne mais d'un éventuel str*cat() qui suit, imaginez ce code:

strncpy(dest, src, sizeof(dest)-1);
strncat(dest, src2, sizeof(dest)-strlen(dest)-1);


Ici strncat est bien utilisé mais le strncpy() va provoquer deux choses d'abord un integer overflow et après un buffer overflow.

strncat à la prototype suivant char * strncat ( char * destination, char * source, size_t num );

Ici l'absence de \0 dans dest à la fin du strncpy va faire que strlen(dest) va être beaucoup plus grand que sizeof(dest) et donc que le résultat sera négatif or la fonction accepte un size_t qui est unsigned donc cela fera un nombre extrêmement grand d'où le possible overflow.

Ensuite il faut savoir que strncat met un \0 à la fin de la chaine de destination à tout les coups donc cet appel provoquera un overflow ( en supposant qu'il y ai bien un \0 dans dest pour ne pas revenir dans le même cas que précédemment ) :

strncat(dest, src, sizeof(dest)-strlen(dest));


Ici la fonction strncat va bien copier sizeof(dest)-strlen(dest) et le buffer sera rempli mais la fonction va rajouter un \0 et provoquer un overflow qui va écraser le premier octet de la sauvegarde de ebp.

Aucun commentaire: