Random IRC quote :      <pancake> acaba de llegar una caja de 100 condones de sabores <pancake> a la oficina

Un IDS para reverse(«elcaro»)

Desempolvando viejas cosas me he encontrado con una prueba de concepto de un IDS para el protocolo propietario Oracle TNS que escribí hace ya algún tiempo y he decidido que mejor que dejarlo morir o enviarlo a /dev/null sería compartirlo con el mundo por si a alguien le pareciera interesante.

Oracle TNS Protocol

El protocolo TNS es un protocolo binario y cerrado utilizado en la comunicación entre cliente y servidor de bases de datos Oracle. Este protocolo no es muy conocido y no existen muchas aportaciones públicas que ayuden a conocer mejor el protocolo exceptuando la herramienta «tnscmd», su documentación asociada, los «diseccionadores» de paquetes TNS de Wireshark y una librería que hice yo para el proyecto Inguma.

La motivación de esta herramienta

Dentro del protocolo TNS hay algunos tipos de paquetes en los cuáles se envían datos en texto plano en el formato siguiente:

((comando=valor)(otrocomando=valor))

Son las denominadas cadenas «NV». En los primeros paquetes que se envían (paquetes de tipo TNS_TYPE_CONNECT) se le pasa del cliente al servidor una serie de datos en este formato tales como el nombre del usuario del sistema operativo, programa que se está ejecutando (por ejemplo, el SQL*Plus), la máquina, el comando a ejecutar y otra serie de datos. Ejemplo de paquete:

(CONNECT_DATA=(SID=sid)(global_dbname=dbname)(CID=(PROGRAM=C:\odio\a\gabri.exe)(HOST=meodio.com)(USER=GGG))

En este ejemplo se puede ver como se pasan algunos parámetros tales como el SID o el nombre global de la base de datos. Otros de los datos mencionados (usuario del sistema operativo, programa, máquina, etc…) son datos que se utilizan en programas como Oracle Database Vault para intentar evitar que usuarios que no se encuentren dentro de un determinado rango de IPs o que no sean el usuario XXX no puedan hacer algunas tareas (como por ejemplo prohibir que si no es el usuario «jefe» no pueda modificar la tabla «nominas»). El problema es que, como he dicho, estos campos se envían en el paquete, siendo perfectamente posible para un atacante envíar lo que se le ponga de la punta del capuyo y pasarse por el arco del triunfo las «restricciones» que se impongan con este tipo de reglas en Oracle Database Vault. Si modificásemos un paquete de conexión normal y pusiésemos los datos que he dado de ejemplo, nos conectaríamos perfectamente y el DBA podría ver seleccionando datos desde la vista V$SESSION que «el diablo» está conectado desde el host «meodio.com».

Por si esto que cuento fuera poco, alguien podría pensar: «Bueno, pero en los logs del TNS Listener tendré la dirección IP del que ha estado jugando». Si estás usando la versión de la base de datos Oracle 11g pues entonces sí, de lo contrario (90% del mundo-mundial), pues no. ¿Quién querría tener en sus logs desde que dirección IP se ha conectado alguien y para qué? Si es que lo queremos todos…

Debido a todos estos problemas y a otros muchos me decidí a hacer una herramienta que, en ocasiones, me podía venir bien para averiguar si alguien estaba jugando con las bases de datos que estaban a mi cargo y que incluso me podría valer como un proxy del protocolo TNS para evitar posibles ataques. Esta herramienta que me hice, que es poco más que una prueba de concepto, se llama tnsids y la tenéis disponible aquí.

Ejemplo de uso

TNSIDS puede ejecutarse en modo pasivo sniffando tráfico de red («se lo traga todo» y no afecta al rendimiento de la base de datos) o en modo proxy (pasas siempre por mitad de esta herramienta y la base de datos si que se nota resentida). Si alguna de las reglas que tiene por defecto definidas (en $DIR/rules) se viola se generará una alerta al estilo de la siguiente:

$ sudo python ./tnsids.py
TNS Intrusion Detection System v1.0
Copyright (c) 2008, 2010 Joxean Koret

[Wed Jun 23 21:16:40 2010-ID:1277320600.54-947] Alert generated for 127.0.0.1:13185->127.0.0.1:1521
[Wed Jun 23 21:16:40 2010-ID:1277320600.54-947] ALERT-High: Non safe command executed ('STOP')
[Wed Jun 23 21:16:40 2010-ID:1277320600.55-501] Alert generated for 127.0.0.1:13185->127.0.0.1:1521
[Wed Jun 23 21:16:40 2010-ID:1277320600.55-501] ALERT-Critical: Denial of service (STOP) attempt

Además de generar alertas y poder crearnos reglas nosotros (en python) nos deja también en el directorio «graphs» unos gráficos muy bonitos en el que se muestra de donde han venido los paquetes utilizando Scapy (unos gráficos muy parecidos a el que se muestra aquí).

Bueno, eso es todo. Espero que os guste la herramienta!

3 Comentarios para “Un IDS para reverse(«elcaro»)”

  1. Comment por vierito5 | 06/23/10 at 4:02 pm

    ¿Quién querría logs con IPs? Eso es de perroflautas

    Estos de Oracle nunca dejan de sorprender con sus decisiones.

  2. Comment por Ruben | 06/23/10 at 7:26 pm

    esta wachi!

  3. Comment por Amián | 06/23/10 at 7:43 pm

    Que webon! ya ahorita puso ELCARO jaja costome la tarde y media webada adivinarmelo. No mas quise escribirle mis felicitaciones!

Se han cerrado los comentarios