Qu'est-ce qu'un débordement de tampon et comment en causer un?
j'ai entendu parler d'un débordement de tampon et j'aimerais savoir comment en causer un.
Quelqu'un peut-il me montrer un petit exemple de débordement de tampon? Nouvelle(Et ce qu'ils sont utilisés pour?)
11 réponses
un dépassement de mémoire tampon est essentiellement quand une section (ou mémoire tampon) de mémoire est écrite en dehors de ses limites prévues. Si un attaquant peut réussir à faire cela se produire à partir de l'extérieur d'un programme, il peut causer des problèmes de sécurité car il pourrait potentiellement leur permettre de manipuler des emplacements de mémoire arbitraires, bien que de nombreux systèmes d'exploitation modernes protègent contre les pires cas de cela.
tandis que la lecture et l'écriture en dehors des limites prévues sont généralement considérées comme une mauvaise idea, le terme "buffer overflow" est généralement réservé à rédaction en dehors des limites, car cela peut permettre à un attaquant de modifier facilement le moyen de votre code s'exécute. Il y a un bon article sur Wikipedia sur dépassement de tampon et les différentes façons dont ils peuvent être utilisés pour les exploits.
En termes de la façon dont vous pouvez programmer vous-même, ce serait une simple question de:
char a[4];
strcpy(a,"a string longer than 4 characters"); // write past end of buffer (buffer overflow)
printf("%s\n",a[6]); // read past end of buffer (also not a good idea)
si cela se compile et ce qui se passe quand il fonctionne serait probablement dépendent de votre système d'exploitation et le compilateur.
exemple classique de dépassement de tampon:
// noone will ever have the time to type more than 64 characters...
char buf[64];
gets(buf); // let user put his name
le débordement de tampon seul ne se produit le plus souvent pas intentionnellement. Cela se produit le plus souvent à cause d'une erreur dite "d'un seul coup". Ce qui signifie que vous avez mal calculé la taille du tableau par un - peut-être parce que vous avez oublié de tenir compte d'un caractère terminus null, ou parce que d'autres choses.
mais il peut aussi être utilisé pour des trucs diaboliques. En effet, l'utilisateur connaissait ce trou depuis longtemps, et puis les inserts disent 70 caractères, avec les derniers contenant quelques bytes spéciaux qui écrasent certains stack-slot - si l'utilisateur est vraiment délicat il/elle va frapper la fente d'adresse de retour dans la pile, et l'écrira de sorte qu'il saute en avant dans ce tampon juste inséré: parce que ce que l'Utilisateur a entré n'était pas son nom, mais son shell-code qu'il a précédemment compilé et jeté. Que l'on va alors juste l'exécuter. Il y a quelques problèmes. Par exemple, vous devez prendre des dispositions pour ne pas avoir de "\n " dans ce code binaire (parce que gets arrêter de lire là). Pour les autres méthodes qui perturbent des fonctions de chaîne dangereuses, le zéro binaire est problématique parce que les fonctions de chaîne cessent d'y Copier vers le buffer. Les gens ont utilisé xor
avec deux fois la même valeur pour produire un zéro aussi, sans écrire explicitement un octet zéro.
C'est la façon classique de faire. Mais il y a des blocs de sécurité qui peuvent dire que de telles choses se sont passées et d'autres choses qui rendent la pile non exécutable. Mais je pense qu'il y a moyen meilleurs trucs que je viens de vous expliquer. Un type de l'assembleur pourrait probablement maintenant vous raconter de longues histoires à ce sujet:)
Comment éviter
Toujours utilisez des fonctions qui prennent un argument de longueur maximale aussi, si vous n'êtes pas 100% bien sûr qu'un tampon est vraiment assez grande. Ne jouez pas à des jeux comme "oh, le nombre ne dépassera pas 5 caractères" - il échouera un jour. Rappelez-vous qu'une fusée où les scientifiques ont dit que le nombre ne dépassera pas certains ampleur, parce que la fusée ne serait jamais aussi vite. Mais un jour, il en fait plus rapide, et ce qui en a résulté a été un débordement d'entier et la fusée s'est écrasée (il s'agit d'un bug dans Ariane 5, un des bugs informatiques les plus chers de l'histoire).
Par exemple, au lieu de obtient utilisation fgets
. Et au lieu de sprintf
utiliser snprintf
là où c'est approprié et disponible (ou juste les choses du style C++ comme istream et autres choses)
dans le système d'exploitation linux moderne, vous ne pouvez pas exploiter le débordement de mémoire tampon sans une expérience supplémentaire. pourquoi ? parce que vous allez être bloqué par ASLR (randomisation de la couche adresse Stack) et pile protecteur dans ce compilateur GNU C moderne. vous ne localiserez pas la mémoire facilement parce que la mémoire tombera dans la mémoire aléatoire causée par ASLR. et vous serez bloqué par pile protecteur si vous essayez de déborder le programme.
Pour le début vous devez mettre de ASLR pour être 0 la valeur par défaut est 2
root@bt:~# cat /proc/sys/kernel/randomize_va_space
2
root@bt:~# echo 0 > /proc/sys/kernel/randomize_va_space
root@bt:~# cat /proc/sys/kernel/randomize_va_space
0
root@bt:~#
dans ce cas, il ne s'agit pas d'un ancien tutoriel de débordement de tampon que vous avez pu obtenir sur internet. ou aleph one tutoriel ne fonctionne plus dans votre système maintenant.
permet maintenant de créer une vulnérabilité de programme au scénario de débordement de tampon
---------------------bof.c--------------------------
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char buffer[400];
strcpy(buffer, argv[1]);
return 0;
}
---------------------EOF-----------------------------
regarde la fonction strcpy est dangereuse sans le protecteur de pile, parce que la fonction sans vérifier combien d'octets nous allons entrer. compiler avec option supplémentaire -fno-stack-protector dan -mpreferred-pile-limite=2 pour le protecteur de pile de décollage dans votre programme C
root@bt:~# gcc -g -o bof -fno-stack-protector -mpreferred-stack-boundary=2 bof.c
root@bt:~# chown root:root bof
root@bt:~# chmod 4755 bof
dépassement de la mémoire tampon C programme SUID root accès scenatio maintenant, nous avons le faire. maintenant permet de rechercher combien d'octets nous avons besoin de mettre en mémoire tampon à fait un programme segmentation fault
root@bt:~# ./bof `perl -e 'print "A" x 400'`
root@bt:~# ./bof `perl -e 'print "A" x 403'`
root@bt:~# ./bof `perl -e 'print "A" x 404'`
Segmentation fault
root@bt:~#
vous voyez que nous avons besoin de 404 octets pour faire défaut de segmentation de programme (plantage) maintenant combien d'octets nous avons besoin d'écraser EIP ? EIP is instruction sera exécuté après. donc hacker faire remplacer EIP pour le mal instruction de ce qu'ils veulent dans le binaire SUID sur le programme. si le programme se trouve dans la racine SUID, L'instruction sera exécutée dans la racine access.
root@bt:~# gdb -q bof
(gdb) list
1 #include <stdio.h>
2 #include <string.h>
3
4 int main(int argc, char** argv)
5 {
6 char buffer[400];
7 strcpy(buffer, argv[1]);
8
9 return 0;
10 }
(gdb) run `perl -e 'print "A" x 404'`
Starting program: /root/bof `perl -e 'print "A" x 404'`
Program received signal SIGSEGV, Segmentation fault.
0xb7e86606 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) run `perl -e 'print "A" x 405'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 405'`
Program received signal SIGSEGV, Segmentation fault.
0xb7e800a9 in ?? () from /lib/tls/i686/cmov/libc.so.6
(gdb)
le programme a obtenu le code de retour d'erreur de segmentation. entrons plus d'octets et prenons voir le registre EIP.
(gdb) run `perl -e 'print "A" x 406'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 406'`
Program received signal SIGSEGV, Segmentation fault.
0xb7004141 in ?? ()
(gdb)
(gdb) run `perl -e 'print "A" x 407'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 407'`
Program received signal SIGSEGV, Segmentation fault.
0x00414141 in ?? ()
(gdb)
un peu plus
(gdb) run `perl -e 'print "A" x 408'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 408'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)
(gdb) i r
eax 0x0 0
ecx 0xbffff0b7 -1073745737
edx 0x199 409
ebx 0xb7fc9ff4 -1208180748
esp 0xbffff250 0xbffff250
ebp 0x41414141 0x41414141
esi 0x8048400 134513664
edi 0x8048310 134513424
eip 0x41414141 0x41414141 <-- overwriten !!
eflags 0x210246 [ PF ZF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
maintenant, vous pouvez faire votre prochaine étape...
Un dépassement de la mémoire tampon est juste écrit-delà de la fin de la mémoire tampon:
int main(int argc, const char* argv[])
{
char buf[10];
memset(buf, 0, 11);
return 0;
}
en plus de ce qui a déjà été dit, Gardez à l'esprit que votre programme peut ou non "planter" lorsqu'un débordement de tampon se produit. devrait crash, et vous devriez l'espoir - mais si le dépassement de la mémoire tampon "déborde" dans une autre adresse que votre demande a également affectée à votre application peut sembler fonctionner normalement pour une période de temps plus longue.
si vous utilisez une édition ultérieure de Microsoft Visual Studio - je suggère d'utiliser le nouveau secure les contreparties dans le stdlib, comme sprintf_s insted de sprintf, ect...
Cela devrait être assez pour reproduire:
void buffer_overflow()
{
char * foo = "foo";
char buffer[10];
for(int it = 0; it < 1000; it++) {
buffer[it] = '*';
}
char accessViolation = foo[0];
}
l'exemple de dépassement de tampon" classique " est:
int main(int argc, char *argv[])
{
char buffer[10];
strcpy(buffer, argv[1]);
}
qui vous permet de jouer avec les paramètres de débordement de tampon et de les ajuster à votre contenu de cœur. Le livre "piratage-L'Art de L'Exploitation " (lien vers Amazon) va dans le détail sur la façon de jouer avec les débordements de tampon (purement comme un exercice intellectuel évidemment).
si vous voulez vérifier que votre programme ne déborde pas de tampon, vous pouvez l'exécuter avec des outils comme Valgrind. Ils trouveront des bogues de gestion de la mémoire pour vous.
C'est un commentaire général sur les réponses reçues. Par exemple:
int main(int argc, char *argv[]) { char buffer[10]; strcpy(buffer, argv[1]); }
Et:
int main(int argc, const char* argv[]) { char buf[10]; memset(buf, 0, 11); return 0; }
sur les plateformes Linux modernes, cela peut ne pas fonctionner comme prévu ou prévu. Il se peut que cela ne fonctionne pas à cause de la fonctionnalité de sécurité FORTIFY_SOURCE.
FORTIFY_SOURCE utilise des variantes "plus sûres" de fonctions à haut risque comme memcpy
et strcpy
. Le compilateur utilise les variantes les plus sûres quand il peut déduire le tampon de destination taille. Si la copie dépasse la taille du tampon de destination, alors le programme appelle abort()
.
pour désactiver FORTIFY_SOURCE pour vos tests, vous devez compiler le programme avec -U_FORTIFY_SOURCE
ou -D_FORTIFY_SOURCE=0
.
dans ce contexte, un tampon est une partie de la mémoire mise de côté pour un but particulier, et un débordement de tampon est ce qui se passe quand une opération d'écriture dans le tampon continue de passer la fin (écriture dans la mémoire qui a un but différent). C'est toujours un bug.
une attaque de débordement de tampon est une attaque qui utilise ce bogue pour accomplir quelque chose que l'auteur du programme n'avait pas l'intention d'accomplir.
avec les bonnes réponses données: pour en savoir plus sur ce sujet, vous voudrez peut-être écouter la sécurité du Podcast maintenant. Épisode 39 (un temps) ils ont discuté de cela en profondeur. C'est un moyen rapide d'obtenir une compréhension plus profonde, sans exiger de digérer un livre en entier.
(au lien vous trouverez l'archive avec plusieurs versions de taille ainsi qu'une transcription, si vous êtes plutôt orienté visuellement). L'Audio n'est pas le parfait moyen pour ce sujet mais Steve fait des merveilles pour gérer ça.