hacktricks/reversing-and-exploiting/linux-exploiting-basic-esp/common-binary-protections/stack-canaries.md

4.3 KiB

Stack Canaries

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras formas de apoiar o HackTricks:

StackGuard e StackShield

StackGuard insere um valor especial conhecido como um canary antes do EIP (Extended Instruction Pointer), especificamente 0x000aff0d (representando nulo, nova linha, EOF, retorno de carro) para proteger contra estouros de buffer. No entanto, funções como recv(), memcpy(), read(), e bcopy() permanecem vulneráveis, e não protege o EBP (Base Pointer).

StackShield adota uma abordagem mais sofisticada do que o StackGuard, mantendo uma Global Return Stack, que armazena todos os endereços de retorno (EIPs). Essa configuração garante que qualquer estouro não cause danos, pois permite a comparação entre os endereços de retorno armazenados e os reais para detectar ocorrências de estouro. Além disso, o StackShield pode verificar o endereço de retorno em relação a um valor de limite para detectar se o EIP aponta para fora do espaço de dados esperado. No entanto, essa proteção pode ser contornada por técnicas como Return-to-libc, ROP (Return-Oriented Programming) ou ret2ret, indicando que o StackShield também não protege variáveis locais.

Protetor de Stack Smash (ProPolice) -fstack-protector:

Esse mecanismo coloca um canary antes do EBP e reorganiza as variáveis locais para posicionar buffers em endereços de memória mais altos, impedindo que eles sobrescrevam outras variáveis. Ele também copia com segurança os argumentos passados na pilha acima das variáveis locais e usa essas cópias como argumentos. No entanto, não protege arrays com menos de 8 elementos ou buffers dentro de uma estrutura do usuário.

O canary é um número aleatório derivado de /dev/urandom ou um valor padrão de 0xff0a0000. Ele é armazenado no TLS (Thread Local Storage), permitindo que espaços de memória compartilhados entre threads tenham variáveis globais ou estáticas específicas da thread. Essas variáveis são inicialmente copiadas do processo pai, e os processos filhos podem alterar seus dados sem afetar o pai ou irmãos. No entanto, se um fork() é usado sem criar um novo canary, todos os processos (pai e filhos) compartilham o mesmo canary, tornando-o vulnerável. Na arquitetura i386, o canary é armazenado em gs:0x14, e no x86_64, em fs:0x28.

Essa proteção local identifica funções com buffers vulneráveis a ataques e injeta código no início dessas funções para colocar o canary e no final para verificar sua integridade.

Quando um servidor web usa fork(), ele permite um ataque de força bruta para adivinhar o byte do canary por vez. No entanto, usar execve() após fork() sobrescreve o espaço de memória, anulando o ataque. vfork() permite que o processo filho execute sem duplicação até tentar escrever, momento em que uma duplicata é criada, oferecendo uma abordagem diferente para a criação de processos e manipulação de memória.

Bypasses

  • Vazamento do canary e então sobrescrevê-lo (por exemplo, estouro de buffer) com seu próprio valor.
  • Se o canary for bifurcado em processos filhos, pode ser possível forçá-lo um byte de cada vez.
  • Se houver alguma vulnerabilidade de vazamento interessante no binário, pode ser possível vazá-lo.