1. UNIVERSIDADE ANTÓNIO AGOSTINHO NETO
FACULDADE DE CIÊNCIAS
DEPARTAMENTO DE CIÊNCIA DA COMPUTAÇÃO
BUFFER OVERFLOWS
(TRANSBORDAMENTO DE DADOS)
CADEIRA: TÓPICOS AVANÇADOS DA COMPUTAÇÃO
3. AGENDA
CONTEXTO HISTÓRICO
01. RESUMO, DE HISTORIA
SOBRE BUFFER
OVERFLOWS.
BUFFER
02. SOBRE BUFFER.
OVERFLOW
03. • BUFFER OVERFLOW
(VISÃO GERAL)
A ESTRUTURA DE UM PROGRAMA
NA MOMÓRIA
04. • HEAP BASED BUFFER
OVERFLOW
• RETURN TO LIBC
ATTACK
• STACK BASED BUFFER
OVERFLOW
4. • Buffer Overflows foram entendidos por volta de 1972, quando o Computer
Security Technology Planning Study (documento de planejamento de
estudos da USAF) definiu a técnica como o seguinte:
“Um código realizando tal função não checa os endereços de fonte e destino
apropriadamente, permitindo que partes do monitor sejam superpostas pelo
usuário. Isso pode ser usado para injetar códigos no monitor que irão permitir o
usuário a tomar o controle da máquina.”
• Em 1995, Thomas Lopatic redescobriu sozinho o buffer overflow e publicou
seus achados na lista de emails da Bugtraq. Um ano depois, Elias Levy
(Também conhecido como Aleph One), publicou na revista Phrack, o artigo
“Smashing the Stack for Fun and Profit” (Arrasando a Pilha por Diversão e
Lucro), uma introdução passo-a-passo para realizar um stackbased buffer
overflow.
CONTEXTO HISTÓRICO
5. • Hoje em dia, o monitor, poderia ser referido como o kernel.
• A documentação mais antiga de Buffer Overflow data de 1988. Foi
uma das muitas vulnerabilidades exploradas pelo Morris worm para
se propagar pela internet.
CONTEXTO HISTÓRICO
6. Em computação, um buffer é uma região
temporária da memória onde são guardados
dados para serem transportados de um lugar
para o outro. Uma aplicação frequente de um
buffer ´e quando dados são capturados de um
dispositivo de entrada (um teclado ou mouse,
por exemplo) e enviados a um dispositivo de
saída(monitor, impressora).
BUFFER - O QUE É?
8. O conceito básico de um overflow é um
transbordamento, ou seja, um overflow ocorre
quando o volume de determinado objeto ou
substância é maior do que a capacidade de seu
compartimento.
OVERFLOW?
10. O buffer overflow é um erro de programação que
pode resultar em execução errônea de um programa,
acesso indevido a áreas de memória, terminação do
programa ou uma possível falha de segurança em
um sistema.
Tecnicamente falando, um buffer overflow consiste
em um processo de armazenar, em um buffer de
tamanho fixo, dados maiores que o seu tamanho.
BUFFER OVERFLOW - UMA VISÃO GERAL
11. Imagine que um programa declara duas estruturas de dados
adjacentes na memória do computador: um vetor de caracteres
de 8 bytes, A, e um inteiro de 2 bytes, B, enche A de zeros e B
recebe o número 3, como no seguinte esquema:
COMO FUNCIONA?
12. A palavra excessivo tem 9 letras, consequentemente, 10
caracteres, pois um caractere nulo é concatenado ao final
para indicar o fim de uma string (vetor de caracteres).
Separando a palavra em caracteres seria algo como: 'e', 'x',
'c', 'e', 's', 's', 'i', 'v', 'o',‘0', sendo o '0' o caractere nulo, que
consiste em um um byte zerado.
Sabendo que cada caractere ocupa um byte, a string A,
então, tem apenas 8 bytes, porém estamos inserindo 10
bytes, que é um tamanho maior do que A comporta.
COMO FUNCIONA?
13. Exploits são pedaços de código, sequências de comandos,
ou até mesmo programas que se aproveitam de
vulnerabilidades ou bugs em softwares, visando causar
comportamento errôneo, inesperado ou até mesmo
ganhar acesso privilegiado a um sistema.
A maioria dos Exploits visa ganhar acesso de nível de
superusuario á sistemas ou derrubar os mesmos. Pode-se
fazer uso de vários exploits diferentes para galgar níveis de
acesso ate chegar ao superusuario.
EXPLOITS E TIPOS DE ATAQUES BASEADOS EM BUFFER OVERFLOW
14. Os tipos mais comuns de ataques baseado
em buffer overflow são:
Stack based buffer overflow
Return To libc Attack
Heap based buffer overflow
TIPOS DE ATAQUES BASEADOS EM BUFFER OVERFLOW
15. Qualquer programa compilado (e isto inclui
interpretadores de linguagens) possui uma forma
estruturada em código de máquina denotando uma
sequência de instruções que serão executadas pelo
processador.
Tal sequência é carregada na memória quando um
programa é chamado á execução.
A estrutura de um programa na memoria se divide em
quatro partes: texto, dados, stack (pilha) e heap.
A ESTRUTURA DE UM PROGRAMA NA MEMÓRIA
16. A região do texto contém as instruções do programa propriamente
ditas e dados somente-leitura. Essa região é geralmente somente-
leitura, para evitar códigos mutáveis. Uma tentativa de escrita nessa
área resulta em uma falha de segmentação.
A região dos dados contém todas as variáveis globais e estáticas do
programa.
A região de heap serve para a alocação dinâmica de variáveis, através de
instruções do tipo malloc();
A pilha é a região mais interessante para os fins deste texto. Trata-se de
um bloco de memória onde são armazenadas informações vitais para
sub-rotinas: variáveis locais, parâmetros e os valores de retorno.
A ESTRUTURA DE UM PROGRAMA NA MEMÓRIA
18. Qualquer programa compilado (e isto inclui interpretadores de
linguagens) possui uma forma estruturada em código de máquina
denotando uma sequência de instrucoes que serão executadas pelo
processador. Tal sequencia é carregada na memória quando um
programa é chamado à execução.
o processador lê uma série de instruções. Tais que são referenciadas por
bytes. Com este conhecimento, podemos então ao invés de
escrevermos um nome, poderíamos enviar um endereço de memória
onde um código previamente inserido possa ser executado. O código
inserido é normalmente chamado de shellcode.
STACK-BASED BUFFER OVERFLOW
19. Este é um tipo muito mais difícil de ser explorado devido ao fato do alvo ser a heap.
Entre as dificuldades estão:
1. Na heap, não existem valores os quais o processador usa para saber qual a
próxima operação a executar, apenas valores de organização do próprio heap.
2. Devido ao fato do heap crescer em direção aos valores maiores da memória e
podermos apenas escrever nesta mesma direção, não é possível reescrever os
valores de controle do bloco atual, apenas dos blocos posteriores.
3. Como a organização da heap pode variar, o atacante precisa saber qual é a
implementação de heap do programa-alvo.
Para explorar um buffer overflow na heap é necessário encontrar uma
vulnerabilidade em alguma função interna de administração da heap, de modo que
esta processe o buffer alvo na heap. Deste modo:
4. Precisamos explorar a heap para sobrescrever os valores de administração de
um bloco alvo e assim inserir o shellcode, construindo um bloco malicioso na heap.
HEAP-BASED BUFFER OVERFLOW
20. Uma das defesas para um ataque de buffer overflow baseado em pilha é
não dar permissão de execucão na pilha. Deste modo, não é possivel
tentar executar um shellcode na pilha. Existe uma alternativa, que é
explorar um código que já existe nas rotinas do programa.
Um código que está em quase qualquer coisa(incluindo o sistema
operacional), são os códigos da libc, a biblioteca padrão do C. Além de
estarem presentes na maioria dos sistemas, eles possuem uma posição
estática na memória em um sistema.
RETURN-TO-LIBC ATTACK