Mostrando entradas con la etiqueta 0 day. Mostrar todas las entradas
Mostrando entradas con la etiqueta 0 day. Mostrar todas las entradas
sábado, 4 de febrero de 2012
Elevación de privilegios en el kernel Linux y un exploit interesante
El pasado día 17 de enero, Linus Torvalds hizo un commit para corregir una elevación de privilegios en el kernel Linux 2.6 (CVE-2012-0056). El fallo fue descubierto por Jüri Aedla y según comenta Torvalds en el
propio parche, se debe a una incorrecta comprobación de privilegios al abrir el /proc/#pid#/mem de un proceso.
Este error no pasó desapercibido a Jason A. Donenfeld que ha escrito y publicado un interesante exploit lo ha bautizado como 'Mempodipper'.
Donenfeld estudió en detalle el proceso de explotación. De partida se encontró con que efectivamente la comprobación de permisos era débil y además, que la protección contra escritura en el espacio de memoria del proceso fue eliminada del código del kernel. De hecho puede leerse en el comentario del commit correspondiente, que se eliminaba la restricción porque no se consideraba un peligro la escritura en /proc/#pid#/mem.
Esto hace virtualmente vulnerables a los núcleos con versión 2.6.39 o superior.
Cómo funciona:
Cuando se abre /proc/#pid#/mem se usa la función 'mem_open'. Dicha función almacena el 'self_exec_id' correspondiente al proceso que solicita la apertura. Esto se hace para comprobar posteriormente si son suficientes privilegios cuando se efectúan operaciones de lectura o escritura sobre el descriptor de fichero obtenido.
propio parche, se debe a una incorrecta comprobación de privilegios al abrir el /proc/#pid#/mem de un proceso.
Este error no pasó desapercibido a Jason A. Donenfeld que ha escrito y publicado un interesante exploit lo ha bautizado como 'Mempodipper'.
Donenfeld estudió en detalle el proceso de explotación. De partida se encontró con que efectivamente la comprobación de permisos era débil y además, que la protección contra escritura en el espacio de memoria del proceso fue eliminada del código del kernel. De hecho puede leerse en el comentario del commit correspondiente, que se eliminaba la restricción porque no se consideraba un peligro la escritura en /proc/#pid#/mem.
Esto hace virtualmente vulnerables a los núcleos con versión 2.6.39 o superior.
Cómo funciona:
Cuando se abre /proc/#pid#/mem se usa la función 'mem_open'. Dicha función almacena el 'self_exec_id' correspondiente al proceso que solicita la apertura. Esto se hace para comprobar posteriormente si son suficientes privilegios cuando se efectúan operaciones de lectura o escritura sobre el descriptor de fichero obtenido.
Código:
static int mem_open(struct inode* inode, struct file* file)
{
file->private_data = (void*)((long)current->self_exec_id);
En el caso de la operación de escritura se hace la comprobación del 'self_exec_id' además de llamar a 'check_mem_permission'. En teoría, para escribir en /proc/#pid#/mem, o se es el mismo proceso #pid# o el
proceso tiene ciertos permisos especiales relacionados con ptrace.
proceso tiene ciertos permisos especiales relacionados con ptrace.
Código:
static ssize_t mem_write(struct file * file, const char __user *buf,
size_t count, loff_t *ppos)
{
...
...
Se llama a 'check_mem_permission' y si 'mm' vuelve con error no se efectúa la operación:
Código:
mm = check_mem_permission(task); copied = PTR_ERR(mm); if (IS_ERR(mm)) goto out_free;
Código:
'check_mem_permission' simplemente llama a '__check_mem_permission' y como se observa dentro de su código efectúa la comprobación "task ==current":
Código:
static struct mm_struct *__check_mem_permission(struct task_struct
*task)
{
struct mm_struct *mm;
mm = get_task_mm(task);
if (!mm)
return ERR_PTR(-EINVAL);
if (task == current)
return mm;
...
...
Si no coinciden devuelve error. Luego debe ser el mismo proceso el que escriba en su propia memoria y si queremos elevar privilegios necesitaríamos un proceso con 'suid'.
Primera aproximación al exploit
Donenfeld se figuró cómo hacer esto:
$ su "yeeeee haw I am a cowboy"
Unknown id: yeeeee haw I am a cowboy
Cualquier cosa que se escriba pasa por la memoria del proceso creado por 'su' (que posee 'suid'). Parecia obvio qué hacer:
Abrimos '/proc/self/mem' y obtenemos su descriptor de archivo. Ejecutamos 'dup2' para multiplexarlo con 'stderr'. Escribimos nuestro shellcode en él y ejecutando posteriormente con exec obtendríamos root... pero no.
Esto no iba a funcionar debido a que aun queda otra restricción más:
Primera aproximación al exploit
Donenfeld se figuró cómo hacer esto:
$ su "yeeeee haw I am a cowboy"
Unknown id: yeeeee haw I am a cowboy
Cualquier cosa que se escriba pasa por la memoria del proceso creado por 'su' (que posee 'suid'). Parecia obvio qué hacer:
Abrimos '/proc/self/mem' y obtenemos su descriptor de archivo. Ejecutamos 'dup2' para multiplexarlo con 'stderr'. Escribimos nuestro shellcode en él y ejecutando posteriormente con exec obtendríamos root... pero no.
Esto no iba a funcionar debido a que aun queda otra restricción más:
Código:
if (file->private_data != (void *)((long)current->self_exec_id)) goto out_mm;
El 'self_exec_id' del proceso que va a ejecutar la escritura 'exec' ha de ser el mismo que abrió originalmente '/proc/#pid#/mem', recordad más arriba cuando se llama a 'mem_open'.
¿Por qué ha cambiado 'self_exec_id'?
Cuando se llama a 'exec' el 'self_exec_id', es aumentado en 1 impidiendo que esto ocurra:
Código:
void setup_new_exec(struct linux_binprm * bprm)
{
...
...
current->self_exec_id++;
Resumiendo. No podemos abrir el '/proc/#pid#/mem' de un proceso cualquiera, hacer 'dup2' con 'stderr' y luego hacer 'exec' de un proceso con 'suid' para escribir allí, ya que al hacer 'exec' no van a coincidir los 'self_exec_id'.
Donenfeld solucionó esto de manera sencilla pero ingeniosa, muy ingeniosa.
El exploit
Se hace 'fork' de un proceso y en este hijo se ejecuta 'exec' a un nuevo proceso. De este modo el 'self_exec_id', que se ha heredado del padre, ahora tiene un valor de +1 con respecto al padre.
Ahora hacemos que el padre ejecute 'exec' sobre un proceso 'suid' que va a escribir nuestro shellcode. En este momento, al ejecutar 'exec' en el padre su 'self_exec_id' acaba de aumentar a +1 coincidiendo con el del hijo.
Mientras tanto en el proceso 'exec' que ha llamado el hijo se obtiene, al abrir, el descriptor del '/pro /#parent_pid#/mem'; y es posible abrirlo porque no existe restricción en la operación de apertura. Es decir, no van a ser comprobados los privilegios del 'exec' que ha creado el hijo.
En este momento tenemos un 'exec' del padre con un proceso 'suid' dispuesto a escribir el shellcode. Un 'exec' del hijo con un descriptor del '/proc/#pid#/mem' del padre y la salida 'stderr' acoplada a ese descriptor (llamada a 'dup2') y lo más importante, tenemos los 'self_exec_id' igualados por lo tanto la restricción ha sido evadida.
Solo queda que el hijo pase el descriptor al padre y éste va a escribir el shellcode allí ya que cuando llame a 'mem_write', como hemos dicho, las comprobaciones van a ser correctas.
Pero aún queda más, averiguar "dónde" se debe escribir en memoria para poder ejecutar de manera exitosa el shellcode. Se necesita una dirección fija de memoria, algo que podría ser complicado si se usa ASLR, pero Donenfeld observó que la mayoría de binarios 'su' de las distribuciones no están compilados con 'PIE'(Position-independent executable)
Podemos observarlo si hacemos:
$ readelf -h /bin/su | grep Type
Type: EXEC (Executable file)
Como el mismo Donenfeld apunta, si el 'Type' fuera 'DYN' entonces si podría protegerse con ASLR debido a que el ejecutable permitiría ser reubicado en distintas posiciones de memoria. Al no ser el caso el desplazamiento en memoria siempre va a ser el mismo.
Buscando Donenfeld obtuvo la dirección 0x402178, correspondiente a una llamada a 'exit@plt'. Tan solo tenía que escribir en 0x402178 menos la longitud de la cadena 'Unknown id: ' y su shellcode se ejecutaría.
En definitiva, un exploit más interesante que la propia vulnerabilidad que explota y una muestra de ingenio por parte de Donenfeld al conseguir la explotación de la forma que hemos visto.
Donenfeld solucionó esto de manera sencilla pero ingeniosa, muy ingeniosa.
El exploit
Se hace 'fork' de un proceso y en este hijo se ejecuta 'exec' a un nuevo proceso. De este modo el 'self_exec_id', que se ha heredado del padre, ahora tiene un valor de +1 con respecto al padre.
Ahora hacemos que el padre ejecute 'exec' sobre un proceso 'suid' que va a escribir nuestro shellcode. En este momento, al ejecutar 'exec' en el padre su 'self_exec_id' acaba de aumentar a +1 coincidiendo con el del hijo.
Mientras tanto en el proceso 'exec' que ha llamado el hijo se obtiene, al abrir, el descriptor del '/pro /#parent_pid#/mem'; y es posible abrirlo porque no existe restricción en la operación de apertura. Es decir, no van a ser comprobados los privilegios del 'exec' que ha creado el hijo.
En este momento tenemos un 'exec' del padre con un proceso 'suid' dispuesto a escribir el shellcode. Un 'exec' del hijo con un descriptor del '/proc/#pid#/mem' del padre y la salida 'stderr' acoplada a ese descriptor (llamada a 'dup2') y lo más importante, tenemos los 'self_exec_id' igualados por lo tanto la restricción ha sido evadida.
Solo queda que el hijo pase el descriptor al padre y éste va a escribir el shellcode allí ya que cuando llame a 'mem_write', como hemos dicho, las comprobaciones van a ser correctas.
Pero aún queda más, averiguar "dónde" se debe escribir en memoria para poder ejecutar de manera exitosa el shellcode. Se necesita una dirección fija de memoria, algo que podría ser complicado si se usa ASLR, pero Donenfeld observó que la mayoría de binarios 'su' de las distribuciones no están compilados con 'PIE'(Position-independent executable)
Podemos observarlo si hacemos:
$ readelf -h /bin/su | grep Type
Type: EXEC (Executable file)
Como el mismo Donenfeld apunta, si el 'Type' fuera 'DYN' entonces si podría protegerse con ASLR debido a que el ejecutable permitiría ser reubicado en distintas posiciones de memoria. Al no ser el caso el desplazamiento en memoria siempre va a ser el mismo.
Buscando Donenfeld obtuvo la dirección 0x402178, correspondiente a una llamada a 'exit@plt'. Tan solo tenía que escribir en 0x402178 menos la longitud de la cadena 'Unknown id: ' y su shellcode se ejecutaría.
En definitiva, un exploit más interesante que la propia vulnerabilidad que explota y una muestra de ingenio por parte de Donenfeld al conseguir la explotación de la forma que hemos visto.
Más información:
Parche de Linus Torvalds
Commit de la eliminación de la protección de escritura
* Linux Local Privilege Escalation via SUID /proc/pid/mem Write
lunes, 29 de noviembre de 2010
0 day: Elevación de privilegios en Microsoft Windows
Se ha públicado un nuevo 0 day en Microsoft Windows que permite a un usuario local obtener privilegios de SYSTEM (control total sobre el sistema) eludiendo cualquier control de usuario.
Los detalles técnicos se han hecho públicos, así como el código fuente y el programa necesarios para aprovechar el fallo. El exploit se aprovecha de la forma en la que el controlador win32k.sys procesa ciertos valores del registro. En concreto, el exploit manipula el valor SystemDefaultUEDCFont del registro y activa el soporte para EUDC (End-User-Defined-Characters) a través de la función EnableEUDC.
Esto quiere decir que el atacante debe crear una clave en el registro donde un usuario no administrador tiene privilegios para hacerlo. Luego intenta leerla, provoca el fallo en el driver y obtiene los privilegios.
La prueba de concepto utiliza esta clave:
HKEY_USERS\[SID DEL USUARIO]\EUDC
La prueba de concepto funciona perfectamente en Windows Vista, 7 y 2008 totalmente parcheados. Tanto si el usuario pertenece al grupo de usuarios como al de administradores (incluso con la protección UAC activa), se obtendrán privilegios sin ningún tipo de advertencia por parte de Windows y por supuesto, sin necesidad de conocer la contraseña.
En Windows XP, la prueba de concepto no funciona (no existe por defecto esa rama del registro) pero es posible que la vulnerabilidad también le afecte. La prueba de concepto no es detectada por ningún motor en estos momentos:
VirusTotal - Free Online Virus, Malware and URL Scanner
Para que este fallo fuese aprovechado por un atacante o malware, primero debería acceder al sistema por cualquier otro medio y encontrarse con que no puede realizar los cambios que desea a causa de los permisos. Realmente, este no suele ser un impedimento para el malware masivo (puesto que el usuario medio suele o bien obviar el UAC o bien deshabilitarlo o bien en XP pertenecer al grupo de administradores). Sí que es posible que este fallo sea usado en ataques dirigidos o entornos profesionales, donde los usuarios de escritorio suelen tener privilegios limitados en el dominio.
Con este fallo, ya son dos problemas de elevación de privilegios que Microsoft debe arreglar. El fallo anterior fue descubierto en el cuerpo del famoso troyano Stuxnet. A través del programador de tareas, el
malware era capaz de elevar privilegios en el equipo infectado. Hace algunos días los detalles de esta vulnerabilidad también se hicieron públicos.
El equipo de seguridad de Microsoft ha declarado en su twitter que está investigando el asunto. Un método para prevenir el problema hasta que exista parche oficial es limitar los permisos del usuario en la rama
HKEY_USERS\[SID DEL USUARIO]\EUDC
En el registro, se debe negar el permiso de escritura a los usuarios no administradores. Gráficamente, es sencillo (localizar el SID del usuario, botón derecho sobre la rama del registro y denegar).
Para automatizar el proceso, aconsejamos (aunque puede tener efectos secundarios, hágalo bajo su responsabilidad) utilizar subinacl.exe, una herramienta oficial de Microsoft descargable desde:
Download details: SubInACL (SubInACL.exe)
Una vez instalada, localizar el SID del usuario (normalmente terminará en 1000) y el nombre de máquina y usuario con el comando:
whoami /user:
INFORMACIÓN DE USUARIO
----------------------
Nombre de usuario SID
==============================================
ordenador\usuario S-1-5-21-123456789-12345677889-123445678990-1000
y ejecutar:
subinacl.exe /subkeyreg "HKEY_USERS\ S-1-5-21-123456789-12345677889-123445678990-1000\EUDC /deny= ordenador\usuario=w
Esto evitará que el usuario pueda escribir en esa rama y por tanto la prueba de concepto no funcionará. Repetir para el resto de usuarios en el equipo si los hubiera.
Más información:
POC:
http://www.exploit-db.com/sploits/uacpoc.zip
We 're investigating public PoC for a local EoP vuln requiring an account on the target system
Security Response (msftsecresponse) on Twitter
Los detalles técnicos se han hecho públicos, así como el código fuente y el programa necesarios para aprovechar el fallo. El exploit se aprovecha de la forma en la que el controlador win32k.sys procesa ciertos valores del registro. En concreto, el exploit manipula el valor SystemDefaultUEDCFont del registro y activa el soporte para EUDC (End-User-Defined-Characters) a través de la función EnableEUDC.
Esto quiere decir que el atacante debe crear una clave en el registro donde un usuario no administrador tiene privilegios para hacerlo. Luego intenta leerla, provoca el fallo en el driver y obtiene los privilegios.
La prueba de concepto utiliza esta clave:
HKEY_USERS\[SID DEL USUARIO]\EUDC
La prueba de concepto funciona perfectamente en Windows Vista, 7 y 2008 totalmente parcheados. Tanto si el usuario pertenece al grupo de usuarios como al de administradores (incluso con la protección UAC activa), se obtendrán privilegios sin ningún tipo de advertencia por parte de Windows y por supuesto, sin necesidad de conocer la contraseña.
En Windows XP, la prueba de concepto no funciona (no existe por defecto esa rama del registro) pero es posible que la vulnerabilidad también le afecte. La prueba de concepto no es detectada por ningún motor en estos momentos:
VirusTotal - Free Online Virus, Malware and URL Scanner
Para que este fallo fuese aprovechado por un atacante o malware, primero debería acceder al sistema por cualquier otro medio y encontrarse con que no puede realizar los cambios que desea a causa de los permisos. Realmente, este no suele ser un impedimento para el malware masivo (puesto que el usuario medio suele o bien obviar el UAC o bien deshabilitarlo o bien en XP pertenecer al grupo de administradores). Sí que es posible que este fallo sea usado en ataques dirigidos o entornos profesionales, donde los usuarios de escritorio suelen tener privilegios limitados en el dominio.
Con este fallo, ya son dos problemas de elevación de privilegios que Microsoft debe arreglar. El fallo anterior fue descubierto en el cuerpo del famoso troyano Stuxnet. A través del programador de tareas, el
malware era capaz de elevar privilegios en el equipo infectado. Hace algunos días los detalles de esta vulnerabilidad también se hicieron públicos.
El equipo de seguridad de Microsoft ha declarado en su twitter que está investigando el asunto. Un método para prevenir el problema hasta que exista parche oficial es limitar los permisos del usuario en la rama
HKEY_USERS\[SID DEL USUARIO]\EUDC
En el registro, se debe negar el permiso de escritura a los usuarios no administradores. Gráficamente, es sencillo (localizar el SID del usuario, botón derecho sobre la rama del registro y denegar).
Para automatizar el proceso, aconsejamos (aunque puede tener efectos secundarios, hágalo bajo su responsabilidad) utilizar subinacl.exe, una herramienta oficial de Microsoft descargable desde:
Download details: SubInACL (SubInACL.exe)
Una vez instalada, localizar el SID del usuario (normalmente terminará en 1000) y el nombre de máquina y usuario con el comando:
whoami /user:
INFORMACIÓN DE USUARIO
----------------------
Nombre de usuario SID
==============================================
ordenador\usuario S-1-5-21-123456789-12345677889-123445678990-1000
y ejecutar:
subinacl.exe /subkeyreg "HKEY_USERS\ S-1-5-21-123456789-12345677889-123445678990-1000\EUDC /deny= ordenador\usuario=w
Esto evitará que el usuario pueda escribir en esa rama y por tanto la prueba de concepto no funcionará. Repetir para el resto de usuarios en el equipo si los hubiera.
Más información:
POC:
http://www.exploit-db.com/sploits/uacpoc.zip
We 're investigating public PoC for a local EoP vuln requiring an account on the target system
Security Response (msftsecresponse) on Twitter
Suscribirse a:
Entradas (Atom)

