Quando se começa a falar sobre segurança de aplicações uma das primeiras vulnerabilidades que o desenvolvedor conhece é o Buffer Overflow.
Embora o Buffer Overflow seja uma vulnerabilidade presente no cenário de segurança desde seu início, ele se faz presente nas aplicações até os dias de hoje.
É mais comum encontrar o Buffer Overflow em linguagens como C e C++, onde há a necessidade de uma definição prévia do tamanho do buffer de memória a ser usado.
Mas temos outros exemplos da ocorrência de Buffer Overflow em de outras linguagens, como por exemplo a que acontece no PHP.
A correção do BUG 77370, por exemplo, resolveu um problema de buffer overflow em uma função chamada mb_regex do PHP, mostrando que o cuidado não deve ser somente com linguagens específicas.
Portanto, neste artigo vamos falar um pouco sobre o que é o Buffer Overflow: como ele impacta a aplicação e como podemos resolver este problema.
O que é Buffer Overflow?
Durante o desenvolvimento de uma aplicação, muitos aspectos precisam ser pensados.
Caso você esteja desenvolvendo em C ou C++, uma das coisas que você vai precisar pensar é no tamanho do buffer de memória que será reservado para receber e usar dados de sua aplicação.
Então, ao determinar o tamanho de um buffer, o desenvolvedor está determinando também o espaço disponível para o armazenamento de cada dado.
Mas às vezes esse tamanho é transmitido de forma equivocada, de forma inadvertida ou mesmo de forma maliciosa.
Quando um desenvolvedor determina o tamanho de um buffer de memória por meio de dados, este buffer pode receber mais dados do que inicialmente estava planejado.
Isso gera um excedente, e esse excedente precisa ir para algum lugar.
Então, os dados que excedem a quantidade esperada em um buffer são direcionados a espaços de memória subjacentes, e isso muitas vezes é explorado como vulnerabilidade.
Conceitualmente o Buffer Overflow é uma vulnerabilidade muito fácil de ser entendida. E pode ser bem exemplificado com uma simples xícara de café.

Quando colocamos mais café em uma xícara do que ela comporta, o excedente precisa ir para algum lugar – no nosso exemplo, este lugar é o pires.
Portanto, quando esse excesso de dados é gravados fora da área esperada, o sistema pode executar o que foi registrado.
E se esse excesso de dados for um comando, ao ser executado ele pode comprometer o sistema.
Buffer Overflow no armazenamento e envio de dados entre diferentes aplicações
Este tipo de falha pode acontecer com uma grande quantidade de aplicações, e pode ser algo simples, como, por exemplo, dados que serão enviados a uma impressora.
Quando enviamos um arquivo para ser impresso, por exemplo, estamos lidando com dois equipamentos que possuem processamentos bem diferentes.
Isso porque sua impressora não tem o mesmo poder de processamento que seu computador, então precisamos de um espaço em memória para guardar os dados que serão enviados para a impressora.
Então, este espaço armazenará os dados e os enviará no tempo da impressora.
No entanto, esse espaço pode acabar corrompido, fazendo com que sejam colocados mais dados do que a impressora pode comportar.
Isso pode gerar comandos, e sua aplicação ou mesmo o Sistema Operacional podem acabar executando esses comandos.
Outro exemplo que podemos citar é quando usamos um campo com tamanho definido para receber o nome de usuário (username) em um formulário de autenticação.

Imagine então que em sua aplicação o campo destinado a receber o nome de seus usuário foi determinado com o tamanho de 10 bytes e, durante um ataque, o atacante insere no campo um dado de 12 bytes.
Quando acontece esse tipo de ataque, o excedente será armazenado fora do buffer determinado e pode ser executado como um comando.
Portanto, essa é claramente uma falha na validação dos dados que foram inseridos pelo usuário.
O que pode acontecer quando existe o Buffer Overflow?
Caso ocorra a exploração de uma vulnerabilidade de buffer overflow, sua aplicação pode ficar instável, parar ou pode ainda retornar com algumas informações do erro.
Já em outros casos, os dados que foram gravados fora do espaço reservado podem conter comandos maliciosos, e quando estes não são devidamente tratados, serão executados.
Essa execução pode trazer uma infinidade de problemas para a segurança de sua aplicação.
Portanto, a seguir vamos falar sobre alguns exemplos do que pode acontecer quando um buffer overflow está presente na aplicação.
1. Execução de código arbitrária e escalação de privilégios
Quando um atacante consegue enviar códigos maliciosos para explorar uma vulnerabilidade de buffer overflow e é bem sucedido, temos um sério problema de segurança na aplicação.
Isso porque ao explorar esse tipo de vulnerabilidade, um atacante pode tomar o controle de uma aplicação, enviando comandos a serem executados.
Esse envio de comando é chamado “execução arbitrária de código”, e acontece quando se injeta código dentro de um buffer e este é executado.
Quando a aplicação está sendo executada em um sistema operacional com privilégios de sistema, esta vulnerabilidade pode ser explorada para que o atacante realize uma ação chamada “elevação de privilégios”.
E, caso o ataque seja bem sucedido, o atacante receberá uma shellcode do sistema com os privilégios do usuário que esteja executando a aplicação.
Se este for o administrador ou o root, os privilégios destes usuários serão transferidos para o atacante.
2. Negação de Serviço ou DoS (Denial of Service)
Nem só de execução de código vive um Buffer Overflow!
E nem toda vulnerabilidade de Buffer Overflow pode ser explorada para a execução de um código arbitrário.
Então, quando não for possível executar um código, o atacante pode lançar mão de ataques de Negação de Serviço via Buffer Overflow.
Como uma vulnerabilidade de Buffer Overflow pode acontecer em qualquer software — independente deste software ser uma aplicação web ou um sistema de roteamento — outros serviços podem sofrer este ataque.
Sistemas de roteadores, switches, firewall e até mesmo IoT podem ter essas vulnerabilidades.
Inclusive, isso pode ser uma fonte incrível de equipamentos para executar outros ataques, como o descrito aqui, onde milhões de equipamentos vulneráveis foram utilizados para executar um ataque de DDoS.
Outro bom exemplo é a exploração de uma falha em roteadores CISCO, que permitiu que vários equipamentos fossem sobrecarregados, deixando-os inoperantes, o que resultou na paralisação de algumas redes.
Essas paradas podem ser simples e rápidas mas também podem ser duradouras, levando a prejuízos e uso indevido de recursos computacionais.
Como evitar as falhas de Buffer Overflow
A ocorrência de vulnerabilidades de Buffer Overflow pode ser evitada de diversas formas em software.
E há duas formas básicas de tratar uma vulnerabilidade dentro do processo de desenvolvimento. A primeira, e mais básica, é trabalhar de forma proativa.
Mas, como ainda estamos enfrentando as vulnerabilidades, nos parece que somente a abordagem proativa não tem funcionado.
Então, podemos dizer que o segundo modo de prevenir as vulnerabilidades seja atuar de forma reativa, trabalhando contramedidas dentro do código para impedir que as vulnerabilidades sejam exploradas.
Vamos detalhar mais um pouco estes dois cenários a seguir.
1. Prevenção proativa
A melhor e mais efetiva forma de prevenir que aconteça uma vulnerabilidade de Buffer Overflow é no próprio código.
Então vamos supor que seu programa receba, em um campo, um dado de 8 bytes. Tendo isso como parâmetro e sabendo desta limitação, seu código deve garantir que somente esses 8 bytes sejam aceitos em seu campo determinado.
O controle desses campos de entrada garante que não haja uma vazamento de dados excedentes.
Além disso, ações proativas dentro do processo de desenvolvimento devem ser aplicadas.
Dessa forma, acontece a revisão e validação de códigos sendo desenvolvidos, garantindo que o código esteja sempre sendo revalidado.
Este processo de constante validação garante não somente que vulnerabilidades de Buffer Overflow estejam presentes no código, mas também outras vulnerabilidades.
Tomando ações proativamente, o desenvolvedor garante que seu código seja criado e mantido da melhor forma possível.
2. Prevenção Reativa
Atuar de forma reativa quer dizer que a ação de correção ou de mitigação da vulnerabilidade acontece após a descoberta da vulnerabilidade.
Um exemplo dessa prevenção são os sistemas operacionais que possuem uma proteção para áreas de memória.
Eles controlam o acesso a essas áreas de memória, e evitando que dados registrados fora delas sejam executados.
Outro método que pode ser usado com o objetivo de reduzir o impacto é a implementação de DEP, ASLR ou mesmo SEHOP.
A proteção de ponteiros também pode ser usado como uma medida reativa à vulnerabilidade.
Então, esse tipo de de proteção vai evitar que atacantes consigam escrever e executar códigos dentro dessas regiões, minimizando o impacto.
Uma outra forma ainda mais externa a aplicação é o uso de um sistema de detecção de intrusos (IDS), que irá monitorar a rede por assinaturas de ataques conhecidos.
No entanto, é importante ressaltar que essas ações são paliativas e reativas, não devendo substituir processos de desenvolvimento seguro em si, com a realização de etapas bem planejadas de revisão de código.
Portanto, o que irá realmente garantir que sua aplicação esteja livre destas vulnerabilidades é a realização de revisões de código periódicas.
O que concluímos?
Neste artigo entregamos uma explicação básica e de forma simples do que vem a ser uma vulnerabilidade de Buffer Overflow.
Descrevemos então o que é e como o Buffer Overflow pode acontecer em sua aplicação, e como podemos mitigar esta vulnerabilidade tanto reativa quanto proativamente.
Acreditamos que, como em qualquer outra vulnerabilidade, a busca por melhorias de código, validações constantes e um processo de desenvolvimento seguro bem implementado é o que realmente garante que o código esteja livre de vulnerabilidades.
Portanto, continuamos defendendo que a forma mais eficaz de reduzir as vulnerabilidades é a atuação de desenvolvedores realizando revisões de códigos de forma manual.
Então, buscar se manter atualizado por meio de treinamentos, conhecendo as melhores práticas e sempre entendendo o real impacto de uma vulnerabilidade, é o que vai manter o desenvolvedor sempre atento ao seu resultado.
Veja também nosso artigo sobre Por que Investir em Treinamentos de AppSec.
Esperamos com isso ter contribuído um pouco mais para um resultado positivo.
