bitcoin prize

EL EXPLOIT DE LA VAQUITA: ESCALADO DE PRIVILEGIOS CON VULNERABILIDAD DIRTY COW EN LINUX 💀💻📓🐄

"El Exploit De La Vaquita: Dirty-Cow y La elevacion de privilegios"

Linux Privilegue Scalation

una de las cosas mas interesantes al estar realizando una auditoria de cyberseguridad es la escalada de privilegios dentro del mismo nucleo del sistema operativo completo.
una de las vulnerabilidades con mas peligro son los fallos de seguridad que estan dentro del kernel o nucleo , ya que son aqui donde residen las propiedades fundamentales mas importantes de los sistemas operativos  ya que es aqui mismo donde residen y se especficican los distintos niveles que ya he mencionado en otras entradas en este mismo blog de investigacion.
el nivel protegido por el propio sistema operativo y el nivel de absraccion.


Este fallo de seguridad es muy temido por todos los que usamos linux y los que usan o usaran linux en su momento,   es un fallo de tipo de condicion de carrrera que no es capaz de validar bien las entradas de las cadenas dentro de determinadas funciones.

el exploit en si mismo esta codificado en lenguaje C al ser de los lenguajes padres de la programacion asi como es el lenguaje de programcacion en el que esta codificado el sistema operativo UNIX asi como el sistema operativo linux y us miles de distribuciones que existen alrededor del mundo.

vamos a ver en un ejemplo muy sencillo lo que es una condicion de carrera,  resumidas cuentas una condicion de carrera como lo dicho anteriormente es un fallo de seguridad en la que por ejemplo una cadena de caracteres o string estan mal validadas y en ocasiones pudiera ser que esto implique a hilos de ejecucion para acceder o tener que escribir, leer y ejecutar en multiples procesos,  por ejemplo si tenemos un programa x o una funcion x que tenga que  ejecutar en segundo plano algunas instrucciones esto dependera directamente de los hilos de ejecucion o mejor conocidos en ingles como Threads o tecnicas de programacion que hacen uso de multiples hilos de ejecucion como el Threading o Multi-Threading para realizar y mandar a segundo plano algunos procesos o instrucciones dentro de la funcion o script que estemos creando.

por ejemplo lo que logra el atacante es inyectar e introducir mediante un margen de tiempo que se abre dentro de la ejecucion de los hilos, el atacante es capaz de aprovecharse si dentro de un margen de tiempo los hilos de ejecucion estan abiertos escribiendo dentro de procesos del sistema e inyectar su codigo para explotar el sistema y aprovecharse de los privilegios en los cuales los hilos y los procesos se estan comunicando entre si.


bien, ahora que entendemos un poco de que va los fallos de seguridad de condicion de carrera o conditions race,  vamos a ver un sencillo ejemplo en python no muy complejo para entender por donde va este asuntillo :) 
 

#importando las librerias de Threading para hacer uso de los hilos de ejecucion y creacion de procesos del S.O
from threading import Thread
from time import sleep

contador = 0


def incrementar(by):
    global contador
    
    local_contador = contador
    local_contador += by
    
    sleep(0.1)
    
    
    contador = local_contador
    print(f'contador={contador}')
    
    
#creacion de los hilos de ejecucion

t1 = Thread(target=incrementar, args=(10,))
t2 = Thread(target=incrementar, args=(20,))

#inicializacion de los hilos de ejecucion
t1.start()
t2.start()


#esperar a que los hilos completen su ejecucion
t1.join()
t2.join()


print(f'The contador final es {contador}')




//
ANALICEMOS:

veamos,  primero importamos las librerias correspondientes para los hilos de ejecucion y la posterior creacion de los procesos determinados.
despues inicializamos una variable llamada contador es igual a 0.
creamos una funcion llamada incrementar con un argumento llamado by que es lo que utilizaremos posteriormente dentro de las instrucciones solicitadas.
inicializamos como una variable global a contador que la declaramos e inicializamos anteriormente con el valor a 0.

igualamamos la variable global contador a otra variable local para poder utilizarla dentro del ambito local de la funcion.
sumamos el valor de la variable contador local al argumento by dentro de la funcion.

mandamos llamar la funcion sleep() para esperarnos antes de ejecutar otro hilo 0.1 microsegundos.
por ultimo antes de salir de la funcion, imprimos el resultado del contador.

creamos los hilos de ejecucion y le pasamos los argumentos 10, 20 respectivamente.
inicializamos los hilos para su posterior ejecucion y creacion de procesos.
esperamos con la funcion join() a que los hilos finalicen su ejecucion correspondiente.
imprimimos nuevamente los resultados de la ejecucion de los hilos con los argumentos pasados.

puede parecer que no hay ningun fallo de seguridad o de programacion pero NO!,   aqui el error es que estamos mandando a ejecutar al mismo tiempo a los hilos y estos a su vez estan creando procesos tambien a la misma vez,  la funcion sleep() de nada sirve porque es solo para esperar ejecucion durante algunos microsegundos de ejecucion.

el resultado seria durante la ejecucion 10 o 20 respectivamente y no 30 como podriamos esperar de un restulado normal como una suma de la variable contador,  este es el error fatal, si un atacante logra acceder a cualesquiera de los dos espacios de memoria o de los procesos que se estan ejejcutando y creando en segundo plano en este script,  lograria entonces inyectar su propio codigo y asi lograr escalar privilegios o jalar los permisos de administrador por donde el proceso se esta creando y ejecutando el sistema operativo.

se supone que el resultado aqui tendria que ser 20 en orden dependiendo de la tecnica que se este utilizando para almacenar los hilos y ejecutarlos pero si se excede el tiempo en que el hilo permanece ejecutandose entonces el atacante podria aprovecharse de este fallo y lograr inyectar codigo malicioso.

afortunadamente para python existe el metodo de clase lock() y lock.acquire() que lo que realiza es bloquea un proceso antes que este sea finalizado y destruido posteriormente para prevenir que un atacante pueda ejecutar codigo dentro del proceso ejecutado.

tambien tenemos a nustra disposicion el lock.release() para liberar el bloqueo una vez el proceso sea ejecutado completamente para que un potencial atacante no pueda ejecutar su codigo no tenga tiempo para tener acceso a este mismo
  
  #objeto para bloquear los procesos e hilos de ejecucion
  lock = lock()
  
  
  #metodo para adquirir el bloque de ejecucion dentro de los hilos
  lock.acquire()
  
  #metodo para liberar el bloqueo de un hilo o proceso de ejecucion
  lock.release()
  
  
  
.

Ahora vamos a ver la vulnerabilidad en si misma,   vamos a ver primeramente la version del kernel para ver si cumple con los requisitos de ser vulnerable.

vemos que tenemos efectivamente un kernel vulnerable,  ahora veamos como es que lo podemos explotar consecuentemente.

procederemos a descargar el exploit y compilarlo con la herramienta integrada dentro de linux o el compliador de C conocido como gcc con sus respectivas opciones de ejecucion.
 
Una vez que hemos compilado el exploit escrito en C,  lo procederemos a ejecutar sin el usuario root  ya que esta es la verdadera magia del exploit,  inyecta su codigo dentro de codigo vulnerable que llama a la funcion o principales funciones que manda llamar al SUID,  el SUID es el script principal que controla los IDS de los usuarios por ejemplo el usuario root tiene su UID y los creados previamente tienen sus respectivos UIDS,  en el kernel de linux escrito en C hay un fallo que permite ejecutar sin privilegios e inyectar codigo maliocioso para modificar el SUID del usuario que nos encontremos convirtiendo asi a cualquier usuario en usuario root con todos los privilegios del sistema.



aterrador no?

Saludos.
The pentester.


DOCUMENTACION , IMAGENES,  REFERENCIAS Y ENLACES TECNICOS:

0 comments:

Publicar un comentario

My Instagram

Uso cookies para darte un mejor servicio.
Mi sitio web utiliza cookies para mejorar tu experiencia. Acepto Leer más