estouro de buffer (buffer overflow) - meus achados preciosos · conceito de pilha (stack) ! pilha...

53
1 Estouro de Buffer (Buffer Overflow) Prof. Paulo Cesar F. de Oliveira, BSc, PhD

Upload: doanquynh

Post on 08-Feb-2019

228 views

Category:

Documents


0 download

TRANSCRIPT

1

Estouro de Buffer (Buffer Overflow)

Prof. Paulo Cesar F. de Oliveira, BSc, PhD

2

Capítulo 03 Estouro Buffer

02/04/14 © P C F de Oliveira 2014

Seção 1.1 Introdução

3 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

O que é ?

4 02/04/14 © P C F de Oliveira 2014

² Definições ²  Buffer (array ou string)

²  Área da memória onde a entrada do usuário é armazenada

²  Estouro (Overflow) ²  Entrada do usuário excede o tamanho máximo do

buffer ²  Sobrescrevendo outras áreas da memória e

corrompendo-as

Capítulo 03 Estouro Buffer

5 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer ² O que é?

²  Evento que ocorre quando:

²  Buffer de dados de comprimento fixo (e.g. string)

²  Pelo menos um valor destinado ao buffer é escrito fora de seus limites (geralmente após o seu fim)

²  Leitura da entrada ou após o tratamento de dados

6 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer ² O que é?

²  Buffer overflows = buffer overruns

²  Stack overrun ²  Buffer na pilha (stack) ²  Também chamado “stack smashing”

²  Heap overrun ²  Buffer na heap ²  Também chamado “heap smashing”

7 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer ² O que é?

²  Problema comum

²  Se explorável ²  Agressor pode controlar o programa

completamente

²  Agressor pode tipicamente causar negação de serviço ²  Muitas defesas simplesmente reduzem-se de

“programa de controle” para o DoS (Denial-of-Service)

8 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

1988: Morris worm – tirou Internet do ar Inclui estouro de buffer via gets() in fingerd

1999: Implementação de referência crypto RSA, Subverteu PGP, OpenSSH, Apache’s ModSSL, etc.

2003: SQL Slammer worm comprometeu máquinas rodando Microsoft SQL Server 2000

2008: Twilight hack – abre consoles Wii, Criando um nome longo para cavalo “Epona” no jogo "The Legend of Zelda: Twilight Princess", permitindo execução

2001: Code Red worm – buffer overflow no Microsoft’s Internet Information Services (IIS) 5.0

1998: University of Washington servidor IMAP (mail)

Histórico

9 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

² Linguagens de Programação e Estouro de Buffer ²  Linguagens que permitem o evento

² C, C++, Objective-C, Vala, Forth, Assembly ²  Linguagens que não permitem

² Ada strings, Pascal: Detém/previne overflow ²  Java, Python, Perl, Ada: Auto-resize

²  Outras linguagens não dão imunidade ²  Implementações da maioria são em C/C++ ² Várias bibliotecas/componentes do SO incluem C/C++ ² Algumas linguagens/compiladores permitem desabilitar

proteção ² C# e Ada

² Escolhendo outra ajuda – mas não completamente

Muito comum

10

Capítulo 03 Estouro Buffer

02/04/14 © P C F de Oliveira 2014

Seção 1.2 Recapitulação

11 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

² Terminação de string em C è \O ²  Strings em C terminam com caracter \0 (1 byte valor 0) ²  Vários SOs e componentes construídos com C

²  Interfaces herdam semanticamente “strings com \0” ²  Alguns componentes não lidam com isto, mesmo

que a linguagem possa ²  Observe que \0 ocupa espaço – lembre-se disto ²  Nome formal é NUL ou caracter NULL

²  Às vezes confundido com NULL – “null pointer”

H e l l o \0 NIL (reduzir confusão)

12 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

² Arrays em C ²  Arrays alocam um tamanho fixo de memória

²  Ex., para um buffer ²  Arrays “char” são usadas para string de caracteres

²  Devem ser o grande suficiente ²  Para os caracteres a serem armazenados ²  Incluindo também o caracter NIL

²  Ex. “char x[10];” § Aloca espaço para uma array x § Array x possui 10 chars § Armazena 9 caracteres + caracter de

terminação NIL

13 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Exemplo #1

int main() { int array[5] = {1, 2, 3, 4, 5}; printf("%d\n", array[5]); }

§ Nunca faça isto § Checar limites da array em tempo de

execução

14 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Exemplo #2

int main() { int array[5] = {1, 2, 3, 4, 5}; int i; for( i=0; i<=255; i++ ) array[i] = 41; }

§ Nunca faça isto § Checar limites da array em tempo de

execução

15 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Exemplo #3

int main(int argc, char* argv[]) { char command[10]; printf(”Seu comando? \n"); gets(command); printf(”Seu comando foi: %s\n", command); } § Só 10 bytes para variável command

(incluindo NIL) §  Instrução gets não provê proteção

contra estouro de buffer

§ Nunca use gets § Use fgets(buf, size, stdin)

16 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Exemplo #3

... char dest [20]; strcpy (dest, src) //copia string src para dest ...

§ strcpy assume dest é grande o bastante

§ Nunca use strcpy § Use strncpy(dest, src, size)

17 02/04/14 © P C F de Oliveira 2014

Seção 1.3 Mapeamento da Memória

Capítulo 03 Estouro Buffer

18 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Stack (Pilha)

Heap (alocada dinamicamente) Dados 2 Globais não inicializados Dados 1 Globais

inicializados Código do Programa

§  Stack: Contém endereço de retorno das chamadas de função, argumentos para funções e variáveis locais

§  Heap: Contém dados dinâmicos e não inicializados

§  Dados 2: Contém variáveis globais não inicializadas

§  Dados 1: Contém variáveis globais inicializadas §  Inicializadas na carga do código

§  Código do programa: Contém as instruções (comandos) § Somente pra leitura

§  Usado para variáveis e constantes globais

19 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Observando código abaixo

int main() { int char sample[10]; int i; for (i=0; i<=9; i++)

sample[i] = 'A'; sample[10] = 'B’

}

Onde ‘B’ ficará (memória) ?

20 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Possibilidade #1

A A A A A A A A A A B

Mem

ória

Afeta os dados do usuário

Dados do Usuário

21 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Possibilidade #2

A A A A A A A A A A B

Mem

ória

Afeta código do usuário

Dados do Usuário Código do Programa do

Usuário

22 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Possibilidade #3

A A A A A A A A A A B

Mem

ória

Afeta os dados do sistema

Dados do Usuário Dados do Sistema

23 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Possibilidade #4

A A A A A A A A A A B

Mem

ória

Afeta código do sistema

Dados do Usuário Código do Programa do

Sistema

24 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Questões para responder

²  Que valores o hacker poderia inserir após o buffer que causasse prejuízo ou dano?

²  Quais códigos de instrução planejados o sistema seria forçado a executar?

25

Capítulo 03 Estouro Buffer

02/04/14 © P C F de Oliveira 2014

Seção 1.4 Stack Smashing (estouro da pilha)

26 02/04/14 © P C F de Oliveira 2014

² Conceito de Pilha (Stack) ²  Pilha de objetos tem a propriedade de que o último objeto

inserido será o primeiro objeto a ser removido ²  Last in – First out (LIFO) ²  Operações básicas

²  PUSH: adiciona um elemento no topo da pilha

²  POP: remove um elemento do topo da pilha, reduzindo o tamanho dela em 1 unidade

 

Capítulo 03 Estouro Buffer

27 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer Funcionamento da Stack (Pilha)

28 02/04/14 © P C F de Oliveira 2014

² Pilha (Stack) no Processo de Mapeamento da Memória ² Área de memória reservada para implementar as chamadas para

um procedure / function / method / subroutine ² Estes termos são sinônimos (C -> function – função)

² Stack é usada para implementar controle de fluxo ² Quando você chama procedure, de “onde ele veio" é inserido

(PUSH) na pilha ² Quando procedure retorna, o de “onde vim" é removido (POP)

da pilha; ² Sistema começa a execução de código lá

² Stack também utilizado para outros dados (em muitos casos) ² Parâmetros passados para procedure ² Variáveis locais das procedures ² Valores de retorno da procedure

 

Capítulo 03 Estouro Buffer

29 02/04/14 © P C F de Oliveira 2014

² Stack possui 2 valores ²  Stack Pointer: valor que está no topo

²  Onde o último dado foi armazenado

²  Modificado quando dado for (pushed/popped)

²  Frame Pointer: valor do “quadro” – conteúdo ²  Simplifica acesso a parâmetros e variáveis locais

²  Aponta para onde “o procedimento” começa dentro da pilha

²  Modificado na entrada/saída do procedimento

Capítulo 03 Estouro Buffer

30 02/04/14 © P C F de Oliveira 2014

#include <stdio.h> #include <stdlib.h> #include <string.h> void f(int a, int b, int c) { char buffer1[5]; char buffer2[10]; strcpy(buffer2, "This is a very long string!!!!!!!");

} int main() { f(1,2,3);

}

Capítulo 03 Estouro Buffer

Código assembler pushl $3 ;constante 3 pushl $2 ;constante 2 pushl $1 ;constante 1 call f

Execução do programa

31 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses

Stack pointer (SP) (current top of stack) 3

Stack: após push do valor 3

32 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 Stack pointer (SP) (current top of stack)

Stack: após push do valor 2

Stack cresce; i.e. devido à chamada da procedure

33 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack pointer (SP) (current top of stack)

Stack: após push do valor 1

Stack cresce; i.e. devido à chamada da procedure

34 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack: logo após a chamada da

função

Endereço Retorno em main() Stack pointer (SP) (current top of stack)

Stack cresce; i.e. devido à chamada da procedure

35 02/04/14 © P C F de Oliveira 2014

#include <stdio.h> #include <stdlib.h> #include <string.h> void f(int a, int b, int c) { char buffer1[5]; char buffer2[10]; strcpy(buffer2, "This is a very long string!!!!!!!");

} int main() { f(1,2,3);

}

Capítulo 03 Estouro Buffer

pushl %ebp ;Push old frame pointer (FP) movl %esp,%ebp ;New FP é SP (old) subl $20,%esp ;New SP está após vars locais

;“$20” calculado p/ser >= espaço var local

Execução da procedure

§  EBP: Base pointer: aponta para o início do stack frame corrente

§  ESP: Stack pointer: aponta para o topo da stack

36 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack: execução da função

Endereço Retorno em main()

Frame pointer (FP) – Use para acessar variáveis locais e parâmetros

Frame pointer salvo (old)

Array local “buffer1”

Array local “buffer2”

Stack pointer (SP) (current top of stack)

Stack cresce; i.e. devido à chamada da procedure

37 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack: “estourando” buffer2

Endereço Retorno em main()

Frame pointer (FP) – Use para acessar variáveis locais e parâmetros

Frame pointer salvo (old)

Array local “buffer1”

Array local “buffer2”

Stack pointer (SP) (current top of stack)

Overw

rite

Stack cresce; i.e. devido à chamada da procedure

38 02/04/14 © P C F de Oliveira 2014

² O que acontece se escrevermos algo no fim de buffer2? ² Substitui o que estiver após buffer2

² Quanto mais longe for, mais endereços altos sobrescritos

² Impacto depende de detalhes do sistema

² No exemplo, irá substituir ² Valores locais (buffer1)

² Frame Pointer Salvo ² Valor de Retorno (mudando ponto de volta ao PP) ² Parâmetros da função (procedure)

² Frames anteriores

Capítulo 03 Estouro Buffer

39 02/04/14 © P C F de Oliveira 2014

² Ataque mais comum de estouro de buffer ² Enviar dados muito largos ou ² Criar dados extremamente largos ² Dados muito largos sobrescrevem o buffer

² Modifica o valor de retorno para

² Aponta para algo que o hacker quer que se execute ² Talvez com parâmetros diferentes também

² No retorno executa código selecionado por ele

Capítulo 03 Estouro Buffer

Mas, tem coisa pior!!!

40 02/04/14 © P C F de Oliveira 2014

² Inserindo código no estouro de buffer (e.g. Shell code) ² Hacker pode incluir um código de máquina que ele quer

que se rode ² Se ele pode definir o valor de “retorno” apontar para

um código malicioso, ² No retorno a vítima executará este código

² A menos que algo seja feito ²  O paper “Smashing the Stack” contém uma descrição

de como inserir este código

Capítulo 03 Estouro Buffer

41 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack: 1 possível resultado após ataque

Endereço Retorno em main()

Frame pointer (FP) – Use para acessar variáveis locais e parâmetros

Frame pointer salvo (old)

Array local “buffer1”

Array local “buffer2”

Stack pointer (SP) (current top of stack)

Stack cresce; i.e. devido à chamada da procedure

Código Malicioso

Ptr código malicioso

42 02/04/14 © P C F de Oliveira 2014

Capítulo 03 Estouro Buffer

Lower-numbered addresses

Higher-numbered addresses 3

2 1

Stack: 1 possível resultado após ataque

Endereço Retorno em main()

Frame pointer (FP) – Use para acessar variáveis locais e parâmetros

Frame pointer salvo (old)

Array local “buffer1”

Array local “buffer2”

Stack pointer (SP) (current top of stack)

Stack cresce; i.e. devido à chamada da procedure

Ptr código malicioso

Shellcode: \xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh

NOP sled: \x90\x90\x90\x90\x90…. NOP slide §  Permite que hacker

pule para qualquer lugar para atacar

§  Alguns muito complexos para detectar

Shellcode: ver slide seguinte

43 02/04/14 © P C F de Oliveira 2014

² Outros tipos de ataques possíveis no estouro de buffer ² Fazer o “código de retorno” apontar para um código

existente que o hacker queira que se execute ² E.g. chamar um shell ² Talvez modificar parâmetros

² Alterar valores de variáveis locais adjacentes ² Alterar valor dos parâmetros ² Entender que sobrescrever algo após o fim de um buffer

pode ter consequências devastadoras ² Detalhes dependem do sistema ² Sim, os hackers realmente entendem isto

Capítulo 03 Estouro Buffer

44 02/04/14 © P C F de Oliveira 2014

Seção 1.5 Heap Smashing (estouro da heap)

Capítulo 03 Estouro Buffer

45 02/04/14 © P C F de Oliveira 2014

² “Estourando a Heap” ² Heap contém dados alocados dinamicamente

² e.g. “new” (Java/C++) ² malloc (C)

² Dados são globais ² Incluem valores de controle de infraestrutura importantes ² Se hacker pode sobrescrever além do buffer, pode controlar outros

valores (e.g. Armazenados depois disto) ² Valores de outras estruturas ² Dados de manutenção da heap (e.g. O que livre/usado) ² Até mesmo 1 byte sobrescrito pode ser devastador

² Detalhes são dependentes do sistema ² Hackers podem explorá-los também ² Questão fundamental como estouro da pilha (stack smashing)

Capítulo 03 Estouro Buffer

46 02/04/14 © P C F de Oliveira 2014

Seção 1.6 Soluções em C

Capítulo 03 Estouro Buffer

47 02/04/14 © P C F de Oliveira 2014

Solução óbvia quando se usa C é sempre

verificar os limites dos buffers (i.e. arrays)

Entretanto...

Capítulo 03 Estouro Buffer

48 02/04/14 © P C F de Oliveira 2014

² Funções C que não verificam limites ² gets() – lê entrada sem checar – não use!!! ² strcpy() – strcpy(dest, src) copia src para dest

² Se src > dest, continua escrevendo!!!! ² strcat() – strcat(dest, src) adiciona src em dest

² Se src + dados em dest > buffer dest, continua gravando!!!

Capítulo 03 Estouro Buffer

49 02/04/14 © P C F de Oliveira 2014

² Funções C que não verificam limites ² scanf() família de funções de entrada – várias opções

perigosas ² scanf(), fscanf(), sscanf(), vscanf(), vsscanf(),

vfscanf() ² Muitas opções não controlam comprimento máximo

(e.g. “%s”) ² Outras funções perigosas

² realpath(), getopt(), getpass() ² streadd(), strecpy(), and strtrns()

² Laços (loops) também podem ocasionar estouro

Capítulo 03 Estouro Buffer

50 02/04/14 © P C F de Oliveira 2014

Seção 1.7 Medidas - Conclusões

Capítulo 03 Estouro Buffer

51 02/04/14 © P C F de Oliveira 2014

²  Estouro de Buffer pode ser devastador ²  C / C++ / Objective-C è vulneráveis ²  Tentar linguagens seguras (e.g. Java, Python)

²  Tornar a localização da pilha (stack) aleatória ²  Usar verificação em tempo de execução

²  StackGuard

²  Libsafe ²  SafeC

²  Teste da Caixa Preta (e.g. eEye Retina, ISIC)

Capítulo 03 Estouro Buffer

52 02/04/14 © P C F de Oliveira 2014

² Referências ²  Conference on Software Security : Aleph One, Smashing

the Stack for Fun and Profit. Originally published in Phrack 49-14.1996

²  IEEE Reference : Buffer Overflows: Attacks and Defenses for the Vulnerability of the Decade*

²  Pincus, Jonathan,”Beyond Stack Smashing: Recent

Advances in Exploiting Buffer Overruns”, IEEE Security&Privacy

Capítulo 03 Estouro Buffer

Texto – Fonte Arial Normal – Máx.14pt / Mín.12pt – Preto – Centralizado

53