2017-06-30 4 views
-3

J'ai effectué une recherche en ligne pendant quelques heures, mais je n'arrive toujours pas à déterminer quelle est la vulnérabilité pour le code ci-dessous. Je dois produire un buffer overflow mais je ne peux pas faire ça. Si j'ai une charge utile supérieure à 28, j'entre dans l'instruction if et retourne false avant que la fonction fread ne soit exécutée dans la ligne 5.Buffer Overflow C

Quelqu'un peut-il me dire comment je peux contourner cette vérification pour déclencher le débordement?

package looks like this 
+------------+------------+------------+ 
|tag = 1 byte|len = 1 byte|payload[len]| 
+------------+------------+------------+ 
0. bool processNextPackage(void){ 
1. char buf[32]; 
2. if(!fread(buf, 2, 1, stdin){ 
3.  return false; 
4. } 
5. if(buf[1] > sizeof(buf)-3 || !fread(buf + 2, buf[1], 1, stdin)){ 
6.  return false; 
7. } 
8. buf[sizeof(buf) - 1] = '\0' 
9. return false; 
10.} 
+0

pas sûr qu'il s'agit d'une vulnérabilité, mais en passant une valeur> 0x7F rend 'buf [1]' négatif. –

+0

@ Jean-FrançoisFabre Oui, 'char' est un type signé. – NieDzejkob

+0

@NieDzejkob dans la plupart des systèmes oui par défaut. Oh, je pense que c'est le problème. –

Répondre

1

Supposons que char est signed char ici (ce qui est le plus courant, mais pas tous les compilateurs faire)

La seule vulnérabilité possible serait d'essayer de passer une plus grande longueur que la longueur maximale autorisée. Ici, nous avons un octet pour le faire.

Cette condition est celle qui pourrait être attaqué:

if(buf[1] > sizeof(buf)-3 || !fread(buf + 2, buf[1], 1, stdin)) 

l'opérateur court-circuit empêche d'entrer dans fread (et lu trop d'octets du fichier) si buf[1] est trop grand.

Mais si la valeur est à portée 0x80 .. 0xff, qui fait buf[1] négative en raison de (probablement) ont signé char. Ce serait inattendu. MAIS il ne réussit toujours pas le test parce que la comparaison négative à non signé sizeof(buf)-3 rend toujours la valeur négative la plus grande.

À côté: buf[sizeof(buf) - 1] = '\0': On dirait que nous sommes nul terminant la chaîne pour printf fins d'affichage. Si le tampon est trop grand, cela n'est pas fait (parce que nous revenons plus tôt), et le code pourrait planter lors de l'impression d'une chaîne non terminée. Donc le tampon devrait être mis à tous les zéros avant de lire.

Mais à part ça, le code n'a aucune vulnérabilité je peux voir.

Cependant, si il a été écrit comme ceci:

int sz = sizeof(buf)-3; 
if(buf[1] > sz || !fread(buf + 2, buf[1], 1, stdin)) 

il y aurait une vulnérabilité puisque la comparaison négative signée passerait à fread, et quand fread est appelée, une valeur négative est passée comme size , mais non signé fread s'attend:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 

il aurait été possible que la valeur est convertie en posit ive (et trop grande) valeur: mettre 0xFF dans buf[1], il devient -1 comme char signé, mais passé à fread il devient une valeur positive, plus grande que la mémoire tampon. Donc, comme la valeur est très grande, il lira tous les octets du fichier: vous pouvez y injecter un code malveillant.

Donc, pour être sûr que le code Noone réécrit cette façon:

  • utilisation unsigned char pour la variable buf pour éviter les effets de comparaison de nombre entier non signé entier/étrange.
  • Initialiser le tampon à tous les zéros pour éviter le blocage lors de l'utilisation de printf sur un tampon non terminé.
+0

Pour que votre réponse ait un sens, vous devez répondre au fait que 'char' a une signature définie par l'implémentation. Il n'y a rien qui empêche un compilateur de rendre le type 'char' par défaut non signé. Il n'est pas évident que '0x80' etc aura pour résultat des valeurs négatives. – Lundin

+0

@Jet merci d'avoir accepté. Comme je n'ai pas trouvé de véritable vulnérabilité (je pense avoir démontré mon point de vue), êtes-vous sûr qu'il y en a un dans ce code? –