Cum functioneaza atacurile buffer overflow - Securitatea Informatica

Cum functioneaza atacurile buffer overflow

Prin buffer overflow intelegem un tip de atac prin care un atacator poate scrie intr-un buffer mai multe informatii decat poate retine bufferul respectiv, corupand astfel zonele adiacente. Rezultatul unui buffer overflow poate conduce la un comportament necorespunzator al programului ( rezultate gresite sau inconsistente ), erori de acces la memorie sau chiar la grave probleme de securitate, atunci cand un atacator produce in mod intentionat un overflow.

Pentru a intelege cum se pot corupe datele adiacente, sa presupunem urmatorul scenariu :
Avem un buffer A de tipul char* ce contine 8 bytes si adiacent cu acesta, un short B, ce contine 2 bytes, ca in imaginea urmatoare :
Buffer Overflow

In momentul in care s-ar face un strcpy cu sirul “overflow” in bufferul A, terminatorul de sir asociat sirului “overflow” va suprascrie primul octet al lui B, facandu-l 0 :
Buffer Overflow

Pentru a exemplifica acest lucru, va punem la dispozitie urmatorul cod C :

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main()
{
	char a[8];
	short b=2010;
	memset(a,0,8);
	printf("inainte de strcpy b=%d\n",b);
	strcpy(a,"overflow");
	printf("dupa strcpy b=%d\n",b);

	return 0;
}

Pentru compilare si rulare vom utiliza :

gcc overflow1.c -o overflow1 -fno-stack-protector
./overflow1

Vom putea observa ca dupa strcpy, valoarea lui B s-a schimbat.

Acum, pentru a intelege cum poate un atacator sa manipuleze programul nostru printr-un buffer overflow pentru a executa cod malitios, trebuie sa analizam putin stiva si sa vedem ce se intampla atunci cand o functie apeleaza alta functie, cat si modul in care o functie isi stocheaza variabilele locale.

Pe majoritatea sistemelor, stiva creste in jos, iar comportamentul este urmatorul ( credits go to Daniel Baluta ) :
Buffer Overflow

Atunci cand o functie apeleaza o alta functie, se retine adresa de return, la care programul se va intoarce la iesirea din functia apelata. Se va crea un nou stack frame pentru noua functie, in care aceasta isi va retine variabilele interne. Odata ce functia s-a incheiat, se va scoate stack frame-ul sau de pe stiva si programul va face jump la adresa specificata in campul ‘return address’, de unde va incepe sa execute cod.

Un atacator poate face overflow la un buffer, suprascriind continutul lui pana ajunge la adresa de return, pe care de asemenea o va suprascrie, pentru a putea executa o alta portiune de cod de pe stiva.

Sa luam drept exemplu programul urmator :

#include <stdlib.h>
#include <stdio.h>

void atacator()
{
	printf("Ai fost atacat\n");
	exit(EXIT_SUCCESS);
}

void init()
{
	int v[3];
	v[0]=98;
	v[1]=99;
	v[2]=101;

	v[4]=(int)&atacator;
}

int main()
{
	init();
	printf("All is ok\n");
	return 0;
}

Vom utiliza bufferul v pentru a accesa adresa de return. Vom completa in v[4] adresa functiei ‘atacator’, astfel incat aceasta va fi apelata la iesirea din functia init().

Twitter Digg Delicious Stumbleupon Technorati Facebook


Nici un comentariu inca... Fii primul care lasa un comentariu!

Lasa un raspuns

This site is protected by Comment SPAM Wiper. This site is protected by WP-CopyRightPro