16 mayo 2012

DNI-E Trojan KIT 1.0

El pasado marzo durante la RootedCon, presenté un prototipo de troyano que involucraba el uso fraudulento del Dni Electrónico.

EL concepto es simple: El DNIe como tal es prácticamente inviolable (acceso a las claves privadas, etc) pero en el momento que tiene que trabajar dentro de un sistema operativo, se vuelve vulnerable

Como expliqué en el turno de preguntas, mi intención era hacer algo basado enteramente en el API de windows, sin emplear hooking ni módulos en el Kernel.

Hoy libero el prototipo del troyano y explicaré su funcionamiento. Hay que destacar que el comportamiento es 'de troyano' pero no efectúa nada dañino. El objetivo es conectarse a la web de la DGT y extraer el saldo de puntos del poseedor del DNI de forma automatizada.

El primer paso es robar el PIN. Para este propósito el troyano utiliza dos métodos:

Keylogging: Es el método mas obvio, el DNIe como tal no aporta ningún tipo de seguridad frente a este tipo de ataques ya que 'caen' en la capa del sistema operativo. Tampoco el software que acompaña al DNIe ofrece ningún tipo de protección.

Obviamente no vale cualquier keylogger, hay que afinar el tiro y saber exactamente cuando logear.

Para ello tenemos que localizar exactamente cuando aparece la ventana que solicita el PIN del DNIe y logear las pulsaciones mientras está presente.

Windows tiene la función perfecta para ello: FindWindow(). Esta función permite localizar cualquier ventana buscándola por su 'caption'. Para averiguar cual es el caption de la ventana del DNIe, podemos usar un programa como WinSpy++ que permite obtener los datos de cualquier ventana.

Por lo tanto, el troyano lo que hace es quedar a la espera hasta que aparece esa ventana y, cuando aparece, usa la función GetAsyncKeyState() para obtener las pulsaciones del teclado.

Hay que señalar que falta por pulir bastante esta funcionalidad del troyano, ya que en estos momentos solo captura combinaciones tecla / número y no combinaciones del tipo @#$%, tampoco discrimina mayúsculas / minúsculas. Como prueba de concepto es suficiente, en sucesivas actualizaciones mejoraré este método.

IntraPhishing: Este método es mucho mas 'divertido' y se basa en un hecho que todo usuario del DNIe conoce bien: la cantidad de veces que sale la ventana de solicitud del PIN. Es muy frecuente y muy normal verla aparecer una y otra vez, lo que me lleva a plantearme la idea de: ¿Y si le envío al usuario una ventana idéntica de solicitud de PIN, pero controlada por mi? El resultado, probablemente, sea que el usuario meta su PIN y nos lo entregue en bandeja. Muy al estilo del Phishing tradicional cuando una web clona a otra.

 
Fake
Una vez el usuario introduzca el PIN, estará bajo nuestro control y podemos proceder a la siguiente fase.

Con el PIN en la mano, el siguiente paso es conectar a la web de la DGT para solicitar el saldo de puntos. La URL que nos lleva a ello es esta https://aplcr.dgt.es/WEB_COPACI/certificado/irAntecedentes.faces

Para llegar a ella vamos a usar Internet Explorer y su objeto OLE InternetExplorer.Application

Para el que no lo sepa, Internet Explorer (así como otros muchos programas) ponen a disposición del desarrollador lo que se denominan 'Objetos OLE/COM' que permiten automatizar tareas de forma desatendida. En el caso de Explorer, queremos que navegue hacia la web de la DGT.

Antes de eso, y dado que va a haber actividad en la pantalla del PC, es necesario que el troyano 'espere' a que el PC esté inactivo para realizar la navegación (van a verse las ventanas de solicitud del PIN) para ello usaremos la función GetLastInputInfo() que permite determinar el tiempo que un PC ha estado inactivo. En el caso del troyano, viene configurado para 6 segundos, obviamente en un escenario real, sería necesario una ventana de tiempo mayor.

Una vez el PC esté desatendido, el troyano instancia un Internet Explorer cuya ventana está oculta, y navega hacia la web de la DGT.

Problema: Vamos a necesitar rellenar varias veces la ventana de solicitud del PIN.

Solución: Lanzamos un hilo que constantemente esté buscando la ventana del DNIe y cuando aparezca, enviamos el PIN (que ya tenemos) haciendo uso de la función SendInput() que permite simular las pulsaciones del teclado.

Una vez completado el proceso, el troyano 'parsea' la respuesta de la web de la DGT y obtiene el saldo de puntos.

Aquí podéis ver un vídeo del troyano en acción con el modo IntraPhishing



Cabe destacar que si bien este 'kit' está adaptado al DNIe, usando estas mismas técnicas se podría atacar cualquier otra SmartCard.

En este ejemplo tan solo se ha obtenido una información más o menos confidencial pero se podría adaptar para, por ejemplo, obtener la declaración de la renta o modificar los datos fiscales

Podéis descargar 'DNI-E Trojan KIT' desde aquí

16 comments :

Angel Alvarez Nuñez dijo...

Muy bueno Yago, ¿algo de esto no ofrecias por twitter hace un tiempo, como para que no nos molestara tanto loggear ;) ? Creo recordar que antes de ir al episodio de Mundo Hacker, ¿podemos fiarnos de ti? Jajajaja.....
No ahora en serio muchas gracias por el aporte y la explicacion, un abrazo!!!

David dijo...

 Entiendo que es necesario que el DNIe esté insertado en el lector. Es decir, dejar el DNIe dentro solo para hacer el trámite que queramos es una medida de seguridad que funciona siempre.

tayoken dijo...

Hola Yago,

Dado que el PIN del DNIE-E se pide tantas y tantas veces, no podría simplemente hacer que se abriese una ventana oculta de IE para hacer "lo que sea" y simplemente surgiese el popup de introducir el PIN. El usuario acostumbrado a trabajar con DNI-E introduce el PIN varias veces (es un coñazo necesario).

De hecho, supongo que el PIN se pide cada vez que se realiza una operación de "AcquireContext" en el CSP del DNI-E. De manera que habrá más de una aplicación en background que pueda provocar el evento de introducir PIN, así que el usuario no notaría mucha diferencia con un comportamiento normal del DNI-E.

Y dicho esto, y hablando un poco más a bajo nivel ¿Sería posible "secuestrar" el "contexto" de una operación de CSP? Quiero decir: Una vez se realiza una operación de "obtener conetxto" (AcquireContext) lo que el CSP devuelve a la API (o lo que sea) es un handle, un puntero. Se podría hacer un troyano que se dedicase a escanear todo el rango continuamente en busca de ese "hprov" (el handle del contexto) haciendo una operación básica y rápida, por ejemplo getprovparam con PP_NAME para saber que es el handle del CSP del DNI-E.

Si me apuras, se puede hacer una operación getprovparam con parámetro PP_ADMIN_PIN para que te devuelva el PIN directamente.

Si el PIN del DNI-E sólo se pidiese en el momento de creación de contexto, habríamos "bypasseado" ese punto (si el contexto está activo, quiere decir que el usuario ya introdujo el pin) y podríamos hacer todas las operaciones criptográficas que quisésemos.

No lo he comprobado y no sé si sería factible encontrar ese handle y a partir de ahí realizar las operaciones criptográficas que queramos. De esta manera el usuario no se daría cuenta de nada y el troyano no necesitaría ni saber el PIN. Quizá hay otra operación (signhash, createhash...) que también requiera PIN, el usuario quizá se vea inundado de peticiones de PIN, no lo sé, es sólo una teoría.

Vaya, mientras escribía el comentario he hecho una POC y en principio ha funcionado con CSP's activos de microsoft. Habría que ver si también funciona con el CSP del DNI-E y si vuelve a pedir el PIN o no.

Juas, vaya chapa de comentario, sorry...

Saludos!

Yago Jesus dijo...

Yo no tengo nada claro que el CSP del DNIe soporte la misma funcionalidad que el CSP de microsoft. Sería increiblemente extraño que pudieses obtener el PIN de esa forma. Si lo pruebas, no olvides dar feedback !

De todas formas, una aproximación tal vez mas sencilla puede ser la que presentó Gabriel Gonzalez en la rooted 2011, creando su propio p11 y permitiendo acceso 'en remoto'.

No obstante, tiene el handicap de que es mucho mas intrusivo

Yago Jesus dijo...

 Son cosas diferentes, por un lado está AutoDNIE http://www.securitybydefault.com/2011/07/auto-dni-e.html que es una herramienta para automatizar el envío del PIN y otra esto.

Se basan en funcionalidades parecidas pero con propósito diferente.

Yago Jesus dijo...

 Absolutamente cierto. Y es una buena práctica el no dejar el DNI insertado en el lector

Angel Alvarez Nuñez dijo...

Jajajajaja gracias por la aclaracion, cuando vi el episodio de de MundoHacker pense "que cachondo Yago, como nos vacilo a todos"....culpa mia. Aunque como broma hubiera estado muy bien jejeje XD.
Gracias por aclaramelo Yago un saludo!!

tayoken dijo...

Bueno, quizá en cuanto a la opción del PP_ADMIN_PIN sería un fiasco si lo soportase, o no, ya que si lo estás pidiendo una vez hecho el "AcquireContext" es porque ya lo has introducido.

En cualquier caso, tampoco sería importante el PIN si conseguimos secuestrar el contexto, ya que no se nos debería volver a pedir para hacer operaciones del CSP.

Haré una prueba de concepto con un BHO que busque el handle cada vez que se cambie de url, por ejemplo, y ya veremos qué sale, aunque sospecho que el entorno de ejecución de un BHO es demasiado restrictivo para estas "invasiones"...

Mencuate dijo...

Usted lo único que demuestra es que windows es un sistema vulnerable, no que lo sea el DNI.

Yo también puedo llevarme su coche del garaje si usted es descuidado y deja la puerta de su casa abierta y las llaves del coche en el primer cajon que hay según se entra.

Saludos.

Yago Jesus dijo...

 Ciertamente, con las últimas versiones de Explorer parece que están hechas para desincentivar el uso de BHO

Yago Jesus dijo...

 Ya sabes, y dame un punto de apoyo y moveré el mundo.

Asdasdasd dijo...

¿Que el DNIe es vulnerable a phishing y sniffers?


Pues claro. ¿Es que alguien pensaba que seria invulnerable a este tipo de "ataques"?

Si nadie lo ha hecho hasta ahora no ha sido por falta de ingenio, si no porque es demasiado obvio como para hacer si quiera un post de ello.

Pero bueno, pues nada. Has confirmado que se puede hacer phishing también del DNIe. Felicidades. Quien lo hubiera dicho.

Yago Jesus dijo...

 Igual tu no has escrito el post porque confundes keyloggers y sniffers.

Por lo demás todo bien :)

pablog★ dijo...

Otra buena práctica: sacar el DNIe del lector cuando no se esté usando xP

Asdasdasd dijo...

Has hecho con mi comentario lo mismo que con el DNIe: señalar un fallo irrelevante.

En fin, que conste que considero entretenido tu post y el campo que abarca. Me resulta interesante. 

Lo unico que no me gusta es que -voluntariamente o no- estás dejando como cagancho en almagro una tecnologia muy cara y avanzada que actualmente es 100% segura... todo por un fallo de los sistemas operativos o quiza fallos que siempre existirán en TODO sistema. Y ello no invalida los sistemas informaticos. De hecho los sistemas informáticos cada vez se usan más a todos los niveles. 

Post como el tuyo dañan esta imagen y en cierto modo lo considero hacer el chorras. Aunque interesante y en fin, alguien tenia que hacerlo.

Un saludo.

Yago Jesus dijo...

 Punto uno, si quieres juzgar mi trabajo, enseñame el tuyo y lo comparamos.

Punto dos, insinuar que estas cosas hay que ocultarlas, que lo sepan unos cuantos y el resto de la gente viva con un peligro inadvertidamente es como decir que informar del daño de la radiación es 'atentar contra centrales nucleares que han costado mucho dinero, etc etc'

Un argumento pueril, sofista e irresponsable.

Nadie ha dicho que el DNI sea inseguro, vuelve a leer el post, subraya si no eres capaz de entenderlo o pide a alguien con mas entendederas que te lo explique, yo no voy a perder más tiempo.