viernes, 24 de octubre de 2014

Análisis de un phishing

El método de propagación de los phishings, en su gran mayoría y casi por definición, sigue siendo el mismo desde hace bastantes años, a través de email. Hace unos días recibimos uno del Banco Santander Chile en el correo del laboratorio. El email, en su conjunto, estaba bien construido, con un lenguaje correcto y sencillo, que nos indicaba que nuestra "Clave 3.0" estaba bloqueada porque aún no se había verificado y nos invitaba a entrar para verificar los datos a través de un enlace.

El phishing que nos mostraba al pulsar en el enlace del correo se encontraba en un sitio vulnerado, cuyo tiempo de carga era un poco largo, por lo tanto esto nos hizo sospechar que el contenido no estaba alojado realmente en el mismo servidor, o que algo raro sucedía, como explicaremos más adelante.

A través de una escalada de directorios, nos encontramos que el servidor, por defecto, listaba el contenido de sus carpetas, y además, nos encontramos un archivo zip llamado "www.santander.cl.zip". Los atacantes suelen subir el kit de phishing comprimido a la página vulnerada y posteriormente extraerlo para tener el phishing listo. En este caso, olvidaron borrar el archivo zip después de extraerlo.

Teniendo ya el zip en nuestro poder nos permite analizarlo al detalle. Este tipo de oportunidades no se deben dejar pasar, pues suponen una valiosa fuente de información para nuestro trabajo de antifraude en el laboratorio.

Al descargarlo y descomprimirlo, observamos que como suponíamos, eran todos los archivos del phishing, así que procedimos a reproducirlo en local para estudiar su funcionamiento, que por su interés mostramos a continuación.

Lo que ve el usuario 

En primer lugar vamos a mostrar el funcionamiento desde el punto de vista del usuario/cliente afectado y posteriormente cómo el phishing almacena y utiliza los datos que le proporcionamos.

Al acceder a la página, se carga una copia falsa de la portada principal del banco. En ella, como buenos usuarios confiados, procedemos a introducir el RUT (número de identificación nacional para los habitantes de Chile) y la clave:


En este punto el phishing hace tres comprobaciones. En primer lugar el RUT y la clave deben tener un formato válido. Además, comprueba contra la página real del banco (por supuesto, en segundo plano), que las credenciales son correctas. En caso de que el RUT y clave tengan el "formato" adecuado pero no seamos clientes del banco (o nos hayamos equivocado en alguno de ellos), nos mostrará la siguiente pantalla de error, pidiéndonos que accedamos 15 minutos después, achacando un error en sus sistemas (y además con faltas ortográficas).


En caso contrario, es decir, somos clientes y nuestro RUT y clave son correctos, pasa a una pantalla en la que solicita la tarjeta de coordenadas completa, que además plantea de manera desorganizada, para parecer más real. Hay dos pequeños detalles en esta pantalla, y es que el phishing ha conseguido ya obtener el nombre y apellido del cliente y el número identificativo de la tarjeta de coordenadas (señalados en verde).


Una vez se rellenan todos los datos, reenvía al usuario a la página real del banco para levantar menos sospechas. En caso de que no se rellenaran todas las casillas o alguna de ellas no tuviera el formato correcto (2 dígitos numéricos), avisaría con un error y se quedaría a la espera para que se corrija.



Este es el proceso "visible" para el usuario, pero vamos a estudiar el código que hay detrás de esto.

Como se realiza el trabajo "sucio"

En primer lugar, el atacante hace uso en todo momento de la librería "cURL" de PHP. Esta facilita la realización de conexión HTTP sobre otro servidor, siendo capaz de mantener las sesiones y cookies, para facilitar bastante el trabajo.

En la primera pantalla, carga el contenido de la página original del banco "http://www.santander.cl/" haciendo uso de cURL. Esto hace que el tiempo de carga aumente, que fue una de las cuestiones que nos llamó la atención.


En el primer bloque de código hace la petición a la página real del banco y descarga el contenido en la variable "$html". En el segundo bloque reemplaza las rutas relativas por rutas absolutas, para que se carguen correctamente las imágenes y demás recursos de la web (JS, CSS) y que además los enlaces sean correctos. En el último bloque modifica la dirección de envío del formulario de identificación, escribiendo una dirección que mantiene bajo su control "?STP=login".

Posteriormente, para comprobar si el RUT y la clave introducidas por el usuario son correctas, vuelve a hacer una petición con cURL sobre la dirección real "https://www.santander.cl/transa/cruce.asp". En caso afirmativo continúa haciendo sendas peticiones sobre
"https://www.santander.cl/transa/segmentos/Menu/views/sections/vsTS.asp?sectionCode=TC1" y "https://www.santander.cl/transa/mensajeria2/pivote_superclave.asp" para obtener el nombre y apellido del cliente y número identificativo de la tarjeta de coordenadas respectivamente.

Toda esta información la mantiene guardada en la sesión de PHP para posteriormente usarla en el proceso de solicitud de la tarjeta de coordenadas, como pudimos ver en la tercera imagen. Todo con objeto de darle más credibilidad al phishing.

Pasamos al momento de generar la página en la que nos solicita la tarjeta de coordenadas.


Con la función GenerateCard() genera un array asociativo con todas las coordenadas y posteriormente, con el código remarcado, extrae coordenadas pseudo-aletorias del array y genera la tabla HTML para la petición de coordenadas.

Como hemos mostrado en la imagen anterior, las solicita de manera desordenada y además tiene 2 métodos de control para asegurarse, en cierto modo, que el usuario no se equivoca al introducirlas. El primero de los métodos es que el usuario debe introducir todas las coordenadas, no puede dejar ninguna en blanco. El segundo es que cada una de las coordenadas deben ser numéricas y tener al menos 2 dígitos. LONGCOORDS es una constante que está fijada a 2 en la cabecera del archivo (no se aprecia en la imagen).


Para terminar, guarda todo esto en un fichero de logs ("Logsdb.txt"), definido en la constante DB_FILE) en el servidor y además, lo manda por correo usando el servidor SMTP configurado en el servidor vulnerado.

La manera de guardar este archivo de logs también es bastante curiosa, pues si lo guardara en texto plano, cualquiera que conociera la ruta del archivo podría abrir el archivo "Logsdb.txt" y ya tendría el "trabajo hecho". Para ello, antes de guardar la información en el registro, la cifra.


Para comenzar la función de cifrado utiliza la variable $string que son los datos robados y la clave $key, que está definida en el código.

  • La línea 5 lo único que hace es extraer cada uno de los caracteres. 
  • La linea 6 extrae un carácter de la clave siguiendo este patrón: si el bucle sólo contuviera esta línea de código y la clave fuera "1234", nos generaría como resultado la cadena "412341234...", con la misma longitud que el texto de entrada. 
  • La línea 7 es la que en realidad hace el cifrado. Realiza una SUMA del valor en decimal de ambos caracteres (el del texto plano y el correspondiente de la clave) y después lo vuelve a transformar en carácter. 
  • La línea 8 concatena todos estos caracteres en la variable "$result". 
  • Para finalizar la función, devuelve el contenido de la variable "result", pero antes lo codifica en base64, ya que los caracteres generados pueden no quedar en el rango ASCII y generar problemas al almacenarlos en disco.

El cifrado es bastante débil, con un pequeño análisis estadístico se podría extraer el texto en claro. Basa la fortaleza del cifrado en lo que se conoce como "seguridad por oscuridad", es decir, se supone que nadie conoce el método excepto él.

Por comodidad, el atacante ha creado la página "index.php?STP=logers" en la que introduciendo un usuario y contraseña, que tiene previamente definidos en el código, se muestra todo el contenido de los logs en texto plano. Para ello utiliza el siguiente código, junto con una captura de los logs (obviamente no son datos reales):


En ella comprueba si el usuario ha introducido el usuario y la contraseña definidas en el código, si es así, muestra el contenido de todos los logs que tiene en el archivo, no sin antes descifrarlos con el método "Desofuscar()". Si no se introduce el usuario y la contraseña o son incorrectos, devuelve un formulario para hacer login.

Y para finalizar, vamos a explicar cómo funciona el método "Desofuscar()", aunque en realidad hace lo mismo que "Ofuscar()", pero a la inversa.



  • En la línea 4 decodifica el texto que tenía almacenado en base64. 
  • En la línea 6 extrae carácter a carácter de la cadena cifrada. 
  • En la línea 7 extrae el carácter correspondiente de la clave, exactamente igual que el método de cifrado. 
  • La línea 8 es la que se encarga realmente de descifrar. Cuando se cifraba se realizaba una suma de los valores en decimal de los caracteres, pues ahora se tiene que realizar la resta del valor almacenado menos la clave. Con ello obtenemos el carácter original. 
  • En la línea 10 concatena los resultados que tenía y cuando termina la cadena completa, la devuelve.

En resumen, el flujo de trabajo del phishing se resume en la siguiente imagen.


Conclusiones

Después de este pequeño estudio podemos sacar algunas conclusiones:
El objetivo final es claro, recoger la máxima información del cliente para posteriormente poder realizar transacciones ilegítimas. Las novedades que han llamado la atención a nuestro departamento antifraude son, en primer lugar, la validación contra la página web del banco, si bien es cierto que no es el primer caso, este banco lo hace un poco más fácil para el atacante, ya que no usa sistemas como el "CSRF token" (por ejemplo), lo cuál no elimina el riesgo, pero complicaría un poco el proceso.

Por otro lado, la forma de engañar al usuario utilizando su nombre real y el número exacto de su tarjeta de coordenadas. La mayoría de phishings que tratamos en nuestro departamento antifraude a diario no se molestan en extraer tanta información para simplemente mostrarla al usuario. En algunas ocasiones simplemente, en lugar del nombre, usan algo genérico como "Cargando...".

Y para terminar, la forma de guardar la información de los usuarios (cifrada) es de lo más interesante. No es un cifrado robusto, como ya hemos dicho anteriormente, pero también es cierto que pocos "phishers" se molestan en hacer esto, simplemente lo guardan en texto plano en algún archivo con nombre extraño.

El código también tiene referencias al sistema de autenticación por SMS, pero no hace uso de él. No sabemos si es por un mal desarrollo o simplemente porque el atacante todavía no han tenido usuarios reales para probarlo. Bien es cierto, que si finalmente se implanta este método (a través de SMS), la recogida de datos del phishing sería más compleja, lo que esperamos que alerte al usuario, porque se haría la transferencia fraudulenta en el mismo momento en que el usuario está introduciendo los datos en el phishing.
  

Antonio Sánchez

jueves, 4 de septiembre de 2014

APKProtect: desempaquetador de bytecode Dalvik dentro de una libreria nativa

En nuestro departamento de antifraude hemos analizado el APK de un troyano Android para envío de SMS, en él hemos encontrado una técnica de desempaquetado muy interesante. El malware usa una librería nativa integrada (libAPKProtect.so) en el APK para desempaquetar el bytecode Dalvik. Además de eso, implementa técnicas para hacer mas difícil el volcado de la memoria del proceso y extraer el bytecode Dalvik también implementa un control para terminar la ejecución en caso de que el APK haya sido reempaquetado. Entendemos que el lector está familiarizado con el entorno Android y con las herramientas para depurar las aplicaciones Android como ndk-gdb de la NDK de Android.



Al abrir el archivo "classes.dex" del APK que contiene el bytecode Dalvik, vemos que hay instrucciones que no fueron interpretadas porque los byte codes están cifrados. El cifrado dificulta la ingeniería inversa, evita que los sistemas automatizados inserten "hooks", etc.

Ejemplo de la funcion "onCreate" cifrada:












Recorriendo el archivo, vemos el constructor de la clase "APKMainAPP12D0C" que carga una librería llamada "APKProtect". El desempaquetador seguramente está dentro de la librería nativa. ¿Cómo? Sí, un desempaquetador de bytecode Dalvik está contenido en una librería nativa compilada para procesadores ARM. Necesitamos de depurar la librería nativa. Por eso, nos hemos inspirado en el blog "The Cobra Den" para configurar el entorno de depuración y la instalación de ndk-gdb de Google.


Cuando el malware carga la librería nativa con la función "loadLibrary", el sistema operativo llama a la funcion "On_JNILoad" de esa misma librería nativa. Depurando la librería, hemos puesto un breakpoint a esa función "On_JNILoad".

En esa función, la primera parte se encarga de  llamar a la función "ptrace" con el parámetro PTRACE_TRACEME. Evita el funcionamiento de todo tipo de depuradores como GDB al igual que tampoco funcionará cualquier tentativa de volcado de memoria.

En la segunda parte, el malware abre el archivo "/proc/self/maps" que contiene el mapeado de su memoria. Itera cada línea hasta encontrar la cadena "classes.dex", es decir la zona de memoria que contiene el mapa del archivo "classes.dex". Analizando esa misma línea, el malware conoce la localización en memoria del mapa del archivo "classes.dex".

Ejemplo del mapeado del codigo Dalvik en el proceso donde vemos que el archivo “classes.dex” esta mapeado entre la dirección 0x47c46000 y 0x47c53000.

47c46000-47c53000 r--p 00000000 1f:01 525 /data/dalvik-cache/data@app@google.service-1.apk@classes.dex

Luego el malware comprueba si es un DEX o un DEX optimizado (DEY) buscando la cadena "dex" o "dey". Si es un DEX, recoge 20 bytes y compara esos 20 bytes con bytes de su librería. Si no hay correspondencias, el malware lanza un hilo que termina la ejecución del proceso en un tiempo aleatorio. ¿Pero…? un momento, ¿20 bytes no es el tamaño de una firma SHA1? En la documentación de Google, vemos que cada archivo DEX tiene una firma SHA1 en su cabecera excepto los códigos optimizados (DEY). Sirve para asegurarse de la integridad del archivo, es decir que el archivo no fue modificado. Si el archivo fue modificado, vuelve a matar su proceso de la misma manera. Pensamos, que el malware comprueba eso para evitar todos los tipos de reempaquetado que consisten en desempaquetar, insertar hooks, y re-empaquetar.

Esta es la firma SHA1 del archivo "classes.dex" que hemos encontrado:
0x73 0xAD 0x50 0x7F 0x1C 0xC6 0x8A 0x4D 0x2E 0x8C 0xEE 0xF5 0xDA 0xF8 0xE7 0x7C 0x27 0x4D 0x97 0xE7

En la tercera parte, el malware recoge el bytecode Dalvik (dentro del map del archivo classes.dex), llama a la funcion mprotect para cambiar la proteccion de las paginas de memoria a escritura. Por cada parte del bytecode Dalvik cifrado, recoge cada byte (LDRB), aplica un Exclusive OR (EORS) con bytes de su libreria, y guarda el resultado (STRB) a la misma ubicacion. Cuando todas las partes estan decifradas, el malware llama de nuevo a la funcion “mprotect” para cambiar las paginas de memoria al modo lectura. Solo en modo lectura, porque es la maquina Dalvik quien va a leer los byte codes, ejecutarlos y no el procesador ARM :=).



Ahora que sabemos donde descifra el malware los bytecode, solo es necesario poner un breakpoint cuando ha terminado, es decir a la funcion "mprotect". Con el comando "dump memory /home/ubuntu/dump.bin 0x47c46000 0x47c53000" dentro de la consola de gdb, conseguimos un volcado de la memoria.  Solo falta abrir el volcado con un intérprete de bytecode Dalvik como IDA para ver el código descifrado.

La misma función "onCreate" pero descifrada: 

El desempaquetador APKProtect no fue diseñado por el autor de malware. En efecto, APKProtect es un producto que se encarga de proteger los APKs ante ingeniería inversa. Desafortunadamente, ayuda tanto a los buenos como a los malos.

Más información:

SHA256 de la muestra analizada  3aee81db24540fb6b3666a38683259fd32713187ec6e0b421da9b91bd216205f

NDK,

Debugging Apps with Native Code - part 1

Dalvik Executable Format

ApkProtect,



  
Laurent Delosières