Proteções do Libc

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Aplicação do Alinhamento de Chunk

Malloc aloca memória em agrupamentos de 8 bytes (32-bit) ou 16 bytes (64-bit). Isso significa que o fim dos chunks em sistemas 32-bit deve alinhar com 0x8, e em sistemas 64-bit com 0x0. A funcionalidade de segurança verifica que cada chunk está corretamente alinhado nesses locais específicos antes de usar um ponteiro de um bin.

Benefícios de Segurança

A aplicação do alinhamento de chunk em sistemas 64-bit melhora significativamente a segurança do Malloc ao limitar a colocação de fake chunks a apenas 1 a cada 16 endereços. Isso complica os esforços de exploração, especialmente em cenários onde o usuário tem controle limitado sobre valores de entrada, tornando os ataques mais complexos e mais difíceis de executar com sucesso.

  • Fastbin Attack on __malloc_hook

As novas regras de alinhamento no Malloc também frustram um ataque clássico envolvendo o __malloc_hook. Anteriormente, atacantes podiam manipular tamanhos de chunk para sobrescrever esse ponteiro de função e obter execução de código. Agora, o requisito de alinhamento estrito garante que tais manipulações não sejam mais viáveis, fechando uma rota comum de exploração e aumentando a segurança geral.

Nota: Desde o glibc 2.34 os hooks legados (__malloc_hook, __free_hook, etc.) foram removidos do ABI exportado. Exploits modernos agora miram outros ponteiros de função graváveis (por exemplo, tcache per-thread struct, vtable-style callbacks) ou dependem de setcontext, _IO_list_all primitives, etc.

Pointer Mangling on fastbins and tcache

Pointer Mangling é um aprimoramento de segurança usado para proteger fastbin e tcache Fd pointers em operações de gerenciamento de memória. Essa técnica ajuda a prevenir certos tipos de táticas de exploração de memória, especificamente aquelas que não requerem informações de memória leak ou que manipulam locais de memória diretamente relativos a posições conhecidas (relative overwrites).

O núcleo desta técnica é uma fórmula de ofuscação:

New_Ptr = (L >> 12) XOR P

  • L é o Storage Location do ponteiro.
  • P é o real fastbin/tcache Fd Pointer.

A razão para o deslocamento bit a bit do Storage Location (L) em 12 bits à direita antes da operação XOR é crítica. Essa manipulação trata uma vulnerabilidade inerente à natureza determinística dos 12 bits menos significativos dos endereços de memória, que tipicamente são previsíveis devido a restrições da arquitetura do sistema. Ao deslocar os bits, a porção previsível é removida da equação, aumentando a aleatoriedade do novo pointer mangled e, assim, protegendo contra exploits que dependem da previsibilidade desses bits.

Esse pointer mangled aproveita a aleatoriedade existente fornecida por Address Space Layout Randomization (ASLR), que randomiza endereços usados por programas para dificultar que atacantes prevejam o layout de memória de um processo.

Demangling do ponteiro para recuperar o endereço original envolve usar a mesma operação XOR. Aqui, o ponteiro mangled é tratado como P na fórmula e, quando XORado com o Storage Location (L) inalterado, resulta na revelação do ponteiro original. Essa simetria entre mangling e demangling garante que o sistema possa codificar e decodificar ponteiros de forma eficiente sem sobrecarga significativa, ao mesmo tempo que aumenta substancialmente a segurança contra ataques que manipulam ponteiros de memória.

Benefícios de Segurança

Pointer mangling visa prevenir sobrescritas parciais e completas de ponteiros no heap, um aprimoramento significativo na segurança. Essa funcionalidade impacta técnicas de exploração de várias maneiras:

  1. Prevention of Bye Byte Relative Overwrites: Anteriormente, atacantes podiam alterar parte de um ponteiro para redirecionar heap chunks para locais diferentes sem conhecer endereços exatos, uma técnica evidente no exploit leakless House of Roman. Com pointer mangling, tais relative overwrites sem um heap leak agora requerem brute forcing, reduzindo drasticamente a probabilidade de sucesso.
  2. Increased Difficulty of Tcache Bin/Fastbin Attacks: Ataques comuns que sobrescrevem ponteiros de função (como __malloc_hook) manipulando entradas de fastbin ou tcache são dificultados. Por exemplo, um ataque pode envolver leaking de um endereço da LibC, liberar um chunk no tcache bin e então sobrescrever o Fd pointer para redirecioná-lo ao __malloc_hook para execução arbitrária de código. Com pointer mangling, esses ponteiros devem ser corretamente mangled, exigindo um heap leak para manipulação precisa, elevando assim a barreira de exploração.
  3. Requirement for Heap Leaks in Non-Heap Locations: Criar um fake chunk em áreas não-heap (como a stack, seção .bss, ou PLT/GOT) agora também requer um heap leak devido à necessidade de pointer mangling. Isso amplia a complexidade de explorar essas áreas, similar ao requisito para manipular endereços da LibC.
  4. Leaking Heap Addresses Becomes More Challenging: Pointer mangling restringe a utilidade dos Fd pointers em fastbin e tcache bins como fontes para heap address leaks. Contudo, ponteiros em unsorted, small, e large bins permanecem unmangled, portanto ainda utilizáveis para leaking de endereços. Essa mudança empurra atacantes a explorar esses bins em busca de informação explorável, embora algumas técnicas ainda possam permitir demangling de ponteiros antes de um leak, embora com restrições.

Safe-Linking Bypass (page-aligned leak scenario)

Mesmo com safe-linking habilitado (glibc ≥ 2.32), se você puder leak o ponteiro mangled e tanto o chunk corrompido quanto o chunk vítima compartilham a mesma página de 4KB, o ponteiro original pode ser recuperado apenas com o offset da página:

// leaked_fd is the mangled Fd read from the chunk on the same page
uintptr_t l = (uintptr_t)&chunk->fd;           // storage location
uintptr_t original = (leaked_fd ^ (l >> 12));  // demangle

Isso restaura o Fd e permite o clássico tcache/fastbin poisoning. Se os chunks estiverem em páginas diferentes, brute-forçando o deslocamento de página de 12 bits (0x1000 possibilidades) é frequentemente viável quando os padrões de alocação são determinísticos ou quando crashes são aceitáveis (por exemplo, exploits em estilo CTF).

Demangling Pointers with a Heap Leak

Caution

Para uma explicação melhor do processo check the original post from here.

Algorithm Overview

A fórmula usada para mangling e demangling de pointers é:

New_Ptr = (L >> 12) XOR P

Onde L é o local de armazenamento e P é o ponteiro Fd. Quando L é deslocado para a direita por 12 bits, ele expõe os bits mais significativos de P, devido à natureza do XOR, que produz 0 quando bits são XORed com eles mesmos.

Passos-chave no Algoritmo:

  1. Vazamento inicial dos bits mais significativos: Ao XORar o L deslocado com P, você obtém efetivamente os 12 bits superiores de P porque a porção deslocada de L será zero, deixando os bits correspondentes de P inalterados.
  2. Recuperação dos bits do ponteiro: Como XOR é reversível, conhecendo o resultado e um dos operandos permite calcular o outro. Essa propriedade é usada para deduzir todo o conjunto de bits de P sucessivamente XORando conjuntos conhecidos de bits com partes do ponteiro mangled.
  3. Demangling iterativo: O processo é repetido, cada vez usando os bits recém-descobertos de P do passo anterior para decodificar o próximo segmento do ponteiro mangled, até que todos os bits sejam recuperados.
  4. Tratamento dos bits determinísticos: Os 12 bits finais de L são perdidos devido ao shift, mas eles são determinísticos e podem ser reconstruídos após o processo.

Você pode encontrar uma implementação deste algoritmo aqui: https://github.com/mdulin2/mangle

Pointer Guard

Pointer guard é uma técnica de mitigação de exploits usada no glibc para proteger function pointers armazenados, particularmente aqueles registrados por chamadas de biblioteca como atexit(). Essa proteção envolve embaralhar os pointers XORando-os com um segredo armazenado nos dados da thread (fs:0x30) e aplicando uma rotação de bits. Esse mecanismo tem como objetivo impedir que atacantes sequestren o fluxo de controle sobrescrevendo function pointers.

Bypassing Pointer Guard with a leak

  1. Entendendo as operações do Pointer Guard: O scrambling (mangling) de pointers é feito usando a macro PTR_MANGLE que XORa o ponteiro com um segredo de 64 bits e então realiza uma rotação à esquerda de 0x11 bits. A operação reversa para recuperar o ponteiro original é realizada por PTR_DEMANGLE.
  2. Estratégia de ataque: O ataque é baseado em uma abordagem known-plaintext, onde o atacante precisa conhecer tanto a versão original quanto a versão mangled de um ponteiro para deduzir o segredo usado no mangling.
  3. Explorando known plaintexts:
  • Identificando function pointers fixos: Examinando o código-fonte do glibc ou tabelas de function pointers inicializadas (como __libc_pthread_functions), um atacante pode encontrar function pointers previsíveis.
  • Calculando o segredo: Usando um function pointer conhecido como __pthread_attr_destroy e sua versão mangled a partir da tabela de function pointers, o segredo pode ser calculado rotacionando o mangled pointer para a direita (reverse rotating) e então XORando-o com o endereço da função.
  1. Plaintexts alternativos: O atacante também pode experimentar mangling de pointers com valores conhecidos como 0 ou -1 para ver se isso produz padrões identificáveis na memória, potencialmente revelando o segredo quando esses padrões são encontrados em dumps de memória.
  2. Aplicação prática: Após calcular o segredo, um atacante pode manipular pointers de forma controlada, essencialmente bypassando a proteção Pointer Guard em uma aplicação multithread com conhecimento da base do libc e a capacidade de ler locais arbitrários de memória.

GLIBC Tunables & Recent Loader Bugs

O dynamic loader parseia GLIBC_TUNABLES antes do startup do programa. Bugs de mis-parsing aqui afetam diretamente o libc antes de a maioria das mitigations entrarem em vigor. O bug de 2023 “Looney Tunables” (CVE-2023-4911) é um exemplo: um valor overlong em GLIBC_TUNABLES transborda buffers internos em ld.so, permitindo privilege escalation em muitas distros quando combinado com binários SUID. A exploração requer apenas a criação do ambiente e invocações repetidas do binário alvo; pointer guard ou safe-linking não previnem isso porque a corrupção ocorre no loader antes da configuração do heap.

Referências

Tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks