Il existe de nombreux risques de sécurité liés à un contact étroit avec le matériel, par opposition à l'utilisation d'API bien testées et éprouvées à partir de langages de programmation de haut niveau. Il est beaucoup plus facile de provoquer un débordement de tampon en C que dans un langage tel que Java.
Quels sont les risques ou vulnérabilités (par exemple, les dépassements de tampon) que chaque programmeur C devrait connaître (vulnérabilités IE pertinentes pour les programmeurs C)? À quels problèmes cela pourrait-il conduire? Comment les éviter et quelles sont les erreurs courantes qui provoquent ces erreurs dans les programmes?
Réponses:
Les débordements de tampon sont importants. Rien en C n'est vérifié par plage par défaut, il est donc très facile d'écraser un tampon. Il existe une fonction de bibliothèque standard
gets()
, qui ne peut pas être empêchée de déborder du tampon, et ne devrait presque jamais être utilisée.Il existe certaines techniques au niveau de l'implémentation pour entraver l'exploitation, telles que le brouillage des blocs de tas, mais cela n'arrêtera pas les débordements de tampon dans les tampons locaux, ce qui peut souvent faire des choses intéressantes comme changer l'adresse à laquelle une fonction retournera.
Il n'y a pas de bonne solution générale en C. De nombreuses fonctions de bibliothèque ont des versions qui limiteront la quantité à écrire. bien que le calcul puisse être maladroit. Il existe des logiciels qui peuvent détecter les débordements de tampon de tas dans le test, tant que le test approprié est exécuté, et le débordement de pile apparaîtra souvent comme un crash lors des tests. À part cela, c'est une question de codage et de révision du code.
Un problème connexe est le problème de l'écriture dans un tampon trop petit d'un caractère, oubliant qu'une chaîne C de n caractères nécessite n + 1 caractères en mémoire, à cause du
'\0'
terminateur. Si l'attaquant parvient à stocker une chaîne sans le terminateur, toute fonction C s'attendant à ce qu'une chaîne continue son traitement jusqu'à ce qu'elle atteigne un octet zéro, ce qui pourrait entraîner la copie ou la sortie de plus d'informations que souhaité (ou la suppression de la mémoire protégée pour une attaque DOS ). La solution, encore une fois, est la sensibilisation, le soin et les revues de code.Il y a un autre risque avec la
printf()
famille. Si vous écrivezchar * str; ... printf(str);
, vous vous installez pour des problèmes sistr
contient un «%» lors de l'impression. La%n
directive format permetprintf()
d'écrire en mémoire. La solution estprintf("%s", str);
ouputs(str);
. (Utilisez également le C99snprintf()
au lieu desprintf()
.)L'utilisation d'entiers non signés, en particulier comme index de boucle, peut entraîner des problèmes. Si vous attribuez une petite valeur négative à un non signé, vous obtenez une grande valeur positive. Cela peut compromettre des choses comme le traitement uniquement de N instances de quelque chose, ou dans des fonctions limitées comme
strncpy()
. Examinez tous les entiers non signés. Vous voudrez peut-être éviterunsigned short
, car une grande valeur dans l'un d'eux se convertira en une grande valeur positive dans unint
.N'oubliez pas qu'une constante de caractère, en C, est en fait un
int
. Écrire quelque chose commechar c; while((c = getchar()) != EOF) ...
peut facilement échouer, carEOF
il ne sera pas représentable dans un fichierchar
.Il y a beaucoup plus d'erreurs C caractéristiques auxquelles je peux penser, mais cela pourrait causer des problèmes de sécurité.
la source
printf("%s", str)
pour une chaîne nue quandputs(str)
fera le même travail.puts
ajoute un caractère de nouvelle ligne alorsprintf
que non.fputs(str, stdout)
, ce qui n'est pas le cas.Certains des risques spécifiques à C incluent: les débordements de tampon , les attaques de formatage de chaînes et les débordements d'entiers .
la source
Voici un risque facile à manquer qui peut causer des problèmes dont la résolution prendra des heures.
Considérez le code suivant, qui se compilera sans problème.
Lorsque vous vérifiez pour voir si
lpstr_current_state
est en fait,CONST_EMERGENCY_STATE_HOLY_CRAP
vous attribuez. Il est préférable de toujours mettre la variable constante à gauche. Lorsque vous placez la constante à gauche, le compilateur échoue car vous ne pouvez pas attribuer de valeur à une variable.Ensuite, vous pouvez facilement vous dire: "Putain de merde, ça aurait pu être mauvais", tout en fixant le code à lire ...
la source
=
et==
.Il n'y a qu'un seul risque de sécurité: le fait qu'il y ait des gens à l'extérieur qui feront de leur mieux pour détecter toute vulnérabilité dans votre logiciel et l'exploiter à leur propre avantage. Tout le reste en découle.
Donc, quand vous pensez que "personne dans son bon sens ne le ferait ...", alors vous devez penser immédiatement "sauf que quelqu'un qui veut pirater les ordinateurs des autres ferait exactement cela".
La plus grande conséquence est que chaque fois que vous réagissez à des événements extérieurs (par exemple, en traitant des données transmises de l'extérieur), vous devez supposer que ces données étaient sous le contrôle de votre pire ennemi.
la source