¿Qué hace setresuid()
y setresgid()
hacer?
Para entender mejor este ejemplo, necesitamos echar un vistazo a estas dos funciones y los tres parámetros que toman.
De esta respuesta (y la página del manual de credenciales (7)):
En Linux, cada proceso tiene los siguientes identificadores de usuario y grupo:
-
ID de usuario real e ID de grupo real. Estos ID determinan quién es el propietario del proceso. Para resumir, esto es quién eres .
-
ID de usuario efectivo e ID de grupo efectivo. El núcleo utiliza estos ID para determinar los permisos que tendrá el proceso al acceder a recursos compartidos, como colas de mensajes, memoria compartida y semáforos. En la mayoría de los sistemas UNIX, estos ID también determinan los permisos al acceder a los archivos. Sin embargo, Linux utiliza los ID del sistema de archivos para esta tarea. Para resumir, esto es lo que puede hacer .
-
ID de usuario de conjunto guardado y ID de grupo de conjunto guardado. Estos ID se utilizan en los programas set-user-ID y set-group-ID para guardar una copia de los ID efectivos correspondientes que se establecieron cuando se ejecutó el programa. Un programa de ID de usuario establecido puede asumir y eliminar privilegios cambiando su ID de usuario efectivo entre los valores de su ID de usuario real y el ID de usuario establecido guardado. Para resumir, esto es quién eras antes .
Además, es importante entender el SetUID-Bit. Lo que hace es ejecutar un programa ejecutable con los derechos del propietario, no de quien lo llama.
Una seguridad nightmare
Su pregunta menciona específicamente que nightmare
es propiedad de root
y tiene el SetUID-Bit establecido. Lo que esto significa es que cualquier usuario que tenga permiso para ejecutar nightmare
esencialmente lo ejecuta como root
. Esto significa que todos los procesos secundarios de nightmare
- como se generan al llamar a system()
- también se ejecutan como root
.
Pero realmente ahora, ¿qué significa setresuid()
hacer?
¿En este contexto? Nada. Dado que el usuario ya está ejecutando cosas como root
, no afecta la explotación posterior de ninguna manera.
¿Podría usar /dev/tty
? ?
Esta pregunta no tiene mucho sentido en este contexto. Tienes que mirar el fragmento de código relevante para ver dónde está la cadena /dev/tty
viene.
if (open("/dev/tty", O_RDWR) != -1) {
fire();
rax = sub_4008d0();
}
Esto significa que el programa está intentando abrir /dev/tty
para leer y escribir y, si tiene éxito, llama a fire()
.
Nombrando una función bash /dev/tty()
, no obtiene los resultados deseados, como open()
requiere una ruta a un archivo como su primer parámetro. Es completamente independiente de bash
y no tiene concepto de funciones bash.
¿Qué pasa con puts()
? ?
Del mismo modo, esto no tiene mucho sentido. strings
no es una magia y no entiende el contexto. Todo lo que hace es buscar series de bytes que sean caracteres ASCII imprimibles.
puts()
es solo una función C que genera una cadena.
¿Qué pasa con /usr/bin/aafire
? ?
Si bien no lo intenté personalmente, parece que prácticamente /usr/bin/aafire
podría haberse utilizado en lugar de /usr/bin/sl -al
. Si esto no es correcto, comente y editaré esta parte.
¿Seguiría funcionando si se usara una ruta relativa?
¡Sí, en realidad incluso mejor! system()
llama internamente sh -c
, que tiene que resolver el $PATH
variable para encontrar sl
. Si la variable de ruta se modificó para incluir .
o cualquier otro directorio escribible por el usuario con mayor prioridad que /usr/bin
, entonces podría simplemente enlazar ./sl
a /bin/bash
.
¿Importa qué tipo de binario/ELF es el archivo SUID raíz?
Sí, porque el SetUID-Bit se ignora en los scripts de shell. Debe ser un ejecutable nativo.