ASLR
Last updated
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)
La Randomización del Diseño del Espacio de Direcciones (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 las aplicaciones. Al hacerlo, se vuelve significativamente más difícil para un atacante predecir la ubicación de procesos y datos específicos, como la pila, el montón y las bibliotecas, mitigando así ciertos tipos de exploits, especialmente los desbordamientos de búfer.
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. Se aleatorizan las bibliotecas compartidas, la pila, mmap(), la página VDSO.
2: Aleatorización completa. Además de los elementos aleatorizados por la aleatorización conservadora, la memoria gestionada a través de brk()
se aleatoriza.
Puedes verificar el estado de ASLR con el siguiente comando:
Para desactivar ASLR, estableces el valor de /proc/sys/kernel/randomize_va_space
en 0. Desactivar ASLR generalmente no se recomienda fuera de escenarios de prueba o depuración. Así es como puedes desactivarlo:
También puedes desactivar ASLR para una ejecución con:
Para habilitar ASLR, puedes escribir un valor de 2 en el archivo /proc/sys/kernel/randomize_va_space
. Esto suele requerir privilegios de root. La habilitación de la aleatorización completa se puede hacer con el siguiente comando:
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:
Después de editar /etc/sysctl.conf
, aplica los cambios con:
Esto asegurará que la configuración de tu ASLR se mantenga en reinicios.
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 variable delta_exec
. Esta variable se inicializa aleatoriamente en cada proceso y se suma a las direcciones iniciales.
Memoria asignada por mmap()
y bibliotecas compartidas —> 16 bits, llamado delta_mmap
.
La pila —> 24 bits, referido como delta_stack
. Sin embargo, efectivamente utiliza 11 bits (desde el byte 10 al 20 inclusive), alineados a 16 bytes —> Esto resulta en 524,288 posibles direcciones reales de pila.
Los datos anteriores son para sistemas de 32 bits y la entropía final reducida hace posible eludir ASLR intentando la ejecución una y otra vez hasta que el exploit se complete con éxito.
Si tienes un desbordamiento lo suficientemente grande para alojar un gran trineo NOP antes del código de la shell, podrías simplemente forzar direcciones en la pila hasta que el flujo salte sobre alguna parte del trineo NOP.
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 trineo NOP y el código de la shell 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):
Si estás atacando un servidor remoto, podrías intentar hacer fuerza bruta en la dirección de la función usleep
de libc
, pasando como argumento 10 (por ejemplo). Si en algún momento el servidor tarda 10 segundos adicionales en responder, encontraste la dirección de esta función.
En sistemas de 64 bits, la entropía es mucho mayor y esto no debería ser posible.
Es posible ocupar una gran parte del stack con variables de entorno y luego intentar abusar del binario cientos/miles de veces localmente para explotarlo. El siguiente código muestra cómo es posible simplemente seleccionar una dirección en el stack y cada pocas cientos de ejecuciones esa dirección contendrá la instrucción NOP:
/proc/[pid]/stat
)El archivo /proc/[pid]/stat
de un proceso siempre es legible por todos y contiene información interesante como:
startcode y endcode: Direcciones arriba y abajo con el TEXTO del binario
startstack: La dirección de inicio del stack
start_data y end_data: Direcciones arriba y abajo donde está el BSS
kstkesp y kstkeip: Direcciones actuales de ESP y EIP
arg_start y arg_end: Direcciones arriba y abajo donde están los argumentos de la línea de comandos
env_start y env_end: Direcciones arriba y abajo donde están las variables de entorno
Por lo tanto, si el atacante está en la misma computadora que el binario que está siendo explotado y este binario no espera el desbordamiento de argumentos sin procesar, sino de una entrada diferente que se puede crear después de leer este archivo. Es posible para un atacante obtener algunas direcciones de este archivo y construir desplazamientos a partir de ellas para el exploit.
Para más información sobre este archivo, consulta https://man7.org/linux/man-pages/man5/proc.5.html buscando /proc/pid/stat
El desafío es dar una fuga
Si se te da una fuga (desafíos fáciles de CTF), puedes calcular desplazamientos a partir de ella (suponiendo, por ejemplo, que conoces la versión exacta de libc que se está utilizando en el sistema que estás explotando). Este exploit de ejemplo se extrae del ejemplo de aquí (consulta esa página para más detalles):
ret2plt
Aprovechando un desbordamiento de búfer, sería posible explotar un ret2plt para extraer la dirección de una función de la libc. Verifique:
Ret2pltLectura Arbitraria de Cadenas de Formato
Al igual que en ret2plt, si tienes una lectura arbitraria a través de una vulnerabilidad de cadenas de formato, es posible extraer la dirección de una función de la libc desde el GOT. El siguiente ejemplo es de aquí:
Puedes encontrar más información sobre la lectura arbitraria de cadenas de formato en:
Format StringsIntenta evadir ASLR abusando de direcciones dentro de la pila:
Ret2ret & Reo2popEl mecanismo vsyscall
sirve para mejorar el rendimiento al permitir que ciertas llamadas al sistema se ejecuten en espacio de usuario, aunque son fundamentalmente parte del kernel. La ventaja crítica de las vsyscalls radica en sus direcciones fijas, que no están sujetas a ASLR (Randomización de Diseño del Espacio de Direcciones). Esta naturaleza fija significa que los atacantes no necesitan una vulnerabilidad de fuga de información para determinar sus direcciones y usarlas en un exploit.
Sin embargo, no se encontrarán gadgets muy interesantes aquí (aunque, por ejemplo, es posible obtener un equivalente a ret;
)
(El siguiente ejemplo y código es de este informe)
Por ejemplo, un atacante podría usar la dirección 0xffffffffff600800
dentro de un exploit. Mientras intentar saltar directamente a una instrucción ret
podría llevar a inestabilidad o bloqueos después de ejecutar un par de gadgets, saltar al inicio de una syscall
proporcionada por la sección vsyscall puede resultar exitoso. Colocando cuidadosamente un gadget ROP que lleve la ejecución a esta dirección de vsyscall, un atacante puede lograr la ejecución de código sin necesidad de evadir ASLR para esta parte del exploit.
Por lo tanto, ten en cuenta cómo podría ser posible burlar ASLR abusando del vdso si el kernel está compilado con CONFIG_COMPAT_VDSO ya que la dirección vdso no se randomizará. Para más información, consulta:
Ret2vDSO