Heap Overflow

Suporte o HackTricks

Informações Básicas

Um heap overflow é como um stack overflow, mas no heap. Basicamente significa que algum espaço foi reservado no heap para armazenar alguns dados e os dados armazenados eram maiores do que o espaço reservado.

Em stack overflows, sabemos que alguns registradores como o ponteiro de instrução ou o quadro de pilha serão restaurados a partir da pilha e poderia ser possível abusar disso. No caso de heap overflows, não há nenhuma informação sensível armazenada por padrão no pedaço de heap que pode ser sobrecarregado. No entanto, poderia ser informações sensíveis ou ponteiros, então a criticidade dessa vulnerabilidade depende de quais dados podem ser sobrescritos e de como um atacante poderia abusar disso.

Para encontrar deslocamentos de overflow, você pode usar os mesmos padrões que em stack overflows.

Stack Overflows vs Heap Overflows

Em stack overflows, a organização e os dados que estarão presentes na pilha no momento em que a vulnerabilidade pode ser acionada são bastante confiáveis. Isso ocorre porque a pilha é linear, sempre aumentando em memória colidindo, em lugares específicos da execução do programa a memória da pilha geralmente armazena um tipo de dados semelhante e tem uma estrutura específica com alguns ponteiros no final da parte da pilha usada por cada função.

No entanto, no caso de um heap overflow, a memória usada não é linear, mas os pedaços alocados geralmente estão em posições separadas da memória (não um ao lado do outro) por causa de bins e zones que separam alocações por tamanho e porque a memória anterior liberada é usada antes de alocar novos pedaços. É complicado saber qual objeto vai colidir com o objeto vulnerável a um heap overflow. Portanto, quando um heap overflow é encontrado, é necessário encontrar uma maneira confiável de fazer com que o objeto desejado esteja próximo na memória do que o que pode ser sobrecarregado.

Uma das técnicas usadas para isso é o Heap Grooming, que é usado, por exemplo, neste post. No post é explicado como, no kernel do iOS, quando uma zona fica sem memória para armazenar pedaços de memória, ela a expande em uma página do kernel, e esta página é dividida em pedaços dos tamanhos esperados que seriam usados em ordem (até a versão 9.2 do iOS, então esses pedaços são usados de forma randomizada para dificultar a exploração desses ataques).

Portanto, no post anterior onde um heap overflow está ocorrendo, para forçar o objeto sobrecarregado a colidir com uma ordem vítima, vários kallocs são forçados por várias threads para tentar garantir que todos os pedaços livres sejam preenchidos e que uma nova página seja criada.

Para forçar esse preenchimento com objetos de um tamanho específico, a alocação fora de linha associada a uma porta mach iOS é um candidato ideal. Ao criar o tamanho da mensagem, é possível especificar exatamente o tamanho da alocação kalloc e quando a porta mach correspondente é destruída, a alocação correspondente será imediatamente liberada de volta para kfree.

Em seguida, alguns desses espaços reservados podem ser liberados. A lista de liberação kalloc.4096 libera elementos em uma ordem de último a entrar, primeiro a sair, o que basicamente significa que se alguns espaços reservados forem liberados e o exploit tentar alocar vários objetos vítimas enquanto tenta alocar o objeto vulnerável à sobrecarga, é provável que este objeto seja seguido por um objeto vítima.

Exemplo libc

Nesta página é possível encontrar uma emulação básica de Heap overflow que mostra como sobrescrever o bit prev in use do próximo pedaço e a posição do tamanho prev é possível consolidar um pedaço usado (fazendo-o pensar que está não utilizado) e então alocá-lo novamente sendo capaz de sobrescrever dados que estão sendo usados em um ponteiro diferente também.

Outro exemplo de protostar heap 0 mostra um exemplo muito básico de um CTF onde um heap overflow pode ser abusado para chamar a função vencedora e obter a bandeira.

No exemplo protostar heap 1 é possível ver como abusar de um estouro de buffer é possível sobrescrever em um pedaço próximo um endereço onde dados arbitrários do usuário serão escritos.

Exemplo ARM64

Na página https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/ você pode encontrar um exemplo de heap overflow onde um comando que será executado é armazenado no próximo pedaço a partir do pedaço sobrecarregado. Portanto, é possível modificar o comando executado sobrescrevendo-o com um exploit simples como:

python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt

Outros exemplos

  • Usamos uma vulnerabilidade de Integer Overflow para obter um Heap Overflow.

  • Corrompemos ponteiros para uma função dentro de uma struct do chunk estourado para definir uma função como system e obter execução de código.

Suporte ao HackTricks

Last updated