La fonction strcpy est-elle toujours dangereuse?

Les fonctions telles que strcpy, gets, etc. sont-elles toujours dangereuses? Et si j’écris un code comme celui-ci:

int main(void) { char *str1 = "abcdefghijklmnop"; char *str2 = malloc(100); strcpy(str2, str1); } 

De cette façon, la fonction n’accepte pas les arguments (parameters …) et la variable str aura toujours la même longueur … ce qui est ici 16 ou légèrement plus selon la version du compilateur … mais ouais 100 suffira à partir de mars 2011 :). Existe-t-il un moyen pour un pirate informatique de tirer parti du code ci-dessus? 10x!

Absolument pas. Contrairement à la campagne marketing de Microsoft pour ses fonctions non standard, strcpy est sûr s’il est utilisé correctement .

Ce qui précède est redondant, mais surtout sans danger. Le seul problème potentiel est que vous ne vérifiez pas la valeur de retour malloc , vous pouvez donc déréférencer la valeur null (comme l’a souligné kotlinski). En pratique, cela risque d’entraîner un arrêt immédiat du programme SIGSEGV.

Une utilisation inappropriée et dangereuse serait:

 char array[100]; // ... Read line into uncheckedInput // Extract subssortingng without checking length strcpy(array, uncheckedInput + 10); 

Ceci est dangereux car le strcpy peut déborder, causant un comportement indéfini. En pratique, cela risque d’écraser d’autres variables locales (ce qui constitue une faille de sécurité majeure). L’un d’entre eux peut être l’adresse de retour. Lors d’une attaque par le retour à la bibliothèque C , l’attaquant peut utiliser des fonctions C comme system pour exécuter des programmes arbitraires. Les débordements peuvent avoir d’autres conséquences.

Cependant, gets est insortingnsèquement dangereux et sera supprimé de la prochaine version de C (C1X). Il n’y a simplement aucun moyen de s’assurer que l’entrée ne débordera pas (causant les mêmes conséquences que ci-dessus). Certaines personnes diront qu’il est sûr d’utiliser un fichier d’entrée connu, mais il n’y a vraiment aucune raison de l’utiliser. Le getline de POSIX est une alternative bien meilleure.

En outre, la longueur de str1 ne varie pas en fonction du compilateur. Il devrait toujours être 17, y compris le NUL final.

oui, c’est dangereux. Après 5 ans de maintenance, votre code ressemblera à ceci: int main (void) {

char * str1 = “abcdefghijklmnop”;

{assez de lignes ont été insérées ici pour ne pas avoir str1 et str2 sympa et proches l’une de l’autre sur l’écran}

char * str2 = malloc (100); strcpy (str2, str1);

}

à ce moment-là, quelqu’un ira changer de str1 en

str1 = “CECI EST UNE TRES LONGUE CHAÎNE QUI SUPPRIMERA MAINTENANT TOUT MOYEN UTILISÉ POUR LE COPIER AU MOINS QUE DES PRÉCAUTIONS SOIENT PRISES POUR CONTRÔLER LES LIMITES DE LA CHAÎNE. PROGRAMME BUGGY ”

et oubliez de regarder où str1 est utilisé et les erreurs aléatoires commenceront à se produire …

Vous regroupez avec force des choses complètement différentes dans une catégorie.

Fonctions gets est en effet toujours dangereux. Il n’existe aucun moyen de s’appeler en toute sécurité, quelles que soient les mesures que vous êtes prêt à prendre et le niveau de défense que vous êtes prêt à prendre.

La fonction strcpy est parfaitement sûre si vous êtes prêt à prendre les mesures [simples] nécessaires pour vous assurer que vos appels vers strcpy sont protégés.

Cela strcpy déjà des strcpy et des strcpy dans des catégories très différentes, qui n’ont rien de commun en matière de sécurité.

Les critiques populaires concernant les aspects de sécurité de la strcpy reposent entièrement sur des observations sociales anecdotiques, par opposition aux faits formels, par exemple, “les programmeurs sont paresseux et incompétents, alors ne les laissez pas utiliser la strcpy “. Pris dans le contexte de la programmation C, cela est, bien sûr, un non-sens. En suivant cette logique, nous devrions également déclarer l’opérateur de division exactement comme non sécurisé pour exactement les mêmes raisons.

En réalité, la strcpy ne pose aucun problème. gets , en revanche, est une histoire complètement différente, comme je l’ai dit ci-dessus.

strcpy n’est pas dangereux pour autant que vous sachiez que le tampon de destination est suffisamment grand pour contenir les caractères de la chaîne source; sinon, strcpy volontiers plus de caractères que le tampon cible ne peut en contenir, ce qui peut avoir plusieurs conséquences fâcheuses (écrasement de stack / autres variables pouvant entraîner des plantages, des attaques de stack superflues, etc.).

Mais si vous avez un caractère générique char * dans l’entrée qui n’a pas encore été vérifié, le seul moyen de vous en assurer est d’appliquer strlen à cette chaîne et de vérifier si elle est trop grande pour votre mémoire tampon; Cependant, vous devez maintenant parcourir la chaîne source complète deux fois, une fois pour en vérifier la longueur, une fois pour effectuer la copie.

Ceci est sous-optimal, car si strcpy était un peu plus avancé, elle pourrait recevoir en paramètre la taille du tampon et arrêter la copie si la chaîne source était trop longue; dans un monde parfait, strncpy comment strncpy se comporterait (en suivant le modèle des autres fonctions de strn*** ). Cependant, ce n’est pas un monde parfait, et strncpy n’est pas conçu pour cela. Au lieu de cela, l’alternative non standard (mais populaire) est strlcpy , qui, au lieu de sortir des limites du tampon cible, tronque.

Plusieurs implémentations de tube cathodique ne fournissent pas cette fonction (notamment glibc), mais vous pouvez toujours obtenir l’une des implémentations de BSD et la placer dans votre application. Une alternative standard (mais plus lente) peut être d’utiliser snprintf avec "%s" comme chaîne de formatage.

Cela dit, puisque vous programmez en C ++ ( edit je vois maintenant que la balise C ++ a été supprimée), pourquoi ne pas simplement éviter toutes les absurdités de la chaîne C (lorsque vous le pouvez, évidemment) et std::ssortingng avec std::ssortingng ? Tous ces problèmes de sécurité potentiels disparaissent et les opérations sur les chaînes deviennent beaucoup plus faciles.

La seule façon dont Malloc peut échouer est lorsqu’une erreur d’insuffisance de mémoire se produit, ce qui est un désastre en soi. Vous ne pouvez pas le récupérer de manière fiable car pratiquement tout peut le déclencher à nouveau et le système d’exploitation est susceptible de tuer votre processus de toute façon.

Votre code n’est pas sécurisé. La valeur de retour de malloc est décochée. Si elle échoue et renvoie 0, la strcpy donnera un comportement indéfini.

En dehors de cela, je ne vois aucun problème autre que le fait que l’exemple ne fait fondamentalement rien.

Comme vous l’avez fait remarquer, dans des circonstances contraignantes, la stratégie n’est pas dangereuse. Il est plus courant de prendre un paramètre de chaîne et de le copier dans un tampon local, c’est-à-dire lorsque les choses peuvent devenir dangereuses et conduire à un dépassement de tampon. Rappelez-vous simplement de vérifier la longueur de vos copies avant d’appeler strcpy et de mettre fin à la chaîne après.

Mis à part le potentiel de déréférencement NULL (car vous ne vérifiez pas le résultat de malloc), qui correspond à UB et ne constitue probablement pas une menace pour la sécurité, cela ne présente aucun problème de sécurité potentiel.

gets() est toujours dangereux ; les autres fonctions peuvent être utilisées en toute sécurité.
gets() est dangereux même lorsque vous avez le contrôle total sur l’entrée – un jour, le programme peut être exécuté par quelqu’un d’autre.

Le seul moyen sûr d’utiliser gets() est de l’utiliser pour une seule opération: créer le source; comstackr; courir; supprimer le binary et le source; interpréter les résultats.