Unsorted Bin Attack

Suporte ao HackTricks

Informações Básicas

Para mais informações sobre o que é um unsorted bin, consulte esta página:

Bins & Memory Allocations

As listas não ordenadas são capazes de escrever o endereço para unsorted_chunks (av) no endereço bk do chunk. Portanto, se um atacante puder modificar o endereço do ponteiro bk em um chunk dentro do unsorted bin, ele poderia ser capaz de escrever esse endereço em um endereço arbitrário que poderia ser útil para vazar endereços do Glibc ou contornar algumas defesas.

Portanto, basicamente, esse ataque permite definir um número grande em um endereço arbitrário. Esse número grande é um endereço, que poderia ser um endereço de heap ou um endereço do Glibc. Um alvo típico é o global_max_fast para permitir a criação de bins rápidos com tamanhos maiores (e passar de um ataque unsorted bin para um ataque fast bin).

Analisando o exemplo fornecido em https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle e usando 0x4000 e 0x5000 em vez de 0x400 e 0x500 como tamanhos de chunk (para evitar Tcache), é possível ver que atualmente o erro malloc(): unsorted double linked list corrupted é acionado.

Portanto, esse ataque unsorted bin agora (entre outras verificações) também requer ser capaz de corrigir a lista duplamente encadeada para que isso seja contornado victim->bk->fd == victim ou não victim->fd == av (arena), o que significa que o endereço onde queremos escrever deve ter o endereço do chunk falso em sua posição fd e que o fd do chunk falso está apontando para a arena.

Observe que esse ataque corrompe o unsorted bin (portanto, também o small e large). Portanto, agora só podemos usar alocações do fast bin (um programa mais complexo pode fazer outras alocações e travar), e para acionar isso devemos alocar o mesmo tamanho ou o programa travará.

Observe que sobrescrever global_max_fast pode ajudar nesse caso, confiando que o fast bin será capaz de lidar com todas as outras alocações até que o exploit seja concluído.

O código de guyinatuxedo explica muito bem, embora se você modificar as alocações para alocar memória grande o suficiente para não terminar em um Tcache, você verá que o erro mencionado anteriormente aparece, impedindo essa técnica: malloc(): unsorted double linked list corrupted

Ataque de Vazamento de Informações do Unsorted Bin

Este é na verdade um conceito muito básico. Os chunks no unsorted bin terão ponteiros. O primeiro chunk no unsorted bin terá na verdade os links fd e bk apontando para uma parte da arena principal (Glibc). Portanto, se você pode colocar um chunk dentro de um unsorted bin e lê-lo (uso após liberação) ou alocá-lo novamente sem sobrescrever pelo menos 1 dos ponteiros para então lê-lo, você pode ter um vazamento de informações do Glibc.

Um ataque semelhante usado neste artigo, foi abusar de uma estrutura de 4 chunks (A, B, C e D - D é apenas para evitar a consolidação com o top chunk) para que uma sobrecarga de byte nulo em B fosse usada para fazer C indicar que B estava inutilizado. Além disso, em B, os dados prev_size foram modificados para que o tamanho, em vez de ser o tamanho de B, fosse A+B. Então C foi desalocado e consolidado com A+B (mas B ainda estava em uso). Um novo chunk de tamanho A foi alocado e então os endereços vazados do libc foram escritos em B de onde foram vazados.

Referências e Outros Exemplos

  • O objetivo é sobrescrever uma variável global com um valor maior que 4869 para ser possível obter a flag e o PIE não estar habilitado.

  • É possível gerar chunks de tamanhos arbitrários e há um estouro de heap com o tamanho desejado.

  • O ataque começa criando 3 chunks: chunk0 para abusar do estouro, chunk1 para ser estourado e chunk2 para que o top chunk não consolide os anteriores.

  • Em seguida, o chunk1 é liberado e o chunk0 é estourado para que o ponteiro bk do chunk1 aponte para: bk = magic - 0x10

  • Em seguida, o chunk3 é alocado com o mesmo tamanho que o chunk1, o que acionará o ataque unsorted bin e modificará o valor da variável global, tornando possível obter a flag.

  • A função de mesclagem é vulnerável porque se ambos os índices passados forem iguais, ela realocará nele e então o liberará, mas retornando um ponteiro para aquela região liberada que pode ser usada.

  • Portanto, 2 chunks são criados: chunk0 que será mesclado consigo mesmo e chunk1 para evitar a consolidação com o top chunk. Em seguida, a função de mesclagem é chamada com o chunk0 duas vezes, o que causará um uso após a liberação.

  • Em seguida, a função view é chamada com o índice 2 (que é o índice do chunk de uso após liberação), que irá vazar um endereço do libc.

  • Como o binário tem proteções para alocar apenas tamanhos maiores que global_max_fast para que nenhum fastbin seja usado, um ataque unsorted bin será usado para sobrescrever a variável global global_max_fast.

  • Em seguida, é possível chamar a função edit com o índice 2 (o ponteiro de uso após liberação) e sobrescrever o ponteiro bk para apontar para p64(global_max_fast-0x10). Em seguida, criando um novo chunk usará o endereço de liberação comprometido anteriormente (0x20) e acionará o ataque unsorted bin sobrescrevendo o global_max_fast com um valor muito grande, permitindo agora criar chunks em fast bins.

  • Agora um ataque fast bin é realizado:

  • Primeiramente, é descoberto que é possível trabalhar com chunks rápidos de tamanho 200 na localização de __free_hook:

  • gef➤  p &__free_hook

$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000

  • Se conseguirmos obter um fast chunk de tamanho 0x200 nessa localização, será possível sobrescrever um ponteiro de função que será executado

  • Para isso, um novo chunk de tamanho 0xfc é criado e a função mesclada é chamada com esse ponteiro duas vezes, dessa forma obtemos um ponteiro para um chunk liberado de tamanho 0xfc*2 = 0x1f8 no fast bin.

  • Em seguida, a função edit é chamada nesse chunk para modificar o endereço fd desse fast bin para apontar para a função __free_hook anterior.

  • Depois, um chunk com tamanho 0x1f8 é criado para recuperar do fast bin o chunk inútil anterior, então outro chunk de tamanho 0x1f8 é criado para obter um chunk do fast bin no __free_hook que é sobrescrito com o endereço da função system.

  • E finalmente um chunk contendo a string /bin/sh\x00 é liberado chamando a função delete, acionando a função __free_hook que aponta para system com /bin/sh\x00 como parâmetro.

  • Outro exemplo de abuso de um overflow de 1B para consolidar chunks no unsorted bin e obter um vazamento de informações da libc e depois realizar um ataque fast bin para sobrescrever o malloc hook com um endereço de one gadget

  • Só podemos alocar chunks de tamanho maior que 0x100.

  • Sobrescrever global_max_fast usando um ataque Unsorted Bin (funciona 1/16 vezes devido ao ASLR, porque precisamos modificar 12 bits, mas devemos modificar 16 bits).

  • Ataque Fast Bin para modificar um array global de chunks. Isso fornece um primitivo de leitura/escrita arbitrário, que permite modificar a GOT e definir algumas funções para apontar para system.

Apoie o HackTricks

Last updated