Entendendo o Buffer Overflow

Introdução

Estou iniciando uma série de artigos onde pretendo escrever sobre vulnerabilidades, shellcodes, exploits e  afins.

É uma área que tenho estudado e descobri ser muito interessante, pois envolve assuntos como assembly, engenharia reversa, programação de baixo-nível, segurança, e que também está no contexto dos crimes cibernéticos.

Por exemplo, uma vulnerabilidade no navegador pode ser explorada quando o usuário acessar um site com códigos-maliciosos, possibilitando assim a instalação de malwares.

Ao invés de utilizar ferramentas prontas resolvi iniciar meus estudos do começo, do nível mais baixo, entender como ocorre uma vulnerabilidade, como é feito um exploit e como é criado o shellcode.

Mesmo que as técnicas estejam um pouco ultrapassadas, acho importante ter o conhecimento da base para depois partir para ferramentas como Metasploit. E para aprender mais nada melhor do que ensinar o pouco que sei.

Então, qual seria a vulnerabilidade mais conhecida e simples de entender?

Buffer Overflow

Frequentemente é noticiado que em uma aplicação qualquer foi encontrada a vulnerabilidade de buffer overflow (ou estouro de buffer) e que através dela um atacante consegue executar código arbitrário. O arbitrário quer dizer qualquer código que ele desejar, ou quase isso.

O comunicado abaixo é um exemplo clássico, emitido pelo CERT em 2003:


A buffer overflow vulnerability exists in Microsoft's Remote Procedure Call (RPC) implementation. A remote attacker could exploit this vulnerability to execute arbitrary code or cause a denial of service.

Atualmente a vulnerabilidade de buffer overflow é encontrada com menos frequência pois foram criados vários mecanismos de proteção contra ela. Porém ainda ocorre, como podemos ver nessa notícia mais atual, de 27/01/2011:


Multiple vulnerabilities have been reported in Symantec products, which can be exploited by malicious people to cause a Denial of Service and compromise a vulnerable system, according to Secunia.

1. An error in the Intel AMS2 component when processing certain messages can be exploited to cause a buffer overflow via specially crafted packets sent to TCP port 38292.
Successful exploitation of the vulnerabilities may allow execution of arbitrary code.
The vulnerabilities are reported in the following products: Symantec AntiVirus Corporate Edition Server 10.x and .Symantec System Center 10.x. A solution is to update to version 10.1 MR10.

Afinal, na prática o que é isso de buffer overflow?

Entendendo o Buffer Overflow

Em programação, buffer é uma variável (também conhecida como array ou vetor), um local na memória que armazena uma quantidade X de bytes.

Por exemplo um buffer que tenha capacidade de armazenar 10 bytes, só conseguiria guardar uma palavra de 9 caracteres (cada caracter sendo 1 byte) já que o último precisa ser o caracter nulo para o programa saber que a palavra termina ali.

Então esse código em C estaria correto:

char buffer[10] = {'S', 'E', 'G', 'U', 'R', 'A', 'N', 'Ç', 'A', '\0'};

Uma variável denominada buffer que tem 10 bytes de capacidade de armazenamento recebe uma palavra de 9 caracteres finalizando com o ('\0'). Isso está correto.

Agora o que aconteceria se eu inserisse uma palavra com mais de 9 caracteres?

Eis o buffer overflow! A variável copia somente os 10 primeiros caracteres e o resto estoura, ou transborda, já que não cabe mais nela.

E o resto da sequência após o 10º byte não é descartado, ele sobrescreve o que tiver na memória após a varíavel. Vamos ver um programinha que demonstra isso.

Esse é o código do programa em C:

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

int main(int argc, char *argv[]){
 char buffer1[8] = {'B','U','F','F','E','R','1','\0'};
 char buffer2[8] = {'B','U','F','F','E','R','2','\0'};
 
 printf("\n[ANTES] Buffer2 contem: %s\n",buffer2);
 printf("[ANTES] Buffer1 contem: %s\n\n",buffer1);
 
 strcpy(buffer2,argv[1]);
 
 printf("[DEPOIS] Buffer2 contem: %s\n",buffer2);
 printf("[DEPOIS] Buffer1 contem: %s\n\n",buffer1);
 
 return 0;
}

O programa cria uma variável denominada buffer1 com capacidade de armazenamento de 8 bytes e atribui a ela a palavra “BUFFER1” com o caracter nulo finalizando, o mesmo ocorre com a buffer2. Depois exibe o conteúdo de cada uma com o printf.

Na sequência copia para a variável buffer2 o que for passando como argumento na execução do programa e exibe novamente o conteúdo de cada uma.

O programa foi salvo com o nome “overflow.c” e compilado no Linux Debian 3.0 R4 com esse comando:

gcc -o overflow overflow.c

Vejamos algumas execuções do programa com argumentos diferentes:


Na primeira execução foi passada a string “1234567” como argumento para o programa, vemos que ela foi exibida corretamente já que possui 7 bytes e está no limite da capacidade da variável, o programa adiciona o caracter nulo automaticamente ao final da string.

Na segunda execução foi informada a string “12345678” e já vemos aí um buffer overflow. Apesar dela ter 8 bytes (mesma capacidade da variável), ela estourou porque o programa sempre adiciona o nulo ao final. Sendo assim o nulo transbordou o espaço do buffer2 e sobrescreveu o espaço do buffer1.

O mesmo aconteceu na terceira execução, a string foi maior ainda “1234567890123”, dessa vez estourou 5 bytes mais o nulo. A variável buffer1 ficou com esses bytes que passaram da conta.

Detalhe: mesmo a string sendo maior que a variável o programa ainda exibe a string completa no buffer2, isso ocorre porque conforme já mencionado o programa só sabe que um string termina quando ele encontra o nulo.

Caso seja passada como parâmetro uma string maior ainda, o programa irá travar e apresentar um erro de Segmentation falt. Isso ocorre porque a string começa sobrescrever vários segmentos de memória que são utilizados para controlar a execução do programa, isso faz com o que o programa “se perca” e trave. Conhece a famosa tela azul do Windows, the blue screen of death? :)

Nosso programa exibindo o erro de segmentation falt:


Justamente a capacidade da variável sobrescrever o que tiver pela frente na memória torna possível tomar o controle do programa e redirecionarmos a execução do mesmo para o que quisermos, isto é, executar código arbitrário. Ao invés de o programa travar podemos fazê-lo executar um shell.

Isso é assunto para o próximo post!

Obs.: os exemplos aqui apresentados podem variar de acordo com a a versão do sistema operacional e do compilador gcc. Utilizei uma versão antiga do Debian, a 3.0 R4, pois nela ainda não havia sido implementadas técnicas de proteção contra buffer overflow. Em posts futuros irei falar sobre isso também.

Adicionado em 15/03/2011:

Para reproduzir os exemplos desse artigo em distribuições Linux mais atuais é necessário desativar algumas proteções, faça o seguinte:

- Debian e Ubuntu based, desativar ASLR:

echo 0 > /proc/sys/kernel/randomize_va_space

- Red Hat based, desativar ASLR e DEP (ExecShield):

echo 0 > /proc/sys/kernel/exec-shield-randomize

echo 0 > /proc/sys/kernel/exec-shield

- GCC a partir da versão 4.1 compilar com diretiva -fno-stack-protector, exemplo:

gcc -fno-stack-protector -o overflow overflow.c

Fiz o teste no Debian 5.0.3 com GCC 4.3.2-2 e funcionou corretamente.

Ronaldo Lima
crimesciberneticos.com | twitter.com/crimescibernet

22 comentários:

  1. Se vc puder faça um post sobre XSS (Cross Site Scripting) que também é uma vulnerabilidade muito conhecida!
    abraço!

    ResponderExcluir
  2. Cara ta de parabéns, tudo que li no seu blog consegui entender com facilidade.. Tô gostando se tiver como postar as coisas mais rapido, melhor ainda =D

    Abraços

    ResponderExcluir
  3. Olá Ronaldo, aqui é o Luiz Vieira!

    Rapaz, muito bom o seu post :-) Estou justamente compilando material para um curso sobre desenvolvimento de exploits, e é legal saber que você também se interessa pela assunto, além da análise de malware (são os dois próximos cursos a serem criados por mim: análise de malware e desenvolvimento de exploits).

    O que me diz de criarmos uma lista sobre o assunto?

    Abração
    Luiz

    ResponderExcluir
  4. Olá pessoal, agradeço todos os comentários!!

    Estão anotadas todas as sugestões.

    Grande Luiz, legal que tenha gostado do post, achei boa sua ideia, podemos criar uma lista sim. Tenho estudado bastante sobre desenvolvimento de exploits. Vou mandar um email pra vc.

    Abraços!

    ResponderExcluir
  5. cara muito bom essa explicação sobre buffer overflow. Estou estudando assembly para entender mais sobre exploits, shell codes e malwares.
    O que vc està estudando para entender sobre estes assuntos e o que eu devo estudar para ficar fera igual vc?
    Vlw cara

    ResponderExcluir
  6. Olá Anônimo, agradeço os comentários.

    Esses assuntos estou estudando por esses livros:

    1. Gray Hat Hacking The Ethical Hackers Handbook, 3rd Edition (acabou de ser lançado)

    2. Hacking: The Art Of Exploitation, 2nd Edition

    3. Writing Security Tools and Exploits

    4. Shellcoder's Handbook

    No site da Amazon dá pra obter mais informações sobre eles, inclusive comprá-los.

    Abraço!

    ResponderExcluir
  7. Vlw pela dica Ronaldo!
    Estou pensando seriamente em buscar cursos dos USA porque os cursoa na àrea de Security aqui no brasil està muito fraco. Achei um site de treinamento em security muito fera! (Programa de Segurança InfoSec Institute) Inclusive uns dos gerentes desta escola é um dos principais autores do livro Shellcoder's Handbook (citado por vc)
    Estava olhando o curso deles de Ethical Hacking e Hands On Training Segurança, e fiquei cabulado!
    Por que será?
    Com certeza é por causa do conteúdo do curso deles...

    Aqui vai uns dos tópicos falados em um dos cursos de Hacking:
    * Escrever exploits de buffer overflow
    * dlmalloc Heap Overflow exploits dlmalloc heap overflow
    * Win32 Heap Overflow exploits Win32 Heap overflow
    * Linux stack overflow exploits Linux explorações de estouro de pilha
    * Defeating non-exec stacks Derrotar pilhas non-exec
    * Return-to-libc shellcode shellcode Return to libc
    * Function pointer overwrites ponteiro de função substitui
    * Crafting Injectable Shellcode Crafting Shellcode injetável
    * Defeating non-executable stacks Derrotar pilhas não-executável
    * Linux LKM Rootkits Rootkits LKM Linux
    * Windows Kernel Rootkits Kernel Rootkits Windows
    * Reverse engineering training Formação em engenharia reversa
    * Vulnerability development and discovery Vulnerabilidade de desenvolvimento e descoberta
    * Attacking and blinding IDSs Atacar e cegando IDSs
    * Hiding your attacks from IDSs Escondendo seus ataques de IDSs
    * Encrypted covert channels Criptografado canais dissimulados



    * Global Offset Table Overwrites Global Tabela Offset Overwrites
    * Windows Shellcode Windows Shellcode
    * Integer Overflows Integer Overflow
    * Linux shellcode Linux shellcode
    * "no listening port" trojans "Nenhuma porta de escuta" trojans
    * A whole day on breaking through enterprise DMZs Um dia inteiro de romper DMZs empresa
    * Reconstructing binaries from sniffed traffic Reconstruindo binários de tráfego cheirou
    * Circumventing antivirus Engana antivírus
    * Bi-directional Spoofed Communication Bi-direcional falsificados Comunicação
    * Session fixation fixação de sessão
    * Advanced SQL Injection Advanced SQL Injection
    * Justifying a penetration test to management and customers Justificando um teste de penetração para a gestão e os clientes
    * Defensive techniques técnicas de defesa


    Fala pra min Ronaldo. Aonde vejo um curso assim no Brasil?

    Os cursos do Brasil parecem que são censurados!

    Vlw Ronaldo! Me add no msn pra gente bater um papo

    igor anderline rfl anderline arroba msn.com

    Abraçs!

    ResponderExcluir
  8. http://www.infosecinstitute.com/

    ResponderExcluir
  9. Olá Igor, muito bom mesmo o curso!!

    Vendo esses tópicos dá vontade de ir correndo lá fazer, vc tem razão não existe nenhum curso avançado no Brasil sobre esses temas.

    Será que falta mercado para esses cursos ou falta profissional qualificado para passar esses conhecimentos no Brasil?

    Cursos similares no exterior têm nessas empresas também:

    SANS
    http://www.sans.org/security-training/courses.php

    Immunity
    http://www.immunitysec.com/education-overview.shtml

    O Luiz Vieira que deixou um comentário acima é instrutor de cursos de segurança na 4Linux, fiz o curso de forense lá com ele, ele falou que está criando um curso de desenvolvimento de exploits, inclusive vamos criar um lista sobre o assunto, aí eu te adiciono ok? O blog dele é esse: http://hackproofing.blogspot.com

    Abraço!

    ResponderExcluir
  10. Ok!! Quando começar este curso Ronaldo você me avisa!
    Fico feliz de saber que no brasil tem grandes profissionais como vc e o Luiz Vieira.
    Vc é uma grande influência nos meus estudos...
    Vlw Ronaldo!
    Abraçs

    ResponderExcluir
  11. muito bacana..que pena q não é muito divulgado..

    macedo$ gcc overflow.c -o overflow
    macedo:Desktop macedo$ ./overflow 12345678

    [ANTES] Buffer2 contem: BUFFER2
    [ANTES] Buffer1 contem: BUFFER1

    [DEPOIS] Buffer2 contem: 12345678
    [DEPOIS] Buffer1 contem: BUFFER1

    macedo:Desktop macedo$

    macedo$ ./overflow 1234567890

    [ANTES] Buffer2 contem: BUFFER2
    [ANTES] Buffer1 contem: BUFFER1

    Abort trap
    macedo:Desktop macedo$

    Como vc tinha falado, provavelmente este erro deve ser pela versão que estou utilizando, caso nao seja...se puder esclarecer obrigado.
    utilizo: Darwin Kernel Version 10.6.0 e gcc version 4.2.1
    obrigado....

    ResponderExcluir
  12. Olá Fernandes, a gente fez o curso de forense juntos né?

    Então, é por causa das versões sim, foram criadas várias proteções tanto no gcc quanto no sistema operacional. Aliás esse kernel que vc está utilizando eu não conheço, é Mac?

    Tente isso para tirar a proteção ASLR:

    echo 0 > /proc/sys/kernel/randomize_va_space

    E compile novamente o programa adicionando esse parâmetro do gcc: -fno-stack-protector

    Talvez isso funcione, mas têm algumas proteções que não me recordo, em breve vou fazer um post novo sobre as proteções e como desativá-las nos sistemas atuais.

    Abraço!

    ResponderExcluir
  13. Não tenho certeza...vc era aquele cara q tinha cabelo grande?...se for fizemos em dezembro 2010...
    De qualquer forma vou dar uma olhada...

    to estudando assembly novamente..o da faculdade nao da pra aprender nada...vc recomenda algum bom livro na area?? to terminado este..
    http://www.submarino.com.br/produto/1/253985/fundamentos+em+programacao+assembly+para+computadores+ibm-pc...

    ResponderExcluir
  14. Fernandes,

    Sou eu mesmo. Esse livro que vc está lendo parece ser bom. Sugiro que vc estude o assembly gerado pelos compiladores, ou seja, o disassembly.

    Escrever um software em assembly é diferente do assembly que os compiladores geram, existem muitas otimizações de código, os livros de engenharia reversa tratam disso, eu tenho o Reversing Secrets of Reversing Engineering e acho muito bom. E para consulta eu uso o Art Of Assembly.

    http://www.crimesciberneticos.com/p/bibliografia.html

    Abraço!

    ResponderExcluir
  15. Pessoal,
    Parabéns a todos. Programo pouco em VB e estou estudando C e assembler (para microcontroladores). Poxa entendi legal tudo aqui postado. Pena que não domino Linux. Esse curso que vcs fizeram foi em São Paulo ?? Se puderem me dar a referência agradeço.
    Ulisses Fontoura.

    ResponderExcluir
  16. Olá Ulisses, tudo bem?

    Agradeço os comentários, legal que tenha entendido o post.

    Na verdade não fizemos esse curso, estávamos comentando que no Brasil quase não tem curso desse tipo. Você conhece a lista de discussão Exploits-Brasil?

    http://www.crimesciberneticos.com/2011/03/grupo-sobre-exploits-e-vulnerabilidades.html

    O Luiz, que é um dos idealizadores da lista está montando alguns cursos EAD sobre esses temas, talvez possa se interessar. Você pode entrar na lista e ver os tópicos antigos ou se quiser falar com ele diretamente o email é: luizwt gmail com.

    Abraços!

    ResponderExcluir
  17. A poucos minutos o meu anti vírus (Comodo) deu esse alerta quando acionei o Firefox, não permitindo a abertura do programa. Como isso pode ocorrer? Troiano?

    Abs

    ResponderExcluir
  18. Olá Roberto,

    Mensagem de "Buffer Overflow"? Pode ser muitas coisas, não dá pra saber só assim, tem que ser feita uma varredura completa na máquina. Pode tentar a reinstalação do Firefox também.

    Abraços.

    ResponderExcluir
  19. Este comentário foi removido pelo autor.

    ResponderExcluir
    Respostas
    1. Parabéns pelos excelentes artigos !!!

      Um grande abraço.

      Excluir
  20. Olá Roberto Lima !!!

    Parabéns pelos seus artigos !!! Explicações claras, concretas e objetivas.

    Gerson Raymond
    www.backtrackbrasil.com.br

    ResponderExcluir

Related Posts Plugin for WordPress, Blogger...