
Exploit de bypass de ASLR y DEP/NX para ELF Linux x32/x64 con stack-spraying
Exploit de bypass de ASLR DEP/NX en Linux ELF x32/x64 con stack-spraying

Propiedades:
Dependencias:
Limitaciones:
Quizás hayas oído hablar del ataque de Heap Spraying? Bueno, Stack Spraying es similar, sin embargo, se consideraba poco práctico para la mayoría de los casos, especialmente ASLR en x86-64.
Mi trabajo demostrará lo contrario.
Para 32 bits, hay 2^32 (4 294 967 296) direcciones teóricas, no obstante, el kernel permitirá controlar solo aproximadamente la mitad de los bits (2^(32/2) = 65 536) para una ejecución en una memoria virtualizada, lo que significa que si controlamos más de 50 000 caracteres en la pila, casi con seguridad apuntaremos a nuestro shellcode, independientemente de la dirección, gracias a la redirección y retraducción del kernel. Según mis pruebas, incluso 100 o 10 caracteres son suficientes si la función llamada no contiene otras creaciones de variables, lo que permitirá un ataque de estilo ROP.
Esto se puede lograr usando variables de shell, que no están realmente limitadas a una longitud específica, pero el límite práctico es de alrededor de cien mil, de lo contrario saturará la TTY.
Por lo tanto, para explotar con éxito con cualquier shellcode, necesitamos poner un NOP sled después del shellcode en una variable de shell y simplemente explotar el binario con una dirección aleatoria. Ten en cuenta que el NOP sled no es necesario, esto es solo para universalizar el exploit.
En un sistema de 64 bits la situación es diferente, pero no tanto tras mi descubrimiento.
Por supuesto, no tendrías que cubrir todas las 2^64 posibilidades; de hecho, el kernel solo permite 48 bits, además una parte de ellos son predecibles y estáticos, lo que nos deja con aproximadamente 2^(4x8+5) (137 438 953 472) posibilidades.
He mencionado el límite de tamaño de las variables de shell, pero también hay un límite de cantidad, que parece ser de alrededor de 10, lo que nos permite almacenar un shellcode de 1 000 000 de caracteres, dejándonos solo con algunas decenas de miles de posibilidades que se pueden probar rápida y automáticamente. Sin embargo, esta vez necesitarás hacer fuerza bruta y usar NOP-sleds para hacer las cosas más rápidas.
Dicho esto, ASLR tanto en 32 como en 64 bits se puede omitir fácilmente en pocos minutos y con pocas líneas de shell...
El DEP/NX por otro lado, se puede omitir en x32 usando la técnica de return-to-libc combinándola con estudios estadísticos de diferentes SO, más específicamente, sus limitaciones e implementaciones de ASLR, lo que puede llevar a una explotación exitosa por 2 razones. La primera es que ASLR no es tan aleatorio en su elección y tiene algunas constantes y pobre entropía (fácil de adivinar la dirección de libC y cada SO tiene sus propias constantes). La segunda es esparcir el argumento shell para libC en el entorno (fácil de encontrar y pasarlo a libC).
Para concluir, DEP/NX en 32 bits se debilita debido a ASLR.
Se puede encontrar una descripción más detallada en el número de Hakin9-12-14.
Si has explotado al menos un desbordamiento de búfer en tu vida, puedes saltarlo, pero por si acaso:
apt install gcc libc6-dev-i386 || kill -9 $$
chmod u+x ASLRay.sh
sudo gcc -z execstack test.c -o test
sudo gcc -m32 -z execstack test.c -o test32
sudo chmod +s test test32
source ASLRay.sh test32 1024
source ASLRay.sh test 1024
source ASLRay.sh test 1024 \x31\x80...your_shellcode_here
sudo gcc -m32 test.c -o test32x
sudo chmod +s test test32
source ASLRay.sh test32x 1024
Para demostrar que el NOP-sled no es necesario para Debian x32:
!!! ADVERTENCIA !!! esto modificará tu /etc/passwd y cambiará los permisos de /etc/shadow, se recomienda ejecución en máquina virtual
chmod u+x PoC.sh
source PoC.sh
grep ALI /etc/passwd
En caso de que aún no funcione, solo añade algunos NOPs (\x90) al principio.
Para demostrar que ni siquiera la variable de entorno es necesaria para Debian x32:
chmod u+x PoC2.sh
source PoC2.sh
Por lo tanto, puedes poner tu shellcode en una variable y dar direcciones aleatorias a los registros para obtener una shell con ASLR, esto se debe al contexto específico donde la función solo tiene una variable que será sobrescrita, por lo que la pila será extraída a EIP solo con nuestro shellcode, lo que es más como un ataque ROP.
Para Arch/Ubuntu también necesitarás deshabilitar la protección contra stack smashing y la fuerza bruta puede tomar mucho más tiempo (retardo de ejecución, probablemente debido a la syscall brk(NULL/0) o/y canario):
sudo gcc -z execstack -fno-stack-protector test.c -o test
sudo gcc -m32 -z execstack -fno-stack-protector test.c -o test32
sudo gcc -m32 -fno-stack-protector test.c -o test32x
En Debian 10, este problema fue parcialmente parcheado, notablemente debido a AppArmor.
Confía siempre en múltiples protecciones y no en una sola.
Necesitamos nuevos mecanismos de seguridad en el sistema.
"Desde donde estamos la lluvia parece aleatoria. Si pudiéramos estar en otro lugar, veríamos el orden en ella. "
Tony Hillerman, Coyote Waits