Jonathan Pincus é pesquisador sênior da Microsoft Research, e Brandon Baker, engenheiro de segurança de desenvolvimento da Microsoft. Neste artigo, eles descrevem três famílias de ataques derivados do estouro de buffers.
O estouro de buffers ocorre quando um programa tenta ler ou escrever além do limite declarado de um array (o referido buffer). Nas linguagens C e C++ não existe nenhum tipo de checagem de extrapolação de limites, ao contrário do que acontece com as linguagens Pascal, Java e C# por exemplo. O estouro de buffer pode ainda ser caracterizado como estouro de buffer da pilha ou estouro de buffer do heap, dependendo do tipo de memória utilizada – no primeiro caso trata-se de variáveis estáticas, localizadas na pilha de execução, ao passo que no segundo caso trata-se de variáveis dinâmicas, localizadas no heap.
A abordagem tradicional do estouro de buffer é o stack smashing: a modificação do endereço de retorno presente na pilha de execução de maneira a alterar o fluxo de execução do programa. Ao invés de apontar para o retorno, o endereço aponta para código malicioso armazenado em determinado local pelo atacante.
No artigo, os autores apresentam 3 novos tipos de ataques desta natureza, afim de que a compreensão do funcionamento dos ataques leve a melhores estratégias de segurança. A seguir, cada um deles é brevemente apresentado.
Arc injection
Este ataque é orientado a dados. Ao invés de também inserir código executável malicioso para que seja desviado o fluxo de execução até ele, um atacante pode apenas fornecer dados tais que quando o programa original operar sobre os mesmos, o objetivo do ataque também será atingido. Um exemplo deste tipo de ataque são comandos de sistema que o programa atacado passa a utilizar para criar novos processos, o que permite a execução arbitrária de código.
Um exemplo deste ataque é o estouro de buffer para desviar o fluxo de execução para uma chamada SYSTEM() presente no código do próprio programa, onde as verificações de integridade dos parâmetros podem ser puladas e o parâmetro é um dado armazenado pelo atacante.
Pointer Subterfuge
Este ataque consiste em alterar o valor de ponteiros. Existem pelo menos quatro versões deste tipo de ataque:
- Function-Pointer Clobbering: Alteração do valor de um ponteiro para um local com código malicioso;
- Data-Pointer Modification: Alteração de locais arbitrários da memória como isca, na expectativa de que tais locais sejam utilizados em alguma atribuição, fazendo com que se obtenha poder também sobre outras áreas da memória que forem fisgadas;
- Exception-Handler Hijacking: Quando um programa lança uma exceção, o Windows examina uma lista encadeada que armazena manipuladores de exceção e invoca um ou mais via ponteiros para o tratamento da exceção. O ataque consiste em alterar tal ponteiro via estouro de buffer, permitindo que ao invés de invocar um manipulador de exceção, o fluxo de execução seja desviado.
- Virtual Pointer (VPTR) Smashing: A maioria dos compiladores C++ implementa funções virtuais através de uma tabela de funções virtuais (VTBL) associada a cada classe. A VTBL é um array de ponteiros para funções utilizados em tempo de execução para implementar o despacho dinâmico. Objetidos individuais apontam para a VTBL apropriada através de ponteiros virtuais (VPTR) armazenado no header do objeto. Substituindo-se o VPTR de um objeto com um ponteiro para código malicioso faz com que o fluxo seja desviado na próxima vez em que uma função virtual for invacada.
Heap Smashing
O estouro de buffers ocorre quando um programa tenta ler ou escrever além do limite declarado de um array (o referido buffer). Nas linguagens C e C++ não existe nenhum tipo de checagem de extrapolação de limites, ao contrário do que acontece com as linguagens Pascal, Java e C# por exemplo. O estouro de buffer pode ainda ser caracterizado como estouro de buffer da pilha ou estouro de buffer do heap, dependendo do tipo de memória utilizada – no primeiro caso trata-se de variáveis estáticas, localizadas na pilha de execução, ao passo que no segundo caso trata-se de variáveis dinâmicas, localizadas no heap.
A abordagem tradicional do estouro de buffer é o stack smashing: a modificação do endereço de retorno presente na pilha de execução de maneira a alterar o fluxo de execução do programa. Ao invés de apontar para o retorno, o endereço aponta para código malicioso armazenado em determinado local pelo atacante.
No artigo, os autores apresentam 3 novos tipos de ataques desta natureza, afim de que a compreensão do funcionamento dos ataques leve a melhores estratégias de segurança. A seguir, cada um deles é brevemente apresentado.
Arc injection
Este ataque é orientado a dados. Ao invés de também inserir código executável malicioso para que seja desviado o fluxo de execução até ele, um atacante pode apenas fornecer dados tais que quando o programa original operar sobre os mesmos, o objetivo do ataque também será atingido. Um exemplo deste tipo de ataque são comandos de sistema que o programa atacado passa a utilizar para criar novos processos, o que permite a execução arbitrária de código.
Um exemplo deste ataque é o estouro de buffer para desviar o fluxo de execução para uma chamada SYSTEM() presente no código do próprio programa, onde as verificações de integridade dos parâmetros podem ser puladas e o parâmetro é um dado armazenado pelo atacante.
Pointer Subterfuge
Este ataque consiste em alterar o valor de ponteiros. Existem pelo menos quatro versões deste tipo de ataque:
- Function-Pointer Clobbering: Alteração do valor de um ponteiro para um local com código malicioso;
- Data-Pointer Modification: Alteração de locais arbitrários da memória como isca, na expectativa de que tais locais sejam utilizados em alguma atribuição, fazendo com que se obtenha poder também sobre outras áreas da memória que forem fisgadas;
- Exception-Handler Hijacking: Quando um programa lança uma exceção, o Windows examina uma lista encadeada que armazena manipuladores de exceção e invoca um ou mais via ponteiros para o tratamento da exceção. O ataque consiste em alterar tal ponteiro via estouro de buffer, permitindo que ao invés de invocar um manipulador de exceção, o fluxo de execução seja desviado.
- Virtual Pointer (VPTR) Smashing: A maioria dos compiladores C++ implementa funções virtuais através de uma tabela de funções virtuais (VTBL) associada a cada classe. A VTBL é um array de ponteiros para funções utilizados em tempo de execução para implementar o despacho dinâmico. Objetidos individuais apontam para a VTBL apropriada através de ponteiros virtuais (VPTR) armazenado no header do objeto. Substituindo-se o VPTR de um objeto com um ponteiro para código malicioso faz com que o fluxo seja desviado na próxima vez em que uma função virtual for invacada.
Heap Smashing
Ao contrário do que se pensava até recentemente, não são apenas os buffers da pilha de execução vulneráveis a este tipo de ataque. Alocadores de memória dinâmica mantém headers para cada bloco do heap, ligados duplamente em listas encadeadas de blocos alocados e liberados. Tais headers são atualizados a cada operação sobre a memória (alocação e liberação).
Se houverem três blocos de memória contíguos X, Y e Z, e houver estouro de buffer em X de forma que os ponteiros do header de Y sejam modificados, pode ocorrer modificação de uma parte arbitrária da memória quando X, Y e Z forem liberados.
Referência
Pincus, J.; Baker, B. Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns. Security & Privacy, IEEE Volume 2, Issue 4, July-Aug. 2004 Page(s): 20 – 27. Disponível em: http://ieeexplore.ieee.org/iel5/9141/29316/01324594.pdf. Acesso em 02 de Junho de 2010.
Se houverem três blocos de memória contíguos X, Y e Z, e houver estouro de buffer em X de forma que os ponteiros do header de Y sejam modificados, pode ocorrer modificação de uma parte arbitrária da memória quando X, Y e Z forem liberados.
Referência
Pincus, J.; Baker, B. Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns. Security & Privacy, IEEE Volume 2, Issue 4, July-Aug. 2004 Page(s): 20 – 27. Disponível em: http://ieeexplore.ieee.org/iel5/9141/29316/01324594.pdf. Acesso em 02 de Junho de 2010.
Nenhum comentário:
Postar um comentário