quarta-feira, 27 de junho de 2018

Publicado quarta-feira, junho 27, 2018 por com 0 comentário

Buffer Overflow - Conceitos Básicos

Uma das vulnerabilidades de segurança mais comuns e mais antigas no software são as vulnerabilidades de buffer overflow (ou estouro de memória). As vulnerabilidades de buffer overflow ocorrem em todos os tipos de programas, desde sistemas operacionais, aplicativos cliente/servidor e programas desktops. Isso geralmente acontece devido à programação incorreta e à falta ou má validação de um programa. Neste post, será explicado o que é exatamente um buffer overflow, como eles funcionam e como podem se tornar vulnerabilidades graves. Também veremos o que acontece quando ocorre um buffer overflow e técnicas para minimizar seus efeitos prejudiciais.

O que é um estouro de buffer?

Um buffer overflow é quando um programa em execução tenta gravar dados fora do buffer da memória, ou seja, num local que não é destinado a armazenar esses dados. Quando isso acontece, estamos falando de um buffer overflow ou buffer overrun. O buffer overflow é uma área na memória do computador (memória RAM) destinada a armazenamento temporário de dados. Esse tipo de buffers pode ser encontrado em todos os programas e usado para armazenar dados de entrada, saída e processamento.

Um exemplo de dados armazenados em buffers são as credenciais de login ou o nome do host de um servidor FTP. Também outros dados armazenados temporariamente antes do processamento podem ser armazenados em buffers. Isso literalmente pode ser qualquer coisa, desde campos de entrada do usuário, como campos de nome de usuário e senha, até arquivos de entrada usados para importar determinados arquivos de configuração. Quando a quantidade de dados gravados no buffer excede a quantidade esperada de dados, o buffer de memória é estourado. Isso acontece, por exemplo, quando um nome de usuário com no máximo 8 bytes é esperado e um nome de usuário de 10 bytes é fornecido e gravado no buffer. Nesse caso, o buffer é excedido em 2 bytes e ocorrerá um estouro quando isso não for impedido. Isso geralmente acontece devido à má programação e à falta de validação na entrada.

O que acontece quando ocorre um buffer overflow?

Quando ocorre um buffer overflow na memória e os dados são gravados fora do buffer, o programa em execução pode se tornar instável, travar ou retornar informações corrompidas. As partes sobrescritas da memória podem conter outros dados importantes para o aplicativo em execução, que agora são sobrescritos e não estão mais disponíveis no programa. Os buffer overflows podem até executar outros programas ou comandos (maliciosos) e resultar na execução arbitrária de códigos.

Execução de código arbitrário e escalonamento de privilégios

A execução de código arbitrário é um processo onde é feita a injeção e execução de algum código no buffer. Quando uma vulnerabilidade de buffer overflow é usada para gravar dados mal-intencionados na memória e o invasor é capaz de assumir o controle do fluxo da execução de um programa, estamos lidando com sérios problemas de segurança. Essas vulnerabilidades de segurança podem ser explorados por hackers para obter controle (remoto) de um host, realizar o escalonamento de privilégios ou algo ainda pior com o resultado da execução arbitrária de código.

A escalação de privilégios é realizada através da exploração de uma vulnerabilidade no buffer overflow para executar algum código arbitrário em um programa que está sendo executado com privilégios de administrador. O código executado pode ser o Shellcode, que fornece ao atacante um shell do SO com privilégios administrativos. Com isso o atacante pode por exemplo adicionar um novo usuário no sistema. Também com buffer overflows o código executado acontece no contexto do aplicativo em execução. Isso significa que quando o aplicativo explorado é executado com privilégios administrativos, o código mal-intencionado também será executado com privilégios administrativos.

Negação de Serviço (DoS)

Nem todas as vulnerabilidades de buffer overflow podem ser exploradas para obter execução de código arbitrário. Além disso, ataques (remotos) de negação de serviço podem ser executados quando eles apenas travam o programa em execução. Como o buffer estoura, as vulnerabilidades podem aparecer em qualquer software, e com isso os ataques DoS não se limitam apenas a serviços e computadores, mas também roteadores, firewalls, dispositivos IoT e qualquer outra coisa que execute um sistema operacional. Um exemplo dessa situação é o recente recente estouro de buffer do Cisco ASA IKEv1 e IKEv2 Buffer Overflow. Algumas dessas explorações remotas apenas travam e forçam a reinicialização do firewall, resultando em inatividade por alguns minutos.

Como evitar que os buffer overflows aconteçam?

Os estouros de buffer no software podem ser evitados ou solucionado de várias maneiras. A mitigação é uma dessas soluções, onde o processo de minimizar o impacto de uma ameaça acontece antes ou depois da ocorrência da ameaça. Eles podem ser impedidos de acontecer antes de ocorrerem (proativos). Mas, como os estouro de buffer continuam ocorrendo, apesar das ações tomadas proativamente para evitá-los, também precisamos de mecanismos para minimizar o impacto quando eles ocorrem (contramedidas reativas). Vamos dar uma olhada em como funciona a prevenção e a atenuação do buffer overflow.

Prevenção de buffer overflows

A melhor e mais eficaz solução é impedir que ocorram condições de buffer overflow no código. Por exemplo, quando temos uma entrada de dados com no máximo 8 bytes então devemos limitar os dados gravados no buffer, para que não ultrapasse 8 bytes. Além disso, os programadores devem usar as funções de depuração para testar o código e corrigir os erros antes da finalização do programa. Métodos proativos para prevenção de estouro de buffer como esses devem ser usados sempre que possível para limitar vulnerabilidades de buffer overflow.

Mitigação de buffer overflows

Outra maneira de evitar os buffer overflows é detectá-los à medida que ocorrem e mitigar a situação. Esta é uma abordagem reativa e se concentra em minimizar o impacto prejudicial. Um exemplo de mitigação eficaz é um sistema operacional moderno que protege certas áreas de memória de serem gravadas ou executadas. Isso poderia impedir que um invasor grave um código arbitrário na memória quando ocorrer o buffer overflow. Implementações de proteção de espaço e ponteiro executável tentam minimizar o impacto negativo de um estouro de buffer. Isso não impede que ocorra o buffer overflow, mas minimiza o impacto.

Outra maneira de detecção do buffer overflow é usar sistemas de detecção de intrusão (IDS) para analisar o tráfego de rede. Um IDS é capaz de detectar assinaturas no tráfego de rede que são conhecidas por explorar vulnerabilidades de buffer overflow. O IDS pode, então, mitigar o ataque e impedir que a carga útil seja executada no sistema operacional.

Como funciona um buffer overflow no código?

Vamos dar uma olhada em como um buffer overflow realmente funciona, observando o código do programa. Nós explicamos este processo usando uma função muito conhecida e vulnerável ao buffer overflow: a função strcpy() na linguagem C. Essa função usa 2 ponteiros como parâmetros, a fonte que aponta para a matriz de origem para copiar e o ponteiro de destino para a matriz de caracteres para gravar. Quando a função é executada, a matriz de origem dos caracteres será copiada para a matriz de destino e não terá uma verificação dos limites quando isso ocorrer. Quando o buffer de origem é maior que o buffer de destino, acontecerá um buffer overflow.

Estouro de buffer com strcpy

A imagem a seguir é um exemplo da função strcpy() fazendo cópia de um valor que está ultrapassando o buffer de destino. 


Abaixo está o código com vulnerabilidade:


Neste exemplo, o buffer está sendo estourado com 2 bytes contendo um inofensivo 1 e 2. Como a função strcpy não realiza uma verificação de limites, podemos escrever qualquer coisa fora do espaço do buffer. Isso também pode se aplicar a um código malicioso, como o shellcode. Futuramente mostrarei mais detalhadamente como fazer o buffer overflow com shellcode. Também aprenderemos como controlar o fluxo de execução de um programa e executar o código de shell malicioso fora do buffer.

Conclusão

Aprendemos que um buffer overflow é causado por determinadas condições em que um programa em execução está gravando dados fora do buffer de memória. Ao injetar código (shell) e redirecionar o fluxo de execução de um programa em execução para esse código, um invasor pode executar esse código facilmente. Isso é chamado de execução de código arbitrário. Com a execução de código arbitrário, um invasor pode obter controle (remoto) de um alvo específico, elevar privilégios ou causar uma negação de serviço no alvo.

Os estouros de buffers podem ser preventivamente evitados e mitigados com várias técnicas. Os programadores devem depurar seus código e testá-lo a fim de evitar os buffer overflows.  Quando esse tipo de vulnerabilidade não é impedida, ela ainda pode ser mitigada com métodos reativos, como a proteção da memória contra gravação.

      edit

0 comentários:

Postar um comentário