.. | ||
README.md | ||
ret2plt.md |
ASLR
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Información Básica
Address Space Layout Randomization (ASLR) es una técnica de seguridad utilizada en sistemas operativos para aleatorizar las direcciones de memoria utilizadas por los procesos del sistema y de la aplicación. Al hacerlo, se dificulta significativamente que un atacante prediga la ubicación de procesos y datos específicos, como la pila, el montón y las bibliotecas, mitigando así ciertos tipos de exploits, particularmente desbordamientos de búfer.
Verificando el Estado de ASLR
Para verificar el estado de ASLR en un sistema Linux, puedes leer el valor del archivo /proc/sys/kernel/randomize_va_space
. El valor almacenado en este archivo determina el tipo de ASLR que se está aplicando:
- 0: Sin aleatorización. Todo es estático.
- 1: Aleatorización conservadora. Las bibliotecas compartidas, la pila, mmap(), la página VDSO están aleatorizadas.
- 2: Aleatorización completa. Además de los elementos aleatorizados por la aleatorización conservadora, la memoria gestionada a través de
brk()
está aleatorizada.
Puedes verificar el estado de ASLR con el siguiente comando:
cat /proc/sys/kernel/randomize_va_space
Deshabilitando ASLR
Para deshabilitar ASLR, debes establecer el valor de /proc/sys/kernel/randomize_va_space
en 0. Deshabilitar ASLR generalmente no se recomienda fuera de escenarios de prueba o depuración. Aquí tienes cómo puedes deshabilitarlo:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
También puedes deshabilitar ASLR para una ejecución con:
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args
Habilitando ASLR
Para habilitar ASLR, puedes escribir un valor de 2 en el archivo /proc/sys/kernel/randomize_va_space
. Esto generalmente requiere privilegios de root. La habilitación de la aleatorización completa se puede hacer con el siguiente comando:
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
Persistencia a Través de Reinicios
Los cambios realizados con los comandos echo
son temporales y se restablecerán al reiniciar. Para hacer que el cambio sea persistente, necesitas editar el archivo /etc/sysctl.conf
y agregar o modificar la siguiente línea:
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR
Después de editar /etc/sysctl.conf
, aplica los cambios con:
sudo sysctl -p
Esto asegurará que la configuración de ASLR se mantenga a través de reinicios.
Bypasses
Fuerza bruta de 32 bits
PaX divide el espacio de direcciones del proceso en 3 grupos:
- Código y datos (inicializados y no inicializados):
.text
,.data
, y.bss
—> 16 bits de entropía en la variabledelta_exec
. Esta variable se inicializa aleatoriamente con cada proceso y se suma a las direcciones iniciales. - Memoria asignada por
mmap()
y bibliotecas compartidas —> 16 bits, llamadadelta_mmap
. - La pila —> 24 bits, referida como
delta_stack
. Sin embargo, utiliza efectivamente 11 bits (del 10º al 20º byte inclusive), alineados a 16 bytes —> Esto resulta en 524,288 posibles direcciones de pila reales.
Los datos anteriores son para sistemas de 32 bits y la entropía final reducida hace posible eludir ASLR al reintentar la ejecución una y otra vez hasta que el exploit se complete con éxito.
Ideas de fuerza bruta:
- Si tienes un desbordamiento lo suficientemente grande para alojar un gran NOP sled antes del shellcode, podrías simplemente forzar direcciones en la pila hasta que el flujo salte sobre alguna parte del NOP sled.
- Otra opción para esto en caso de que el desbordamiento no sea tan grande y el exploit se pueda ejecutar localmente es posible agregar el NOP sled y el shellcode en una variable de entorno.
- Si el exploit es local, puedes intentar forzar la dirección base de libc (útil para sistemas de 32 bits):
for off in range(0xb7000000, 0xb8000000, 0x1000):
- Si atacas un servidor remoto, podrías intentar forzar la dirección de la función
usleep
delibc
, pasando como argumento 10 (por ejemplo). Si en algún momento el servidor tarda 10s extra en responder, encontraste la dirección de esta función.
{% hint style="success" %} En sistemas de 64 bits, la entropía es mucho mayor y esto no es posible. {% endhint %}
Información Local (/proc/[pid]/stat
)
El archivo /proc/[pid]/stat
de un proceso siempre es legible por todos y contiene información interesante como:
- startcode & endcode: Direcciones por encima y por debajo con el TEXT del binario
- startstack: La dirección del inicio de la pila
- start_data & end_data: Direcciones por encima y por debajo donde está el BSS
- kstkesp & kstkeip: Direcciones actuales de ESP y EIP
- arg_start & arg_end: Direcciones por encima y por debajo donde están los argumentos cli.
- env_start & env_end: Direcciones por encima y por debajo donde están las variables de entorno.
Por lo tanto, si el atacante está en la misma computadora que el binario que se está explotando y este binario no espera el desbordamiento de argumentos en bruto, sino de una entrada diferente que se puede crear después de leer este archivo. Es posible que un atacante obtenga algunas direcciones de este archivo y construya offsets a partir de ellas para la explotación.
{% hint style="success" %}
Para más información sobre este archivo, consulta https://man7.org/linux/man-pages/man5/proc.5.html buscando /proc/pid/stat
{% endhint %}
Tener un leak
- El desafío es dar un leak
Si se te da un leak (desafíos CTF fáciles), puedes calcular offsets a partir de él (suponiendo, por ejemplo, que conoces la versión exacta de libc que se utiliza en el sistema que estás explotando). Este ejemplo de explotación se extrae de el ejemplo de aquí (consulta esa página para más detalles):
from pwn import *
elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()
p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)
libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
0x0, # return address
next(libc.search(b'/bin/sh'))
)
p.sendline(payload)
p.interactive()
- ret2plt
Abusando de un desbordamiento de búfer, sería posible explotar un ret2plt para exfiltrar una dirección de una función de la libc. Ver:
{% content-ref url="ret2plt.md" %} ret2plt.md {% endcontent-ref %}
- Format Strings Lectura Arbitraria
Al igual que en ret2plt, si tienes una lectura arbitraria a través de una vulnerabilidad de cadenas de formato, es posible exfiltrar la dirección de una función de libc desde el GOT. El siguiente ejemplo es de aquí:
payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|'
payload += b'%3$s' # The third parameter points at the start of the buffer
# this part is only relevant if you need to call the main function again
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])
Puedes encontrar más información sobre la lectura arbitraria de cadenas de formato en:
{% content-ref url="../../format-strings/" %} format-strings {% endcontent-ref %}
Ret2ret & Ret2pop
Intenta eludir ASLR abusando de direcciones dentro de la pila:
{% content-ref url="../../stack-overflow/ret2ret.md" %} ret2ret.md {% endcontent-ref %}
{% hint style="success" %}
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.