Cómo llamar a execve en C sin nombrarlo y evadir el corrector de la escuela
Calling a function in C without naming it
Un estudiante y su amigo sortean el sistema de calificación automática de su escuela, que verifica las funciones permitidas mediante el AST. Aprovechan que el código se compila con ASan para filtrar el offset entre printf y mmap, obtener una página ejecutable y lanzar cualquier syscall, incluido execve, logrando ejecución de shell. Un bypass de ASLR que demuestra que la seguridad por oscuridad no funciona.
En C, la inseguridad es una característica, así que podemos usar uniones.
- ashdnazg
Nuestra universidad era mucho menos cuidadosa, y simplemente ejecutaba nuestras entregas en la misma red que todo lo demás, aunque con un usuario con apenas permisos.
Una vez, cuando las pruebas automáticas hicieron fallar mi entrega, simplemente usé `system` para volcar la entrada de prueba en mi directorio home. Sin embargo, olvidé configurar los permisos, ¡así que no pude acceder a ella! Tras un par de reenvíos más con chmods adicionales, estropeando algo distinto cada vez, logré reproducir mi bug, arreglarlo, reenviar y purgar toda (o casi toda) la evidencia.
- Kevin_Flynn
Como sabemos que nuestro código se compila con ASan, optamos por filtrar el offset entre printf, una función que siempre está permitida, y mmap, una función que nos da ejecución arbitraria de código ensamblador. Así podemos saltarnos las comprobaciones de la escuela y llamar a cualquier syscall, en nuestro caso execve para obtener acceso a shell.
No investigamos más y simplemente reportamos este posible problema a la escuela.
No veo una forma trivial de parchear esto.
El fallo parece estar en el sistema de entrega.
El sistema de entrega podría compilar/reenlazar tu código con una librería trampolín donde el cuerpo de cada función a prohibir se reemplace con reporte de errores y abort. En tu ejemplo, atraparía:
char *code =
notmmap.fn(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
y evitaría que uses el flag PROT_EXEC durante la fase de ejecución de la validación de la entrega.
Según la IA, en linux: "... un filtro seccomp-BPF aplicado a cada proceso antes de que empiece a ejecutar el programa. Puede inspeccionar el argumento prot de mmap y devolver EPERM cuando PROT_EXEC está activado."
Además, en linux: "systemd ofrece MemoryDenyWriteExecute=yes para servicios. Eso es menos restrictivo que prohibir cada mapeo ejecutable: apunta a mapeos escribibles+ejecutables y formas relacionadas de hacer memoria ejecutable."
( SI ... leí el artículo correctamente )
ps. Envía las soluciones propuestas al jefe de tu departamento u otra figura de autoridad que pueda lanzarte algún tipo de hueso para que tu sol […]
- PeterWhittaker
Parece que la escuela necesita envolver las cosas en una lista de denegación de seccomp. Potencialmente no trivial, pero potencialmente interesante.
Requisitos: