ASLR
Informações Básicas
Randomização do Layout do Espaço de Endereços (ASLR) é uma técnica de segurança usada em sistemas operacionais para randomizar os endereços de memória usados por processos do sistema e de aplicativos. Ao fazer isso, torna significativamente mais difícil para um atacante prever a localização de processos e dados específicos, como a pilha, heap e bibliotecas, mitigando assim certos tipos de exploits, especialmente estouros de buffer.
Verificando o Status do ASLR
Para verificar o status do ASLR em um sistema Linux, você pode ler o valor do arquivo /proc/sys/kernel/randomize_va_space
. O valor armazenado neste arquivo determina o tipo de ASLR aplicado:
0: Sem randomização. Tudo é estático.
1: Randomização conservadora. Bibliotecas compartilhadas, pilha, mmap(), página VDSO são randomizadas.
2: Randomização completa. Além dos elementos randomizados pela randomização conservadora, a memória gerenciada por meio de
brk()
é randomizada.
Você pode verificar o status do ASLR com o seguinte comando:
Desativando o ASLR
Para desativar o ASLR, você define o valor de /proc/sys/kernel/randomize_va_space
como 0. Desativar o ASLR geralmente não é recomendado fora de cenários de teste ou depuração. Veja como você pode desativá-lo:
Você também pode desativar o ASLR para uma execução com:
Ativando ASLR
Para ativar o ASLR, você pode escrever o valor 2 no arquivo /proc/sys/kernel/randomize_va_space
. Isso geralmente requer privilégios de root. A ativação da randomização completa pode ser feita com o seguinte comando:
Persistência através de reinicializações
As alterações feitas com os comandos echo
são temporárias e serão redefinidas após a reinicialização. Para tornar a alteração persistente, você precisa editar o arquivo /etc/sysctl.conf
e adicionar ou modificar a seguinte linha:
Depois de editar /etc/sysctl.conf
, aplique as alterações com:
Isso garantirá que suas configurações de ASLR permaneçam após os reinícios.
Bypasses
Forçando por tentativa e erro em sistemas de 32 bits
O PaX divide o espaço de endereço do processo em 3 grupos:
Código e dados (inicializados e não inicializados):
.text
,.data
e.bss
—> 16 bits de entropia na variáveldelta_exec
. Esta variável é inicializada aleatoriamente a cada processo e adicionada aos endereços iniciais.Memória alocada por
mmap()
e bibliotecas compartilhadas —> 16 bits, chamadodelta_mmap
.A pilha —> 24 bits, referido como
delta_stack
. No entanto, ele efetivamente usa 11 bits (do 10º ao 20º byte inclusive), alinhados a 16 bytes —> Isso resulta em 524.288 possíveis endereços reais de pilha.
Os dados anteriores são para sistemas de 32 bits e a entropia final reduzida torna possível contornar o ASLR tentando a execução repetidamente até que o exploit seja concluído com sucesso.
Ideias de força bruta:
Se você tiver um estouro grande o suficiente para hospedar um grande trenó NOP antes do shellcode, você poderia apenas forçar por tentativa e erro os endereços na pilha até que o fluxo salte sobre alguma parte do trenó NOP.
Outra opção para isso, caso o estouro não seja tão grande e o exploit possa ser executado localmente, é possível adicionar o trenó NOP e o shellcode em uma variável de ambiente.
Se o exploit for local, você pode tentar forçar por tentativa e erro o endereço base da libc (útil para sistemas de 32 bits):
Se estiver atacando um servidor remoto, você pode tentar forçar a endereço da função
usleep
dalibc
, passando como argumento 10 (por exemplo). Se em algum momento o servidor demorar 10s extras para responder, você encontrou o endereço dessa função.
Em sistemas de 64 bits, a entropia é muito maior e isso não deveria ser possível.
Forçando a pilha de 64 bits
É possível ocupar uma grande parte da pilha com variáveis de ambiente e então tentar abusar do binário centenas/milhares de vezes localmente para explorá-lo. O código a seguir mostra como é possível apenas selecionar um endereço na pilha e a cada algumas centenas de execuções esse endereço conterá a instrução NOP:
Informações Locais (/proc/[pid]/stat
)
/proc/[pid]/stat
)O arquivo /proc/[pid]/stat
de um processo é sempre legível por todos e contém informações interessantes como:
startcode e endcode: Endereços acima e abaixo com o TEXTO do binário
startstack: O endereço do início da pilha
start_data e end_data: Endereços acima e abaixo onde está o BSS
kstkesp e kstkeip: Endereços atuais de ESP e EIP
arg_start e arg_end: Endereços acima e abaixo onde estão os argumentos da linha de comando
env_start e env_end: Endereços acima e abaixo onde estão as variáveis de ambiente
Portanto, se o atacante estiver no mesmo computador que o binário sendo explorado e esse binário não esperar o estouro a partir de argumentos brutos, mas de uma entrada diferente que pode ser criada após a leitura deste arquivo. É possível para um atacante obter alguns endereços deste arquivo e construir offsets a partir deles para o exploit.
Para mais informações sobre este arquivo, consulte https://man7.org/linux/man-pages/man5/proc.5.html procurando por /proc/pid/stat
Tendo um vazamento
O desafio é fornecer um vazamento
Se você receber um vazamento (desafios fáceis de CTF), você pode calcular offsets a partir dele (supondo, por exemplo, que você saiba a versão exata da libc que está sendo usada no sistema que está explorando). Este exploit de exemplo é extraído do exemplo daqui (verifique essa página para mais detalhes):
ret2plt
Aproveitando um estouro de buffer, seria possível explorar um ret2plt para exfiltrar um endereço de uma função da libc. Verifique:
pageRet2pltLeitura Arbitrária de Strings de Formato
Assim como no ret2plt, se você tiver uma leitura arbitrária via uma vulnerabilidade de strings de formato, é possível exfiltrar o endereço de uma função libc a partir do GOT. O seguinte exemplo está aqui:
Pode encontrar mais informações sobre a leitura arbitrária de strings de formato em:
pageFormat StringsRet2ret & Ret2pop
Tente contornar o ASLR abusando de endereços dentro da pilha:
pageRet2ret & Reo2popvsyscall
O mecanismo vsyscall
serve para melhorar o desempenho permitindo que certas chamadas de sistema sejam executadas no espaço do usuário, embora façam parte fundamentalmente do kernel. A vantagem crítica das vsyscalls está em seus endereços fixos, que não estão sujeitos ao ASLR (Randomização do Layout do Espaço de Endereços). Essa natureza fixa significa que os atacantes não precisam de uma vulnerabilidade de vazamento de informações para determinar seus endereços e usá-los em uma exploração.
No entanto, não serão encontrados gadgets super interessantes aqui (embora, por exemplo, seja possível obter um equivalente a ret;
)
(O exemplo e código a seguir são deste artigo)
Por exemplo, um atacante pode usar o endereço 0xffffffffff600800
dentro de uma exploração. Enquanto tentar pular diretamente para uma instrução ret
pode levar a instabilidade ou falhas após a execução de alguns gadgets, pular para o início de uma syscall
fornecida pela seção vsyscall pode ser bem-sucedido. Ao colocar cuidadosamente um gadget ROP que direcione a execução para este endereço vsyscall, um atacante pode obter execução de código sem precisar contornar o ASLR para esta parte da exploração.
vDSO
Note que pode ser possível burlar o ASLR abusando do vdso se o kernel for compilado com CONFIG_COMPAT_VDSO, pois o endereço do vdso não será randomizado. Para mais informações, consulte:
pageRet2vDSOLast updated