You are on page 1of 4

Ataque de estouro de buffer

Descri��o

Erros de buffer overflow s�o caracterizadas pela substitui��o de fragmentos de


mem�ria do processo, o que nunca deveria ter sido modificados intencionalmente ou
n�o. Substitui��o de valores do IP (Instruction Pointer), BP (Base Pointer) e
outros registros provocam exce��es, falhas de segmenta��o, e que outros erros
ocorram. Geralmente estes erros de execu��o final da aplica��o de uma forma
inesperada. Erros de buffer overflow ocorre quando operamos em buffers do tipo
char.
Erros Bo (nome comum para este tipo de erros) s�o simplesmente estouro de pilha ou
heap em erros de estouro. N�o fazemos distin��o entre estes dois neste artigo para
evitar a confus�o do leitor.
A seguir exemplos s�o escritos em linguagem C sob o sistema GNU / Linux em
arquitetura x86.

Exemplo 1

#include <stdio.h>
int main(int argc, char **argv)
{
char buf[8]; // buffer for eight characters
gets(buf); // read from stdio (sensitive function!)
printf("%s\n", buf); // print out data stored in buf
return 0; // 0 as return value
}

Esta aplica��o muito simples l� da entrada padr�o um array de caracteres e copia


para o buffer do tipo char. O tamanho desta reserva � de oito caracteres. Depois
disso, o conte�do do buffer � exibido e sai do aplicativo.

Compila��o do programa:

portalhacking@spin ~/inzynieria $ gcc bo-simple.c -o bo-simple


/tmp/ccECXQAX.o: In function `main':
bo-simple.c:(.text+0x17): warning: the `gets' function is dangerous and
should not be used.

Nesta fase, mesmo que o compilador sugira que a fun��o obtenha () n�o � segura.
Exemplo de uso:

portalhacking@spin ~/inzynieria $ ./bo-simple // program start


1234 // we eneter "1234" string from the keyboard
1234 // program prints out the conent of the buffer
rezos@spin ~/inzynieria $ ./bo-simple // start
123456789012 // we eneter "123456789012"
123456789012 // content of the buffer "buf" ?!?!
Segmentation fault // information about memory segmenatation fault

N�s gerenciamos, (in)felizmente para executar a opera��o com defeito pelo programa,
e provoc�-lo a sair de forma anormal.
An�lise do problema:

O programa chama uma fun��o, que opera no buffer tipo char e n�o faz nenhuma
verifica��o contra estar transbordando o tamanho atribu�do a esse buffer. Como
resultado, � poss�vel que, intencionalmente ou n�o armazene mais dados do buffer, o
que vai causar um erro. Surge a seguinte quest�o: O buffer armazena apenas oito
personagens, ent�o por que a fun��o printf () Exibe doze?. A resposta vem da
organiza��o da mem�ria do processo. Quatro personagens que transbordaram do buffer
tamb�m substituir o valor armazenado em um dos registros, o que era necess�rio para
o retorno da fun��o correta. Mem�ria continuidade resultou em imprimir os dados
armazenados na �rea de mem�ria.

Exemplo 2

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

void doit(void)
{
char buf[8];

gets(buf);
printf("%s\n", buf);
}

int main(void)
{
printf("So... The End...\n");
doit();
printf("or... maybe not?\n");

return 0;
}

Este exemplo � an�logo ao primeiro. Al�m disso, antes e depois da fun��o doit (),
temos duas chamadas para fun��o printf ().

Compilation:

portalhacking@dojo-labs ~/owasp/buffer_overflow $ gcc example02.c -o example02


-ggdb
/tmp/cccbMjcN.o: In function `doit':
/home/rezos/owasp/buffer_overflow/example02.c:8: warning: the `gets'
function is dangerous and should not be used.

Usage example:
rezos@dojo-labs ~/owasp/buffer_overflow $ ./example02
So... The End...
TEST // user data on input
TEST // print out stored user data
or... maybe not?

O programa define entre as duas chamadas printf () mostra o conte�do da mem�ria


interm�dia, que � preenchida com os dados introduzidos pelo utilizador.

portalhacking@dojo-labs ~/owasp/buffer_overflow $ ./example02


So... The End...
TEST123456789
TEST123456789
Segmentation fault

Porque o tamanho do buffer foi definido (char buf [8]) e foi preenchido com treze
caracteres do tipo char, o buffer transbordou.
Se o nosso pedido de bin�rio est� no formato ELF, ent�o somos capazes de usar um
programa para analisar objdump-lo e encontrar informa��es necess�rias para explorar
o erro de estouro de buffer.
Abaixo encontra-se de sa�da produzido pelo objdump. Desde que a produ��o, somos
capazes de encontrar endere�os, onde printf () � chamado (0x80483d6 e 0x80483e7).

portalhacking@dojo-labs ~/owasp/buffer_overflow $ objdump -d ./example02

080483be <main>:
80483be: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483c2: 83 e4 f0 and $0xfffffff0,%esp
80483c5: ff 71 fc pushl 0xfffffffc(%ecx)
80483c8: 55 push %ebp
80483c9: 89 e5 mov %esp,%ebp
80483cb: 51 push %ecx
80483cc: 83 ec 04 sub $0x4,%esp
80483cf: c7 04 24 bc 84 04 08 movl $0x80484bc,(%esp)
80483d6: e8 f5 fe ff ff call 80482d0 <puts@plt>
80483db: e8 c0 ff ff ff call 80483a0 <doit>
80483e0: c7 04 24 cd 84 04 08 movl $0x80484cd,(%esp)
80483e7: e8 e4 fe ff ff call 80482d0 <puts@plt>
80483ec: b8 00 00 00 00 mov $0x0,%eax
80483f1: 83 c4 04 add $0x4,%esp
80483f4: 59 pop %ecx
80483f5: 5d pop %ebp
80483f6: 8d 61 fc lea 0xfffffffc(%ecx),%esp
80483f9: c3 ret
80483fa: 90 nop
80483fb: 90 nop

Se a segunda chamada para printf () deve informar o administrador sobre o logout do


usu�rio (por exemplo, sess�o fechada), ent�o podemos tentar omitir esta etapa e
terminar sem a chamada para printf ().

portalhacking@dojo-labs ~/owasp/buffer_overflow $ perl -e 'print "A"x12


."\xf9\x83\x04\x08"' | ./example02
So... The End...
AAAAAAAAAAAAu*.
Segmentation fault

A aplica��o terminar sua execu��o com falha de segmenta��o, mas a segunda chamada
para printf () n�o teve lugar.
Algumas palavras de explica��o:
perl-e 'print "A" x12 "\ XF9 \ x83 \ x04 \ x08".' - ir� imprimir doze caracteres
"A" e, em seguida, quatro personagens, que s�o na verdade um endere�o da instru��o
que deseja executar. Por doze anos?

8 // size of buf (char buf[8])


+ 4 // four additional bytes for overwriting stack frame pointer
----
12

An�lise do problema:
A quest�o � o mesmo que no primeiro exemplo. N�o existe controle sobre o tamanho do
buffer de copiado para o anteriormente declarado. Neste exemplo, substituir o
registo EIP com o endere�o 0x080483f9, que � na verdade uma chamada para ret na
�ltima fase da execu��o do programa.
Como usar erros de estouro de buffer de uma maneira diferente?
Geralmente, a explora��o desses erros pode levar a:
* Aplica��o DoS
* Reorganiza��o da execu��o de fun��es
* Execu��o de c�digo (se est� apto a shellcode, descrita em um documento separado)

Como os erros de estouro de buffer s�o feitos?


Estes tipos de erros s�o muito f�ceis de fazer. Durante anos, eles eram o pesadelo
de um programador. O problema reside em fun��es C nativas, que n�o se importam em
fazer verifica��es de comprimento tamp�o adequadas. Abaixo est� a lista de tais
fun��es e, se existirem, os seus equivalentes de seguran�a:

* gets() -> fgets() - read characters


* strcpy() -> strncpy() - copy content of the buffer
* strcat() -> strncat() - buffer concatenation
* sprintf() -> snprintf() - fill buffer with data of different types
* (f)scanf() - read from STDIN
* getwd() - return working directory
* realpath() - return absolute (full) path

Use fun��es equivalentes seguras, que verificam o comprimento buffers, sempre que
poss�vel. a saber:

1- gets() -> fgets()


2- strcpy() -> strncpy()
3- strcat() -> strncat()
4- sprintf() -> snprintf()

Essas fun��es que n�o tem equivalentes seguros deve ser reescrito com verifica��es
de seguran�a implementadas. Tempo gasto no que vai beneficiar no futuro. Lembre-se
que voc� tem que faz�-lo apenas uma vez.
Use compiladores, que s�o capazes de identificar as fun��es inseguras, erros de
l�gica e verifique se a mem�ria � substitu�do quando e onde ele n�o deveria estar.