DNS Abuse

Por XXX



Introducción.

Últimamente han aparecido en bugtraq una serie de mails tratando el tema de los abusos del protocolo DNS. DNS es el protocolo que se usa para convertir IPs numericas en Fully Qualified Domain Name (FQDN) y al revés.

No me extenderé mucho sobre la explicación del protocolo, siempre podeis consultar las RFCs que tratan todos los aspectos de DNS:

1031, 1032, 1033, 1034, 1035

Conceptos Básicos.

La función de un servidor DNS (Nameserver - NS ) es la de resolver IPs a nombres y al revés. Como funciona la resolución? Pues bien, pongamos un ejemplo:

Nuestro NS es ns.hispahack.org y el nombre que nos han dicho que resolvamos es "memo.lala.lelo.com".
Lo que hara nuestro nameserver es destripar la dirección en partes. Primero consultará a uno de los ROOT-nameservers de Inet quien sirve el dominio "com". El NS tiene una lista de estos ROOT-NS con sus IPs asociadas, luego no tiene que consultar ya que IPs tienen (sino no conseguiria resolver nunca nada). Bueno, pues consulta el dominio "com". Entonces obtiene la dirección del NS que sirve al dominio "com". A continuación pregunta a ese NS quien sirve el dominio "lelo". Obtiene la direccion de otro NS, a éste le pregunta quien sirve el dominio "lala", obtiene la direccion de otro NS y le pregunta que IP tiene la maquina "memo". Asi, ya ha obtenido la IP de "memo.lala.lelo.com", pongamos, por ejemplo, que es 123.123.123.123.

Aquí ha terminado el trabajo de nuestro NS, que además de resolver la dirección, la guarda en su cache para futuras consultas.
La cache es un registro de las últimas direcciones que resolvió el NS, por si se le consulta sobre éstas no tener que volver a resolverlas.

Nota: Éste es el funcionamiento de un NS que soporta la función de recursividad (la mayoria). Esto significa que si el NS no sirve la dirección que se le pide que resuelva, enviara la peticion a otro NS para que la resuelva, hasta obtener la resolución o un error de dirección irresoluble. Si el NS no tiene esta función de recursividad, simplemente, si sirve el dominio de la dirección que le pedimos que resuelva la resolvera, y sino nos dira que no puede resolverla, que nos busquemos la vida.

Por tanto, las vulnerabilidades que se explican mas adelante,

SOLO AFECTAN A SERVIDORES DNS QUE SOPORTAN RECURSION

Datagramas DNS.

El protocolo DNS se comunica por UDP, un protocolo de transporte sin conexión, es decir, que lanza el paquete a la red, y ya no se preocupa mas de él. Ésto imposibilita que se lleve un control del flujo de la conexión, correccion de errores, etc. Éste es un punto muy importante, pues UDP no puede, al contrario que TCP, mantener un flujo de comunicación entre dos hosts, con los ya conocidos sequence numbers.

Asi pues si queremos spoofear o meternos en medio de una conexion UDP no tendremos que predecir estos seqnums.
Podeis consultar la estructura de los datagramas DNS en la RFC 1035 si quereis datos más concretos sobre como funciona.

Dado que el protocolo de transporte no identifica los paquetes por conexión, debe ser el protocolo DNS el que asigne a los paquetes una "identificación" para poder saber que paquete responde a una pregunta anterior, etc.
A esta identificación se le llama QueryID y la asigna el NS que inicia la comunicación (el que pregunta). A partir de ese momento todos los paquetes referentes a la resolucion de esa pregunta iran identificados con ese QueryID.

Inyección de datos falsos en la cache de un NS.

A continuación viene la parte interesante, como engañar a un NS para que resuelva un nombre dado a una IP que queramos nosotros o al revés.

Método A: Suplantación de un NS.

Para este ataque debemos disponer de:

- Un NS primario (al que pueda consultar cualquier ordenador sobre un dominio)

La técnica es la siguiente...

Digamos que nosotros somos m1.hh.org (1.1.1.1) y el ns que controlamos es ns.xs.com y queremos spoofear como XXX.lechuck.org al NS ns.victim.com.

Se trata de hacernos pasar por el ns de lechuck.org  y hacer creer a ns.victim.com que ha resuelto bien a XXX.lechuck.org. Para crear este "paquete" con información falsa, el NS de victim.com debe preguntarnos sobre él, y en ese momento sera cuando nosotros contestemos. Pero como no somos el NS de lechuck.org no podemos saber cual será el QueryID de ns.victim.com. Por tanto tenemos un problema, como sabemos el QueryID que tendrá el paquete que preguntará sobre XXX.lechuck.org ?

Si hacemos una consulta a ns.victim.com sobre una dirección que sirva el ns.xs.com (por ejemplo, consultamos www.xs.com), ns.victim.com se pondrá en contacto con ns.xs.com y le preguntará la dirección de www.xs.com, nuestro NS le responderá, y tan contentos. Dado que previamente habremos sniffado la conexion con nuestro NS por parte de ns.victim.com preguntando por la direccion de www, sabremos con que QueryID ha preguntado.
El QueryID del protocolo DNs no es un número aleatorio o pseudo-aleatorio como el de algunas implementaciones de TCP, sino que es secuencial, ésto es, que para cada pregunta, aumenta en uno el QueryID. Esto es así porque el QueryID no se diseñó como un mecanismo de seguridad ante posibles spoofs, sino como una manera de controlar que respuesta corresponde a que pregunta y al revés.

Pues bien, una vez tenemos el QueryID del NS víctima creamos un datagrama DNS con la información falsa que queremos transmitir (XXX.lechuck.org <-> 1.1.1.1 ), como si la enviara el NS de lechuck.org, y con destino a ns.victim.com.
Hacemos una consulta al ns.victim.com preguntando por alguna direccion del dominio lechuck.org y inmediatamente enviamos el paquete de respuesta spoofeado.
En lugar de enviar un paquete es conveniente enviar unos cuantos, con QueryIDs consecutivos, dado que en el tiempo en que hemos tardado entre que obtenemos el queryID y solicitamos la consulta por lechuck.org el NS victima puede haber recibido otras peticiones de resolución, y por tanto el QueryID puede haber aumentado ligeramente.

Asi, si ns.victim.com recibe antes nuestra respuesta que la respuesta del NS de lechuck.org (en caso de que exista) o un error indicando que no hay tal dominio (en caso de que no exista) ya tendremos en la cache del NS víctima la información falsa que queriamos inyectarle.

Método B: Inyección de datos en nuestra respuesta.

Para este ataque debemos disponer igual que antes de un NS primario.

Esta técnica consiste en...

Cuando un NS hace una consulta a otro no sabe que numero de respuestas puede obtener a su query, ni le importa, pues todo lo que sea información lo recibirá con mucho gusto.
Pues bien, si al hacer una consulta a un NS, además (o en lugar) de la información que solicita se le devuelve la informacion falsa que nosotros queramos, el NS que preguntó la aceptará y ya la tendremos en la cache del DNS que nos preguntó :)

Así, aplicado al caso anterior, lo único que debemos hacer es preparar nuestro NS (ns.xs.com) para que responda con la información falsa (XXX.lechuck.org <->1.1.1.1) a las preguntas de un NS (ns.victim.com) y hacer que el NS víctima pregunte a nuestro NS.

Este método es mucho más sencillo y efectivo que el anterior, aunque requiere mas recursos para que funcione, pues debemos modificar el programa servidor de nombres o bien hacer un programa que funcione como tal, y que sirva nuestros datos falsos.

Impacto.

Aparte del uso que todos podais estar pensando para este tipo de ataques a DNS (fanfarronear en IRC) hay multitud de usos mucho más serios, en que la seguridad de muchos sistemas puede quedar comprometida:

- NFS (Network File Sharing) en sistemas que exporten para nombres de hosts

- Servicios r* (rlogin, rsh, etc.) haciendonos pasar por "trusted hosts".

- TCP Wrappers que se basen en nombres de hosts para cortar el paso.

- ...

Conclusión.

El protocolo DNS es sensible a ataques de este tipo, y probablemente existen muchas más vulnerabilidades que las que aquí se han descrito.

El primer ataque seria evitable si se usase un protocolo de transporte como TCP, con números de sequencia "aleatorios" o bien usando QueryIDs tambien más o menos aleatorios.

La segunda vulnerabilidad es ya inherente al protocolo DNS, y necesitaria de una profunda revisión de la especificación de DNS para controlar que las respuestas se correspondan con lo que hemos preguntado.

Bibliografia.

Para aquellos que querais ampliar mas sobre este tema, os recomiendo que écheis una ojeada a:

- "Adressing weaknesses in the Domain Name System protocol"  PostScript  PDF

- RFC 1536
 

APENDICE : Puesta en practica del metodo B

Vamos a suponer que ya tenemos lo que necesitabamos, un host que sea NS primario de un dominio y otro host donde haremos correr nuesto programa "inyector" de informacion falsa DNS.

Vamos a suponer esta situacion:

- Nameserver primario: ns.xs.com
- Host que corre el inyector: 123.123.123.123

Voy a exponer aqui cual serian las modificaciones a hacer a la configuracion del demonio DNS suponiendo que este es el "named", el que con mas probabilidad vais a encontrar en un server un*x.

Bien, lo primero que hacemos es consultar en el fichero de configuracion del named donde almacena la informacion de los dominios que sirve. Este fichero es el /etc/named.boot (aunque en las ultimas versiones de bind, se ha
trasladado a /etc/named.conf y se ha modificado un poco la estructura del fichero, en cuyo caso vais a tener que adaptar las explicaciones que de aqui un poco). En nuestro ejemplo, contiene lo siguiente:


directory /var/named

cache              .                            root.cache
primary           xs.com                  db.xs.com
secondary       robin.org               db.robin.org


Vamos a analizarlo linea por linea: directory /var/named : Directorio base donde almacena los ficheros de
configuracion de los dominios primary xs.com db.xs.com : Es un NS primario del dominio xs.com, y lo
almacena en el fichero db.xs.com (Este es el que nos interesa) secondary robin.org : Es Ns secundario del dominio robin.org,
y lo almacena en el fichero db.robin.org (Este no nos interesa)

Asi pues, vamos a echarle una ojeada al fichero db.xs.com (que como sabemos, estara en /var/named):


xs.com.                        IN        SOA     ns.xs.com. root.xs.com. (
                                                            1997062100
                                                            28800
                                                            7200
                                                            604800
                                                            86400)

xs.com.                        IN         NS      ns.xs.com.

localhost                       IN        A        127.0.0.1
XXX                                 IN        A        10.0.0.1
elaine.xs.com.                IN        A        10.0.0.2


Las primeras lineas se refieren a la configuracion del dominio, quien lo gestiona, las fechas de expiracion, etc.

A continuacion esta la configuracion de los Nameservers del dominio:

xs.com.                         IN      NS      ns.xs.com.

En esta linea se especifica que el host "ns.xs.com" sirve al dominio xs.com.

Aqui es donde vamos a hacer la modificacion. Tenemos que insertar una linea que cree un subdominio y que ponga a nuestro host inyector como nameserver de ese subdominio. A la derecha de un IN NS solo se acepta un FQDN, es decir, no podemos poner
una ip numerica. Asi que vamos a tener que crear un host y luego asignarle una IP. La primera modificacion, pues, quedaria asi con lo que hemos supuesto antes:

xs.com.                         IN      NS      ns.xs.com.
sub.xs.com.                         IN      NS      ns1.xs.com.

Ahora vamos que tener que asignarle la IP a este host nuevo que hemos creado (ns1.xs.com). Para asignar una IP numerica a un FQDN, se usa el RR "IN A", tal como se puede ver en las siguientes lineas:

XXX                                   IN      A       10.0.0.1
elaine.xs.com.                  IN      A       10.0.0.2

La segunda linea, asigna la IP 10.0.0.2 al FQDN pitufa.xs.com. El punto al final de pitufa.xs.com. es muy importante, ya que si no le ponemos punto (como a XXX) el named le pone al final el nombre del dominio (xs.com).

Asi, para insertar la linea que queremos, y segun lo que hemos supuesto antes, utilizariamos esta linea:

ns1.xs.com.                     IN      A       123.123.123.123

Asi ya tenemos el named configurado para el spoof. Solo nos queda recargar esta informacion en el named (killall -HUP named), esperar a que la informacion se propague y poner a trabajar el programa inyector.

Como programa inyector, podeis utilizar el jizz (fuente en .c).


He pretendido con este artículo dar una ligera idea sobre el protocolo DNS y los métodos de DNS Spoofing conocidos, espero que os sirva de algo :)

Sólo me queda agradecer a Els Apostols la información referente al segundo método que he explicado, que yo desconocia totalmente, y su página de prueba de NS vulnerables.

Saludos,
XXX
 
 


(C) 1997-2001 by !Hispahack
Para ver el web en las mejores condiciones, usa una resolución de 800x600 y Netscape Navigator