SizeofPtr -- Utilisation de sizeof() sur un type pointeur

De RAD Studio
Aller à : navigation, rechercher

Remonter à Audits C++

Description

SizeofPtr signale l'usage imprévu de sizeof() sur des expressions de pointeurs.

Le code appelle sizeof() sur un type pointeur alloué via malloc, qui renvoie toujours wordsize/8. Cela peut produire un résultat inattendu si le programmeur a l'intention de déterminer la quantité de mémoire allouée.

Exemple 1

Un soin particulier doit être pris afin de garantir que sizeof renvoie la taille de la structure de données elle-même, et pas la taille du pointeur sur la structure de données.

Dans cet exemple, sizeof(foo) renvoie la taille du pointeur.

 double *foo;
 ...
 foo = (double *)malloc(sizeof(foo));

Dans cet exemple, sizeof(*foo) renvoie la taille de la structure de données, et pas la taille du pointeur.

 double *foo;
 ...
 foo = (double *)malloc(sizeof(*foo));
Exemple 2

Cet exemple définit un nom d'utilisateur fixe et un mot de passe. La fonction AuthenticateUser() a été conçue pour accepter un nom d'utilisateur et un mot de passe de la part d'un utilisateur non fiable, et vérifie la correspondance du nom d'utilisateur et du mot de passe. Si le nom d'utilisateur et le mot de passe correspondent, AuthenticateUser() a été conçue pour indiquer que l'authentification a réussi.

 char *username = "admin";
 char *pass = "password";

 int AuthenticateUser(char *inUser, char *inPass) {
   printf("Sizeof username = %d\n", sizeof(username));
   printf("Sizeof pass = %d\n", sizeof(pass));

   if (strncmp(username, inUser, sizeof(username))) {
     printf("Auth failure of username using sizeof\n");
     return(AUTH_FAIL);
   }
   /* sizeof returns 4 on many platforms and architectures. */
   if (! strncmp(pass, inPass, sizeof(pass))) {
     printf("Auth success of password using sizeof\n");
     return(AUTH_SUCCESS);
   }
   else {
     printf("Auth fail of password using sizeof\n");
     return(AUTH_FAIL);
   }
 }

 int main (int argc, char **argv)
 {
   int authResult;

   if (argc < 3) {
     ExitError("Usage: Provide a username and password");
   }
   authResult = AuthenticateUser(argv[1], argv[2]);
   if (authResult != AUTH_SUCCESS) {
     ExitError("Authentication failed");
   }
   else {
     DoAuthenticatedTask(argv[1]);
   }
 }

Dans AuthenticateUser(), puisque sizeof() est appliquée à un paramètre avec un type tableau, l'appel à sizeof() pourrait renvoyer 4 sur de nombreuses architectures modernes. En résultat, l'appel à strncmp() vérifie seulement les quatre premiers caractères du mot de passe d'entrée, résultant en une comparaison partielle, conduisant une authentification erronée.

En raison de la comparaison partielle, ces mots de passe provoqueront toujours la réussite de l'authentification pour l'utilisateur "admin" :

pass5
passABCDEFGH
passWORD

Puisque seuls quatre caractères sont vérifiés, cela réduit de manière significative l'espace de recherche pour un attaquant, rendant les attaques en force brute plus faisables.

Le même problème s'applique aussi au nom d'utilisateur. Ainsi, des valeurs telles que adminXYZ et administrator réussiront pour le nom d'utilisateur.


Voir aussi