Si hace poco salía a la luz un fallo en el control de acceso a la memoria del kernel de Linux, ahora no menos sorprendente es la publicación de una vulnerabilidad de tipo format string en las versiones de sudo de la 1.8.0 a la 1.8.3p1, ambas inclusive.
Concretamente el fallo está en la función sudo_debug() introducida para el soporte de depuración en el desarrollo de políticas o en el logging de la E/S de algunos plugins:
src/sudo.c:
void
sudo_debug(int level, const char *fmt, ...)
{
va_list ap;
char *fmt2;
if (level > debug_level)
return;
/* Backet fmt with program name and a newline to make it a single
write */
easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
va_start(ap, fmt);
vfprintf(stderr, fmt2, ap);
va_end(ap);
efree(fmt2);
}
Como veis en el código anterior, el nombre de programa (getprogname()) es usado como parte del format string que se pasa a la función vfprintf(). Este nombre de programa puede ser controlado por el usuario (caller), incluso a través de un enlace simbólico o, en algunos sistemas, configurando el argumento argv[0] cuando se ejecuta sudo.
Por ejemplo:
/tmp $ ln -s /usr/bin/sudo %n
/tmp $ ./%n -D9
*** %n in writable segment detected ***
Aborted
/tmp $
El resultado que podéis observar, es debido a FORTIFY_SOURCE que hace la explotación difícil pero no imposible. Sin FORTIFY_SOURCE el exploit sería bastante sencillo:
1. Uso de formatstring para sobreescribir setuid() con setgid()
2. Trigger con formatstring -D9
3. Uso de SUDO_ASKPASS y preparación de un shellcode en el script de askpass
4. Como askpass es llamado después de que el formatstring ha sobreescrito el setuid(), el script askpass se ejecutará con el uid 0
5. Obtención de la rootshell
La solución: ya se ha publicado la versión de sudo 1.8.3p2 que soluciona esta vulnerabilidad.
Concretamente el fallo está en la función sudo_debug() introducida para el soporte de depuración en el desarrollo de políticas o en el logging de la E/S de algunos plugins:
src/sudo.c:
void
sudo_debug(int level, const char *fmt, ...)
{
va_list ap;
char *fmt2;
if (level > debug_level)
return;
/* Backet fmt with program name and a newline to make it a single
write */
easprintf(&fmt2, "%s: %s\n", getprogname(), fmt);
va_start(ap, fmt);
vfprintf(stderr, fmt2, ap);
va_end(ap);
efree(fmt2);
}
Como veis en el código anterior, el nombre de programa (getprogname()) es usado como parte del format string que se pasa a la función vfprintf(). Este nombre de programa puede ser controlado por el usuario (caller), incluso a través de un enlace simbólico o, en algunos sistemas, configurando el argumento argv[0] cuando se ejecuta sudo.
Por ejemplo:
/tmp $ ln -s /usr/bin/sudo %n
/tmp $ ./%n -D9
*** %n in writable segment detected ***
Aborted
/tmp $
El resultado que podéis observar, es debido a FORTIFY_SOURCE que hace la explotación difícil pero no imposible. Sin FORTIFY_SOURCE el exploit sería bastante sencillo:
1. Uso de formatstring para sobreescribir setuid() con setgid()
2. Trigger con formatstring -D9
3. Uso de SUDO_ASKPASS y preparación de un shellcode en el script de askpass
4. Como askpass es llamado después de que el formatstring ha sobreescrito el setuid(), el script askpass se ejecutará con el uid 0
5. Obtención de la rootshell
La solución: ya se ha publicado la versión de sudo 1.8.3p2 que soluciona esta vulnerabilidad.
Comentarios
Publicar un comentario