Unsorted Bin Attack
Last updated
Last updated
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Para mais informações sobre o que é um bin não ordenado, confira esta página:
Bins & Memory AllocationsListas 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 bin não ordenado, ele poderá escrever esse endereço em um endereço arbitrário, o que pode ser útil para vazar endereços Glibc ou contornar alguma defesa.
Assim, basicamente, esse ataque permite definir um grande número em um endereço arbitrário. Esse grande número é um endereço, que pode ser um endereço de heap ou um endereço Glibc. Um alvo típico é global_max_fast
para permitir a criação de bins de fast bin com tamanhos maiores (e passar de um ataque de bin não ordenado para um ataque de fast bin).
Dando uma olhada no 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 hoje em dia o erro malloc(): unsorted double linked list corrupted
é acionado.
Portanto, esse ataque de bin não ordenado agora (entre outras verificações) também requer ser capaz de corrigir a lista duplamente encadeada, de modo 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.
Note que este ataque corrompe o bin não ordenado (portanto, pequeno e grande também). Portanto, só podemos usar alocações do fast bin agora (um programa mais complexo pode fazer outras alocações e travar), e para acionar isso devemos alocar o mesmo tamanho ou o programa travará.
Note que sobrescrever global_max_fast
pode ajudar neste caso, confiando que o fast bin será capaz de cuidar de todas as outras alocações até que a exploração seja concluída.
O código de guyinatuxedo explica isso muito bem, embora se você modificar os mallocs para alocar memória grande o suficiente para não acabar em um Tcache, você pode ver que o erro mencionado anteriormente aparece, impedindo essa técnica: malloc(): unsorted double linked list corrupted
Este é, na verdade, um conceito muito básico. Os chunks no bin não ordenado terão ponteiros. O primeiro chunk no bin não ordenado terá, na verdade, os links fd
e bk
apontando para uma parte da arena principal (Glibc).
Portanto, se você puder colocar um chunk dentro de um bin não ordenado 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ção Glibc.
Um ataque semelhante usado neste relatório foi abusar de uma estrutura de 4 chunks (A, B, C e D - D é apenas para evitar a consolidação com o chunk superior), então um estouro de byte nulo em B foi usado para fazer C indicar que B estava não utilizado. 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 da libc vazados foram escritos em B, de onde foram vazados.
O objetivo é sobrescrever uma variável global com um valor maior que 4869 para que seja possível obter a flag e o PIE não está 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 chunk superior não consolide os anteriores.
Então, chunk1 é liberado e chunk0 é estourado para que o ponteiro bk
de chunk1 aponte para: bk = magic - 0x10
Então, chunk3 é alocado com o mesmo tamanho que chunk1, o que acionará o ataque de bin não ordenado 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 o mesmo, ela irá realocar nele e depois liberá-lo, mas retornando um ponteiro para essa 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 chunk superior. Então, a função de mesclagem é chamada com chunk0 duas vezes, o que causará um uso após liberação.
Então, a função view
é chamada com o índice 2 (que é o índice do chunk de uso após liberação), o que vazará um endereço da libc.
Como o binário tem proteções para alocar apenas tamanhos maiores que global_max_fast
, nenhum fastbin é usado, um ataque de bin não ordenado será usado para sobrescrever a variável global global_max_fast
.
Então, é possível chamar a função de edição 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)
. Então, criando um novo chunk, o endereço livre anteriormente comprometido (0x20) acionará o ataque de bin não ordenado, sobrescrevendo o global_max_fast
com um valor muito grande, permitindo agora criar chunks em fast bins.
Agora um ataque de fast bin é realizado:
Primeiro de tudo, descobre-se que é possível trabalhar com fast chunks de tamanho 200 na localização de __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 nesta 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 de mesclagem é chamada com esse ponteiro duas vezes, assim obtemos um ponteiro para um chunk liberado de tamanho 0xfc*2 = 0x1f8
no fast bin.
Então, a função de edição é chamada neste chunk para modificar o endereço fd
deste fast bin para apontar para a função anterior __free_hook
.
Então, um chunk com tamanho 0x1f8
é criado para recuperar do fast bin o chunk inútil anterior, assim outro chunk de tamanho 0x1f8
é criado para obter um chunk de fast bin na __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 de deletar, acionando a função __free_hook
que aponta para system com /bin/sh\x00
como parâmetro.
Outro exemplo de abuso de um estouro de 1B para consolidar chunks no bin não ordenado e obter um vazamento de informação da libc e depois realizar um ataque de fast bin para sobrescrever o malloc hook com um endereço de um gadget.
Só podemos alocar chunks de tamanho maior que 0x100
.
Sobrescrever global_max_fast
usando um ataque de Bin Não Ordenado (funciona 1/16 vezes devido ao ASLR, porque precisamos modificar 12 bits, mas devemos modificar 16 bits).
Ataque de Fast Bin para modificar um array global de chunks. Isso fornece uma primitiva de leitura/escrita arbitrária, que permite modificar o GOT e definir algumas funções para apontar para system
.
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)