El patrón normal que solemos encontrar cuando estudiamos los exploit kits comienza con un sitio web legítimo que se infecta y se utiliza para redirigir en forma automática a sus visitantes hacia el contenido malicioso real. Con mucha frecuencia, se puede observar el uso de técnicas como la inyección iFrame y las redirecciones HTTP.
Sin embargo, esta semana, mientras investigábamos el tráfico de un exploit kit, encontramos una variante interesante. Notamos que el sitio web comprometido contenía un código que, de hecho, interactúa con el usuario, ya que muestra un mensaje falso acerca de un script que afecta el rendimiento del navegador:
El código responsable de esta interacción está en formato HTML inyectado, que se muestra únicamente si el navegador en uso es Internet Explorer. También podemos ver que parte de los datos se envía junto con la solicitud POST (volveremos a este punto más adelante):
Como es de esperar, al hacer clic tanto en "Cancel" como en "OK" se activa la misma solicitud POST para una página intermedia que, a su vez, redirige al visitante al Angler exploit kit, y devuelve un pequeño fragmento de código HTML y Javascript:
Ahora volvamos a los datos enviados junto con la solicitud POST. Podemos ver que está codificado en Base64, pero su decodificación arroja datos que parecen aleatorios:
>>> ua_base64 =
‘tlP7Vt89hmr1vjdAW8YqmDT/sGFiyxROsPBX45R6HxinEeZC+
YGrgEA0mmA3NDEJUYzgWm29EKShU2QPqxBXzVNMJvpfJN3QcVGGehPCNNXOlxo0JE94z0RTBgCq0VubolrWHmAexV14+
cqx6qILC6z1EZDl4JFYd32wrMZrhNinl47lzpnvXwPluNsmh0CA’
>>> base64.b64decode(ua_base64)
‘\xb6S\xfbV\xdf=\x86j\xf5\xbe7@[\xc6*\x984\xff\xb0ab\xcb\x14N\xb0\xf0W\xe3\x94z\x1f\x18\xa7\x11\xe6B\xf9\x81\xab\x80@4\x9a`741\tQ\x8c\xe0Zm\xbd\x10\xa4\xa1Sd\x0f\xab\x10W\xcdSL&\xfa_$\xdd\xd0qQ\x86z\x13\xc24\xd5\xce\x97\x1a4$Ox\xcfDS\x06\x00\xaa\xd1[\x9b\xa2Z\xd6\x1e`\x1e\xc5]x\xf9\xca\xb1\xea\xa2\x0b\x0b\xac\xf5\x11\x90\xe5\xe0\x91Xw}\xb0\xac\xc6k\x84\xd8\xa7\x97\x8e\xe5\xce\x99\xef_\x03\xe5\xb8\xdb&\x87@\x80′
Por el nombre de parámetro 'ua', podemos suponer que contiene la cadena Usuario-Agente del navegador, que en nuestra prueba sabemos que era:
“Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET4.0C; .NET4.0E; BOIE8;ENUSMSCOM)”.
¿Qué pasaría si se aplicara el cifrado XOR a todos los parámetros con la misma cadena de claves? Usemos este texto sin formato para obtener la cadena de claves mediante la aplicación del cifrado XOR a la cadena Usuario-Agente cifrada con base64 y ya decodificada, usando nuestro texto (en minúscula). Si la teoría es correcta, al usar la cadena de claves obtenida de esta manera para aplicar el cifrado XOR al valor del parámetro 'furl', debería arrojar como resultado la URL de la página de destino del Angler exploit kit:
import base64
def xor(message, key):
decrypted = “”
for i in range(0, len(message)):
decrypted += chr(ord(message[i]) ^ ord(key[i%len(key)]))
return(decrypted)
ua = “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET4.0C; .NET4.0E; BOIE8;ENUSMSCOM)”
ua_plaintext = ua.lower()
ua_base64 = “tlP7Vt89hmr1vjdAW8YqmDT/sGFiyxROsPBX45R6HxinEeZC+
YGrgEA0mmA3NDEJUYzgWm29EKShU2QPqxBXzVNMJvpfJN3QcVGGehPCNNXOlxo0JE94z0RTBgCq0VubolrWHmAexV14+
cqx6qILC6z1EZDl4JFYd32wrMZrhNinl47lzpnvXwPluNsmh0CA”
furl_base64 = “s0j1T4l+yCai5DANXd0gmz38sX5pwRVb/vhQpcU9Qlj8G6tQ5Nc=”
keystream = xor(base64.b64decode(ua_base64), ua_plaintext)
print “Decrypted furl:”
print(xor(base64.b64decode(furl_base64), keystream))
$ python angler-dexor.py
Decrypted furl:
hxxp://cct7m.xenybuvifd.net/4genk1met8
¡Comprobado!
Si lo normal es que los visitantes sean redirigidos automáticamente al exploit kit cuando visitan un sitio web comprometido, ¿para qué molestarse en mostrar antes un texto? Quizá sea para prevenir que sistemas automatizados (sandboxes de análisis de malware, bots de motores de búsqueda, etc.) logren llegar hasta el exploit kit, lo que les dificulta a los investigadores rastrear e investigar dicha amenaza.
El código malicioso que se estaba propagando en el momento de la investigación era Win32/PSW.Papras.CX
(SHA1: 7484063282050af9117605a49770ea761eb4549d).
Traducción del post de Sébastien Duquette en We Live Security.