Estouro de buffer
Em segurança da informação e programação, um estouro de buffer, ou saturação de buffer, é uma anomalia em que um programa, ao gravar dados em um buffer, ultrapassa o buffer's limite e sobrescreve os locais de memória adjacentes.
Os buffers são áreas de memória reservadas para armazenar dados, geralmente durante a movimentação de uma seção de um programa para outra ou entre programas. Estouros de buffer geralmente podem ser acionados por entradas malformadas; se alguém assumir que todas as entradas serão menores que um determinado tamanho e o buffer for criado para ter esse tamanho, uma transação anômala que produza mais dados poderá fazer com que ela grave além do final do buffer. Se isso sobrescrever dados adjacentes ou código executável, isso pode resultar em um comportamento errático do programa, incluindo erros de acesso à memória, resultados incorretos e travamentos.
Explorar o comportamento de um estouro de buffer é uma exploração de segurança bem conhecida. Em muitos sistemas, o layout da memória de um programa ou do sistema como um todo é bem definido. Ao enviar dados projetados para causar um estouro de buffer, é possível gravar em áreas conhecidas por conter código executável e substituí-lo por código malicioso, ou sobrescrever seletivamente dados pertencentes ao estado do programa, causando assim um comportamento que foi não pretendido pelo programador original. Os buffers são amplamente difundidos no código do sistema operacional (SO), portanto, é possível fazer ataques que realizam escalonamento de privilégios e obtêm acesso ilimitado aos recursos do computador. O famoso worm Morris em 1988 usou isso como uma de suas técnicas de ataque.
As linguagens de programação comumente associadas a estouros de buffer incluem C e C++, que não fornecem proteção integrada contra acesso ou substituição de dados em qualquer parte da memória e não verificam automaticamente se os dados gravados em uma matriz (o tipo de buffer integrado) está dentro dos limites dessa matriz. A verificação de limites pode evitar estouros de buffer, mas requer código adicional e tempo de processamento. Os sistemas operacionais modernos usam uma variedade de técnicas para combater estouros de buffer maliciosos, principalmente randomizando o layout da memória ou deixando espaço deliberadamente entre os buffers e procurando ações que gravam nessas áreas ("canários").
Descrição técnica
Um estouro de buffer ocorre quando os dados gravados em um buffer também corrompem os valores dos dados nos endereços de memória adjacentes ao buffer de destino devido à verificação de limites insuficiente. Isso pode ocorrer ao copiar dados de um buffer para outro sem primeiro verificar se os dados cabem no buffer de destino.
Exemplo
No exemplo a seguir, expresso em C, um programa tem duas variáveis que são adjacentes na memória: um buffer de string de 8 bytes, A, e um inteiro big-endian de dois bytes, B.
Charlie. ANão.8] = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ";não assinado curto B = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1979;
Inicialmente, A não contém nada além de zero bytes e B contém o número 1979.
nome variável | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
valor | [null string] | 1979 | ||||||||
valor de hex | 00:00 | 00:00 | 00:00 | 00:00 | 00:00 | 00:00 | 00:00 | 00:00 | 07 | BB |
Agora, o programa tenta armazenar a string terminada em nulo "excessivo"
com codificação ASCII no buffer A.
Estranho(A, "excessivo");
"excessivo"
tem 9 caracteres e codifica para 10 bytes, incluindo o terminador nulo, mas A pode levar apenas 8 bytes. Ao não verificar o comprimento da string, ele também sobrescreve o valor de B:
nome variável | A | B | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
valor | " ' | "x" ' | C ' | " ' | ' ' | ' ' | Eu... ' | V ' | 25856 | |
Hex | 65 | 78 | 63 | 65 | 73 | 73 | 69 | 76 | 65 | 00:00 |
O valor de B agora foi inadvertidamente substituído por um número formado por parte da cadeia de caracteres. Neste exemplo, "e" seguido por um byte zero se tornaria 25856.
A gravação de dados após o fim da memória alocada pode, às vezes, ser detectada pelo sistema operacional para gerar um erro de falha de segmentação que encerra o processo.
Para evitar que o estouro do buffer aconteça neste exemplo, a chamada para strcpy pode ser substituída por strlcpy, que leva a capacidade máxima de A (incluindo um valor nulo caractere de terminação) como um parâmetro adicional e garante que não mais do que esta quantidade de dados seja gravada em A:
Estranho(A, "excessivo", tamanho de(A));
Quando disponível, a função de biblioteca strlcpy é preferível a strncpy, que não encerra o buffer de destino com valor nulo se o comprimento da string de origem for maior que ou igual ao tamanho do buffer (o terceiro argumento passado para a função), portanto, A não pode ser terminado em nulo e não pode ser tratado como uma string válida no estilo C.
Exploração
As técnicas para explorar uma vulnerabilidade de estouro de buffer variam de acordo com a arquitetura, o sistema operacional e a região da memória. Por exemplo, a exploração no heap (usado para memória alocada dinamicamente) difere marcadamente da exploração na pilha de chamadas. Em geral, a exploração de heap depende do gerenciador de heap usado no sistema de destino, a exploração de pilha depende da convenção de chamada usada pela arquitetura e pelo compilador.
Exploração baseada em pilha
Um usuário tecnicamente inclinado pode explorar estouros de buffer baseados em pilha para manipular o programa a seu favor de várias maneiras:
- Ao substituir uma variável local localizada perto do buffer vulnerável na pilha, a fim de alterar o comportamento do programa
- Ao substituir o endereço de retorno em um frame de pilha para apontar para o código selecionado pelo atacante, geralmente chamado de shellcode. Uma vez que a função retorna, a execução será retomada no shellcode do atacante.
- Ao substituir um ponteiro de função ou manipulador de exceção para apontar para o shellcode, que é executado posteriormente
- Ao substituir uma variável local (ou ponteiro) de um quadro de pilha diferente, que será usado pela função que possui esse quadro mais tarde.
O invasor projeta dados para causar uma dessas explorações e, em seguida, coloca esses dados em um buffer fornecido aos usuários pelo código vulnerável. Se o endereço dos dados fornecidos pelo usuário usados para afetar o estouro do buffer de pilha for imprevisível, explorar um estouro de buffer de pilha para causar a execução remota de código torna-se muito mais difícil. Uma técnica que pode ser usada para explorar esse estouro de buffer é chamada de "trampolining". Nessa técnica, um invasor encontrará um ponteiro para o buffer de pilha vulnerável e calculará a localização de seu shellcode em relação a esse ponteiro. Então, eles usarão o overwrite para pular para uma instrução já na memória que fará um segundo salto, desta vez relativo ao ponteiro; esse segundo salto ramificará a execução para o shellcode. Instruções adequadas geralmente estão presentes em código grande. O Projeto Metasploit, por exemplo, mantém um banco de dados de opcodes adequados, embora liste apenas aqueles encontrados no sistema operacional Windows.
Exploração baseada em heap
Um estouro de buffer que ocorre na área de dados do heap é chamado de estouro de heap e é explorável de uma maneira diferente dos estouros baseados em pilha. A memória no heap é alocada dinamicamente pelo aplicativo em tempo de execução e geralmente contém dados do programa. A exploração é executada corrompendo esses dados de maneiras específicas para fazer com que o aplicativo sobrescreva estruturas internas, como ponteiros de lista vinculada. A técnica de estouro de heap canônico sobrescreve a vinculação de alocação de memória dinâmica (como metadados malloc) e usa a troca de ponteiro resultante para sobrescrever um ponteiro de função de programa.
A vulnerabilidade GDI+ da Microsoft no manuseio de JPEGs é um exemplo do perigo que um estouro de heap pode representar.
Barreiras à exploração
A manipulação do buffer, que ocorre antes de sua leitura ou execução, pode levar ao fracasso de uma tentativa de exploração. Essas manipulações podem atenuar a ameaça de exploração, mas não podem torná-la impossível. As manipulações podem incluir conversão para letras maiúsculas ou minúsculas, remoção de metacaracteres e filtragem de strings não alfanuméricas. No entanto, existem técnicas para contornar esses filtros e manipulações; shellcode alfanumérico, código polimórfico, código auto-modificável e ataques return-to-libc. Os mesmos métodos podem ser usados para evitar a detecção por sistemas de detecção de intrusão. Em alguns casos, incluindo onde o código é convertido em Unicode, a ameaça da vulnerabilidade foi deturpada pelos divulgadores como apenas negação de serviço quando, na verdade, a execução remota de código arbitrário é possível.
Práticas de exploração
Nas explorações do mundo real, há uma variedade de desafios que precisam ser superados para que as explorações operem de forma confiável. Esses fatores incluem bytes nulos em endereços, variabilidade na localização do shellcode, diferenças entre ambientes e várias contra-medidas em operação.
Técnica de trenó NOP
Um NOP-sled é a técnica mais antiga e amplamente conhecida para explorar estouros de buffer de pilha. Ele resolve o problema de encontrar o endereço exato do buffer aumentando efetivamente o tamanho da área de destino. Para fazer isso, seções muito maiores da pilha são corrompidas com a instrução de máquina no-op. No final dos dados fornecidos pelo invasor, após as instruções no-op, o invasor coloca uma instrução para executar um salto relativo para o topo do buffer onde o shellcode está localizado. Essa coleção de no-ops é chamada de "NOP-sled" porque se o endereço de retorno for substituído por qualquer endereço dentro da região não operacional do buffer, a execução "deslizará" desative o no-ops até que seja redirecionado para o código malicioso real pelo salto no final. Essa técnica exige que o invasor adivinhe onde está o trenó NOP na pilha, em vez do shellcode comparativamente pequeno.
Devido à popularidade dessa técnica, muitos fornecedores de sistemas de prevenção de invasões procurarão esse padrão de instruções de máquina não operacional na tentativa de detectar o shellcode em uso. É importante observar que um NOP-sled não contém necessariamente apenas instruções tradicionais de máquinas no-op; qualquer instrução que não corrompa o estado da máquina a um ponto em que o shellcode não será executado pode ser usada no lugar do no-op assistido por hardware. Como resultado, tornou-se uma prática comum para os criadores de exploits compor o sled no-op com instruções escolhidas aleatoriamente que não terão nenhum efeito real na execução do shellcode.
Embora esse método melhore muito as chances de um ataque ser bem-sucedido, ele não é isento de problemas. Os exploits que usam essa técnica ainda devem contar com alguma sorte para adivinhar as compensações na pilha que estão dentro da região do trenó NOP. Uma suposição incorreta geralmente resultará na falha do programa de destino e poderá alertar o administrador do sistema sobre as atividades do invasor. Outro problema é que o trenó NOP requer uma quantidade muito maior de memória para manter um trenó NOP grande o suficiente para ser útil. Isso pode ser um problema quando o tamanho alocado do buffer afetado é muito pequeno e a profundidade atual da pilha é rasa (ou seja, não há muito espaço do final do quadro de pilha atual até o início da pilha). Apesar de seus problemas, o NOP-sled costuma ser o único método que funcionará para uma determinada plataforma, ambiente ou situação e, como tal, ainda é uma técnica importante.
O salto para o endereço armazenado em uma técnica de registro
O "pular para registrar" A técnica permite a exploração confiável de estouros de buffer de pilha sem a necessidade de espaço extra para um NOP-sled e sem ter que adivinhar os deslocamentos de pilha. A estratégia é sobrescrever o ponteiro de retorno com algo que fará com que o programa salte para um ponteiro conhecido armazenado em um registrador que aponta para o buffer controlado e, portanto, para o shellcode. Por exemplo, se o registrador A contiver um ponteiro para o início de um buffer, qualquer salto ou chamada que tome esse registrador como um operando pode ser usado para obter o controle do fluxo de execução.
Na prática, um programa pode não conter intencionalmente instruções para pular para um registrador específico. A solução tradicional é encontrar uma instância não intencional de um opcode adequado em um local fixo em algum lugar da memória do programa. Na figura E à esquerda está um exemplo de uma instância não intencional da instrução i386 jmp esp
. O opcode para esta instrução é FF E4
. Esta sequência de dois bytes pode ser encontrada em um deslocamento de um byte desde o início da instrução call DbgPrint
no endereço 0x7C941EED
. Se um invasor substituir o endereço de retorno do programa por este endereço, o programa primeiro pulará para 0x7C941EED
, interpretará o opcode FF E4
como a instrução jmp esp
, e então pulará para o topo da pilha e executará o código do invasor.
Quando esta técnica é possível, a gravidade da vulnerabilidade aumenta consideravelmente. Isso ocorre porque a exploração funcionará de maneira confiável o suficiente para automatizar um ataque com uma garantia virtual de sucesso quando for executado. Por esse motivo, essa é a técnica mais comumente usada em worms da Internet que exploram vulnerabilidades de estouro de buffer de pilha.
Este método também permite que o shellcode seja colocado após o endereço de retorno substituído na plataforma Windows. Como os executáveis são baseados principalmente no endereço 0x00400000
e x86 é uma arquitetura Little Endian, o último byte do endereço de retorno deve ser nulo, o que encerra a cópia do buffer e nada é gravado além disso. Isso limita o tamanho do shellcode ao tamanho do buffer, que pode ser excessivamente restritivo. As DLLs estão localizadas em alta memória (acima de 0x01000000
) e, portanto, têm endereços que não contêm bytes nulos, portanto, esse método pode remover bytes nulos (ou outros caracteres não permitidos) do endereço de retorno substituído. Usado dessa maneira, o método geralmente é chamado de "trampolim DLL".
Contramedidas de proteção
Várias técnicas têm sido usadas para detectar ou prevenir estouros de buffer, com várias compensações. As seções a seguir descrevem as opções e implementações disponíveis.
Escolha da linguagem de programação
Assembly, C e C++ são linguagens de programação populares que são vulneráveis ao estouro de buffer em parte porque permitem acesso direto à memória e não são fortemente tipadas. C não oferece proteção interna contra acesso ou substituição de dados em qualquer parte da memória; mais especificamente, ele não verifica se os dados gravados em um buffer estão dentro dos limites desse buffer. As bibliotecas C++ padrão fornecem muitas maneiras de armazenar dados em buffer com segurança, e a Standard Template Library (STL) do C++ fornece contêineres que podem, opcionalmente, executar verificações de limites se o programador solicitar verificações explicitamente ao acessar os dados. Por exemplo, a função de membro at()
de um vetor
realiza uma verificação de limites e lança uma exceção out_of_range
se a verificação de limites falhar. No entanto, C++ se comporta exatamente como C se a verificação de limites não for chamada explicitamente. Técnicas para evitar estouros de buffer também existem para C.
As linguagens fortemente tipadas e que não permitem acesso direto à memória, como COBOL, Java, Python e outras, impedem a ocorrência de estouro de buffer na maioria dos casos. Muitas linguagens de programação diferentes de C ou C++ fornecem verificação de tempo de execução e, em alguns casos, até verificação de tempo de compilação, o que pode enviar um aviso ou gerar uma exceção quando C ou C++ sobrescrever dados e continuar a executar instruções adicionais até que sejam obtidos resultados errôneos que podem ou pode não causar a falha do programa. Exemplos de tais linguagens incluem Ada, Eiffel, Lisp, Modula-2, Smalltalk, OCaml e derivados de C como Cyclone, Rust e D. Os ambientes de bytecode Java e.NET Framework também requerem verificação de limites em todos os arrays. Quase toda linguagem interpretada protegerá contra estouros de buffer, sinalizando uma condição de erro bem definida. Muitas vezes, quando um idioma fornece informações de tipo suficientes para fazer a verificação de limites, é fornecida uma opção para ativá-lo ou desativá-lo. A análise de código estático pode remover muitas verificações dinâmicas de ligação e tipo, mas implementações ruins e casos estranhos podem diminuir significativamente o desempenho. Os engenheiros de software devem considerar cuidadosamente as compensações de segurança versus custos de desempenho ao decidir qual linguagem e configuração de compilador usar.
Uso de bibliotecas seguras
O problema de buffer overflows é comum nas linguagens C e C++ porque elas expõem detalhes representacionais de baixo nível de buffers como contêineres para tipos de dados. Os estouros de buffer devem, portanto, ser evitados mantendo um alto grau de correção no código que executa o gerenciamento de buffer. Também há muito tempo é recomendado evitar as funções de biblioteca padrão que não têm limites verificados, como gets
, scanf
e strcpy
. O worm Morris explorou uma chamada gets
em fingerd.
Bibliotecas de tipo de dados abstratos bem escritas e testadas que centralizam e executam automaticamente o gerenciamento de buffer, incluindo verificação de limites, podem reduzir a ocorrência e o impacto de estouros de buffer. Os dois principais tipos de dados de bloco de construção nessas linguagens nas quais geralmente ocorrem estouros de buffer são strings e arrays; portanto, as bibliotecas que impedem estouros de buffer nesses tipos de dados podem fornecer a grande maioria da cobertura necessária. Ainda assim, a falha em usar essas bibliotecas seguras corretamente pode resultar em estouros de buffer e outras vulnerabilidades; e, naturalmente, qualquer bug na própria biblioteca é uma vulnerabilidade em potencial. "Seguro" implementações de biblioteca incluem "The Better String Library", Vstr e Erwin. A biblioteca C do sistema operacional OpenBSD fornece as funções strlcpy e strlcat, mas elas são mais limitadas do que as implementações de bibliotecas totalmente seguras.
Em setembro de 2007, foi publicado o Relatório Técnico 24731, elaborado pelo comitê de normas C; ele especifica um conjunto de funções que são baseadas na cadeia de caracteres da biblioteca C padrão e nas funções IO, com parâmetros adicionais de tamanho do buffer. No entanto, a eficácia dessas funções com o objetivo de reduzir estouros de buffer é discutível; ele requer a intervenção do programador em uma base por chamada de função que é equivalente à intervenção que poderia fazer com que o estouro de buffer de funções de biblioteca padrão análogas mais antigas seja seguro.
Proteção contra estouro de buffer
A proteção contra estouro de buffer é usada para detectar os estouros de buffer mais comuns, verificando se a pilha não foi alterada quando uma função retorna. Caso tenha sido alterado, o programa sai com falha de segmentação. Três desses sistemas são Libsafe e os patches gcc StackGuard e ProPolice.
A implementação da Microsoft do modo Data Execution Prevention (DEP) protege explicitamente o ponteiro para o Structured Exception Handler (SEH) de ser substituído.
Proteção de pilha mais forte é possível dividindo a pilha em duas: uma para dados e outra para retornos de função. Essa divisão está presente na linguagem Forth, embora não tenha sido uma decisão de design baseada em segurança. Independentemente disso, esta não é uma solução completa para estouros de buffer, pois dados confidenciais que não sejam o endereço de retorno ainda podem ser substituídos.
Proteção do ponteiro
Os estouros de buffer funcionam manipulando ponteiros, incluindo endereços armazenados. PointGuard foi proposto como uma extensão de compilador para impedir que invasores manipulem ponteiros e endereços de maneira confiável. A abordagem funciona fazendo com que o compilador adicione código para codificar ponteiros com XOR automaticamente antes e depois de serem usados. Teoricamente, como o invasor não sabe qual valor será usado para codificar e decodificar o ponteiro, não pode ser previsto para o que o ponteiro apontará se for substituído por um novo valor. O PointGuard nunca foi lançado, mas a Microsoft implementou uma abordagem semelhante começando no Windows XP SP2 e no Windows Server 2003 SP1. Em vez de implementar a proteção de ponteiro como um recurso automático, a Microsoft adicionou uma rotina de API que pode ser chamada. Isso permite um melhor desempenho (porque não é usado o tempo todo), mas coloca o fardo sobre o programador para saber quando é necessário.
Como o XOR é linear, um invasor pode manipular um ponteiro codificado substituindo apenas os bytes inferiores de um endereço. Isso pode permitir que um ataque seja bem-sucedido se o invasor for capaz de tentar a exploração várias vezes ou for capaz de concluir um ataque fazendo com que um ponteiro aponte para um dos vários locais (como qualquer local dentro de um trenó NOP). A Microsoft adicionou uma rotação aleatória ao seu esquema de codificação para resolver esse ponto fraco para substituições parciais.
Proteção de espaço executável
A proteção de espaço executável é uma abordagem para proteção contra estouro de buffer que impede a execução de código na pilha ou no heap. Um invasor pode usar estouros de buffer para inserir código arbitrário na memória de um programa, mas com proteção de espaço executável, qualquer tentativa de executar esse código causará uma exceção.
Algumas CPUs suportam um recurso chamado bit NX ("No eXecute") ou XD ("eXecute Disabled"), que em conjunto com o software, pode ser usado para marcar páginas de dados (como aqueles que contêm a pilha e o heap) como legíveis e graváveis, mas não executáveis.
Alguns sistemas operacionais Unix (por exemplo, OpenBSD, macOS) vêm com proteção de espaço executável (por exemplo, W^X). Alguns pacotes opcionais incluem:
- Pax
- Escudo exec
- Openwall
As variantes mais recentes do Microsoft Windows também oferecem suporte à proteção de espaço executável, chamada Prevenção de Execução de Dados. Os complementos proprietários incluem:
- BufferShield
- StackDefender
A proteção de espaço executável geralmente não protege contra ataques de retorno à libc ou qualquer outro ataque que não dependa da execução do código do invasor. No entanto, em sistemas de 64 bits que usam ASLR, conforme descrito abaixo, a proteção de espaço executável torna muito mais difícil executar esses ataques.
Aleatorização do layout do espaço de endereçamento
Address space layout randomization (ASLR) é um recurso de segurança do computador que envolve organizar as posições das principais áreas de dados, geralmente incluindo a base do executável e a posição das bibliotecas, pilha e pilha, aleatoriamente em um processo' espaço de endereçamento.
A randomização dos endereços de memória virtual nos quais as funções e variáveis podem ser encontradas pode tornar a exploração de um estouro de buffer mais difícil, mas não impossível. Também força o invasor a adaptar a tentativa de exploração ao sistema individual, o que frustra as tentativas de worms da Internet. Um método semelhante, mas menos eficaz, é rebasear processos e bibliotecas no espaço de endereço virtual.
Inspeção profunda de pacotes
O uso de inspeção profunda de pacotes (DPI) pode detectar, no perímetro da rede, tentativas remotas muito básicas de explorar estouros de buffer pelo uso de assinaturas de ataque e heurística. Eles são capazes de bloquear pacotes que possuem a assinatura de um ataque conhecido, ou se uma longa série de instruções de não-operação (conhecidas como NOP-sled) for detectada, elas já foram usadas quando a localização do exploit carga útil é ligeiramente variável.
A varredura de pacotes não é um método eficaz, pois só pode impedir ataques conhecidos e há muitas maneiras de um NOP-sled ser codificado. O shellcode usado pelos invasores pode ser alfanumérico, metamórfico ou automodificável para evitar a detecção por scanners heurísticos de pacotes e sistemas de detecção de intrusão.
Teste
Verificar se há estouros de buffer e corrigir os erros que os causam naturalmente ajuda a evitar estouros de buffer. Uma técnica automatizada comum para descobri-los é o fuzzing. O teste de caso de borda também pode descobrir estouros de buffer, assim como a análise estática. Uma vez detectado um estouro de buffer em potencial, ele deve ser corrigido; isso torna a abordagem de teste útil para software que está em desenvolvimento, mas menos útil para software legado que não é mais mantido ou suportado.
História
Os estouros de buffer foram compreendidos e parcialmente documentados publicamente já em 1972, quando o Computer Security Technology Planning Study apresentou a técnica: "O código que executa esta função não verifica os endereços de origem e destino adequadamente, permitindo partes de o monitor seja sobreposto pelo usuário. Isso pode ser usado para injetar código no monitor que permitirá ao usuário assumir o controle da máquina." Hoje, o monitor seria chamado de kernel.
A primeira exploração hostil documentada de um estouro de buffer foi em 1988. Foi uma das várias explorações usadas pelo worm Morris para se propagar pela Internet. O programa explorado era um serviço no Unix chamado finger. Mais tarde, em 1995, Thomas Lopatic redescobriu independentemente o buffer overflow e publicou suas descobertas na lista de discussão de segurança Bugtraq. Um ano depois, em 1996, Elias Levy (também conhecido como Aleph One) publicou na revista Phrack o artigo "Smashing the Stack for Fun and Profit", um passo a passo introdução à exploração de vulnerabilidades de estouro de buffer baseadas em pilha.
Desde então, pelo menos dois grandes worms da Internet exploraram estouros de buffer para comprometer um grande número de sistemas. Em 2001, o worm Code Red explorou um estouro de buffer no Internet Information Services (IIS) 5.0 da Microsoft e, em 2003, o worm SQL Slammer comprometeu máquinas executando o Microsoft SQL Server 2000.
Em 2003, buffer overflows presentes em jogos Xbox licenciados foram explorados para permitir que software não licenciado, incluindo jogos homebrew, rodassem no console sem a necessidade de modificações de hardware, conhecidas como modchips. O PS2 Independence Exploit também usou um estouro de buffer para conseguir o mesmo para o PlayStation 2. O hack Twilight conseguiu o mesmo com o Wii, usando um estouro de buffer em The Legend of Zelda: Twilight Princess.
Contenido relacionado
Fila dupla
Asteróides (vídeo game)
Operador bastardo do inferno