web-dev-qa-db-fra.com

Pourquoi strncpy n'est pas sécurisé?

Je cherche à savoir pourquoi strncpy est considéré comme non sécurisé. Quelqu'un at-il une sorte de documentation à ce sujet ou des exemples d'exploits l'utilisant?

64
stimms

Jetez un oeil à ce site ; c'est une explication assez détaillée. Fondamentalement, strncpy() ne nécessite pas de terminaison NUL et est donc sensible à une variété d'exploits.

39
Tim

Le problème d'origine est évidemment que strcpy (3) n'était pas un opération sans danger pour la mémoire , donc un attaquant pourrait fournir une chaîne plus longue que le tampon qui écraserait le code sur la pile , et s'il est soigneusement organisé, pourrait exécuter du code arbitraire de l'attaquant.

Mais strncpy (3) a un autre problème en ce qu'il ne fournit pas de terminaison nulle dans tous les cas à la destination. (Imaginez une chaîne source plus longue que le tampon de destination.) Les opérations futures peuvent s'attendre à des chaînes terminées en C nul conformes entre des tampons de taille égale et un dysfonctionnement en aval lorsque le résultat est copié dans un troisième tampon.

L'utilisation de strncpy (3) est meilleure que strcpy (3) mais des choses comme strlcpy (3) sont encore meilleures.

12
DigitalRoss

Pour utiliser en toute sécurité strncpy, il faut soit (1) coller manuellement un caractère nul sur le tampon de résultat, (2) savoir que le tampon se termine par un nul au préalable, et passer (longueur-1) à strncpy, ou (3) savoir que le tampon ne sera jamais copié en utilisant une méthode qui ne liera pas sa longueur à la longueur du tampon.

Il est important de noter que strncpy remplira tout le contenu du tampon au-delà de la chaîne copiée, contrairement aux autres variantes de strcpy à longueur limitée. Dans certains cas, cela peut être une perte de performances, mais dans d'autres cas, cela peut être un avantage en termes de sécurité. Par exemple, si l'on utilise strlcpy pour copier "supercalifragilisticexpalidocious" dans un tampon puis pour copier "it", le tampon contiendra "it ^ ercalifragilisticexpalidocious ^" (en utilisant "^" pour représenter un octet zéro). Si le tampon est copié dans un format de taille fixe, les données supplémentaires peuvent être marquées avec lui.

7
supercat

La question est basée sur une prémisse "chargée", ce qui rend la question elle-même invalide.

L'essentiel ici est que strncpy n'est pas considéré comme non sécurisé et n'a jamais été considéré comme non sécurisé. Les seules revendications d '"insécurité" qui peuvent être attachées à cette fonction sont les revendications générales d'insécurité générale du modèle de mémoire C et du langage C lui-même. (Mais c'est évidemment un sujet complètement différent).

Dans le domaine du langage C, la croyance erronée d'une sorte d '"insécurité" inhérente à strncpy est dérivée du modèle douteux répandu d'utiliser strncpy pour la "copie sécurisée de chaînes", c'est-à-dire quelque chose de cette fonction ne fait pas et n'a jamais été destiné. Une telle utilisation est en effet très sujette aux erreurs. Mais même si vous mettez un signe d'égalité entre "très sujet aux erreurs" et "non sécurisé", c'est toujours un problème d'utilisation (c'est-à-dire un problème de manque d'éducation) pas un problème strncpy.

Fondamentalement, on peut dire que le seul problème avec strncpy est une dénomination malheureuse, ce qui fait que les programmeurs débutants supposent qu'ils comprennent ce que fait cette fonction au lieu de lire réellement la spécification. En regardant le nom de la fonction, un programmeur incompétent suppose que strncpy est une "version sûre" de strcpy, alors qu'en réalité ces deux fonctions sont complètement indépendantes.

Exactement la même réclamation peut être faite contre l'opérateur de division, par exemple. Comme la plupart d'entre vous le savent, l'une des questions les plus fréquemment posées au sujet du langage C est: "Je supposais que 1/2 sera évalué à 0.5 mais j'ai eu 0 au lieu. Pourquoi? "Pourtant, nous ne prétendons pas que l'opérateur de division n'est pas sûr juste parce que les débutants en langage ont tendance à mal interpréter son comportement.

Pour un autre exemple, nous n'appelons pas les fonctions de générateur de nombres pseudo-aléatoires "peu sûres" simplement parce que les programmeurs incompétents sont souvent désagréablement surpris par le fait que leur sortie n'est pas vraiment aléatoire.

C'est exactement comme ça avec la fonction strncpy. Tout comme il faut du temps aux programmeurs débutants pour apprendre ce que font réellement les générateurs de nombres pseudo-aléatoires, cela leur prend du temps pour apprendre ce que strncpy fait réellement. Il faut du temps pour apprendre que strncpy est une fonction conversion, destinée à convertir terminaison zéro chaînes en largeur fixe chaînes . Il faut du temps pour apprendre que strncpy n'a absolument rien à voir avec la "copie sécurisée de chaînes" et ne peut pas être utilisé de manière significative à cette fin.

Certes, il faut généralement beaucoup plus de temps pour qu'un étudiant en langue apprenne le but de strncpy que de trier les choses avec l'opérateur de la division. Cependant, c'est une base pour toute réclamation "d'insécurité" contre strncpy.

P.S. Le document CERT lié dans la réponse acceptée est dédié précisément à cela: démontrer les insécurités de l'abus incompétent typique de la fonction strncpy en tant que version "sûre" de strcpy. Il n'est nullement destiné à prétendre que strncpy lui-même est en quelque sorte peu sûr.

3
AnT

Un pathc de Git 2.19 (Q3 2018) trouve qu'il est trop facile de mal utiliser les fonctions API système telles que strcat(); strncpy(); ... et interdit ces fonctions dans cette base de code.

Voir commit e488b7a , commit cc8fdae , commit 1b11b64 (24 juil 2018), et commit c8af66a (26 juil 2018 ) par Jeff King (peff) .
(Fusionné par Junio ​​C Hamano - gitster - in commit e28daf2 , 15 août 2018)

banned.h: Marquez strcat() comme interdit

La fonction strcat() a tous les mêmes problèmes de débordement que strcpy().
Et en prime, il est facile de se retrouver accidentellement quadratique, car chaque appel ultérieur doit parcourir la chaîne existante.

Le dernier appel de strcat() a disparu dans f063d38 (démon: utilisez cld-> env_array lors de la réapparition, 2015-09-24, Git 2.7.0).
En général, strcat() peut être remplacée soit par une chaîne dynamique (strbuf ou xstrfmt), soit par xsnprintf si vous connaissez la longueur est limitée.

1
VonC