Comunidad Underground Hispana  

Retroceder   Comunidad Underground Hispana > Foros De Consulta General > Revista E-Zine > Noticias

Respuesta Crear Nuevo Tema
 
Compartir en twitter LinkBack Herramientas Desplegado
Antiguo 28-ene-2012, 19:37   #1
Moderador
 
Avatar de pamda
 
Fecha de Ingreso: noviembre-2006
Ubicación: Digital nomad
Amigos 1
Mensajes: 827
Gracias: 96
Agradecido 44 veces en 33 mensajes.
Exclamation 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.

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.

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:

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 '/proc/#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

[Solo usuarios registrados pueden ver los links. REGISTRARSE]



Commit de la eliminación de la protección de escritura

[Solo usuarios registrados pueden ver los links. REGISTRARSE]



* Linux Local Privilege Escalation via SUID /proc/pid/mem Write

[Solo usuarios registrados pueden ver los links. REGISTRARSE]

__________________


"La imaginación es más importante que el conocimiento. El conocimiento es limitado, mientras que la imaginación no".Albert Einstein



Última edición por pamda; 01-feb-2012 a las 17:46
pamda está desconectado   Responder Citando
Antiguo 01-feb-2012, 11:27   #2
Moderador V2.0
 
Avatar de David Novikov
 
Fecha de Ingreso: agosto-2009
Ubicación: /dev/null
Amigos 4
Mensajes: 813
Gracias: 57
Agradecido 170 veces en 123 mensajes.
Predeterminado Respuesta: Elevación de privilegios en el kernel Linux y un exploit interesante

Ayyyyy esas etiquetas de [CODE] :b
__________________
(Python)

[Solo usuarios registrados pueden ver los links. REGISTRARSE]

(Python)

[Solo usuarios registrados pueden ver los links. REGISTRARSE]


David Novikov está desconectado   Responder Citando
El Siguiente Usuario Agradeció a David Novikov Por Este Mensaje:
pamda (01-feb-2012)
Antiguo 01-feb-2012, 17:47   #3
Moderador
 
Avatar de pamda
 
Fecha de Ingreso: noviembre-2006
Ubicación: Digital nomad
Amigos 1
Mensajes: 827
Gracias: 96
Agradecido 44 veces en 33 mensajes.
Predeterminado Respuesta: Elevación de privilegios en el kernel Linux y un exploit interesante

Cita:
Iniciado por David Novikov Ver Mensaje
Ayyyyy esas etiquetas de [CODE] :b
Ahi... mucho mejor

=)
__________________


"La imaginación es más importante que el conocimiento. El conocimiento es limitado, mientras que la imaginación no".Albert Einstein


pamda está desconectado   Responder Citando
Respuesta

Herramientas
Desplegado

Normas de Publicación
No puedes crear nuevos temas
No puedes responder mensajes
No puedes subir archivos adjuntos
No puedes editar tus mensajes

Los Códigos BB están Activado
Las Caritas están Activado
[IMG] está Activado
El Código HTML está Desactivado
Trackbacks están Activado
Pingbacks están Activado
Refbacks están Activado


Temas Similares
Tema Autor Foro Respuestas Último mensaje
0 day: Elevación de privilegios en Microsoft Windows [251110] pamda Noticias 0 25-nov-2010 07:25
Error de regresión en el kernel Linux [09/2010] pamda Noticias 0 21-sep-2010 09:34
Actualización del kernel para SuSE Linux Enterprise 10 [040910] pamda Noticias 0 04-sep-2010 13:41
Vulnerabilidades locales en el kernel Linux [250810] pamda Noticias 0 25-ago-2010 12:31
interesante (y peligroso) fallo en el kernel Linux 2.6 [180810] pamda Noticias 0 18-ago-2010 21:38


La franja horaria es GMT -5. Ahora son las 05:03.


MegaTareas Ente MX Monografias Hacker Descargar Musica juegos de bob esponja
Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.6.0