DNS (Domain Name System)
El Sistema de Nombres de Dominio (DNS) es parte integrante de Internet. Por ejemplo, a través de nombres de dominio, como www.domain.com, podemos llegar a los servidores web a los que el proveedor de alojamiento ha asignado una o varias direcciones IP concretas. El DNS es un sistema para resolver nombres de ordenador en direcciones IP, y no tiene una base de datos central. Simplificado, podemos imaginarlo como una biblioteca con muchas guías telefónicas diferentes. La información está distribuida en muchos miles de servidores de nombres. Los servidores DNS distribuidos globalmente traducen los nombres de dominio en direcciones IP y controlan así a qué servidor puede acceder un usuario a través de un dominio concreto.
Hay varios tipos de servidores DNS que se utilizan en todo el mundo:
- DNS root server
- Authoritative name server
- Non-authoritative name server
- Caching server
- Forwarding server
- Resolver
Tipos de registros DNS
| Registro DNS | Descripción |
|---|---|
A | Devuelve una dirección IPv4 del dominio solicitado. |
AAAA | Devuelve una dirección IPv6 del dominio solicitado. |
MX | Devuelve los servidores de correo responsables. |
NS | Devuelve los servidores DNS (servidores de nombres) del dominio. |
TXT | Puede contener diversa información: validación de Google Search Console, certificados SSL, entradas SPF y DMARC para validar el tráfico de correo y protegerlo del spam. |
CNAME | Sirve como alias. Si un dominio debe apuntar a la misma IP que otro, se crea un registro A para uno y un CNAME para el otro. |
PTR | Funciona al revés (búsqueda inversa). Convierte direcciones IP en nombres de dominio válidos. |
SOA | Proporciona información sobre la zona DNS correspondiente y la dirección de correo electrónico del contacto administrativo. |
❯ dig soa www.domain.com
; <<>> DiG 9.16.27-Debian <<>> soa www.domain.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15876
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.domain.com. IN SOA
;; AUTHORITY SECTION:
domain.com. 900 IN SOA ns-161.awsdns-20.com. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
;; Query time: 16 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Jan 05 12:56:10 GMT 2023
;; MSG SIZE rcvd: 128Configuración local de DNS
❯ cat /etc/bind/named.conf.local
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "domain.com" {
type master;
file "/etc/bind/db.domain.com";
allow-update { key rndc-key; };
};Archivos de zona (Zone Files)
❯ cat /etc/bind/db.domain.com
;
; BIND reverse data file for local loopback interface
;
$ORIGIN domain.com
$TTL 86400
@ IN SOA dns1.domain.com. hostmaster.domain.com. (
2001062501 ; serial
21600 ; refresh after 6 hours
3600 ; retry after 1 hour
604800 ; expire after 1 week
86400 ) ; minimum TTL of 1 day
IN NS ns1.domain.com.
IN NS ns2.domain.com.
IN MX 10 mx.domain.com.
IN MX 20 mx2.domain.com.
IN A 172.16.58.10
server1 IN A 172.16.58.10
server2 IN A 172.16.58.12
ns1 IN A 172.16.58.2
ns2 IN A 172.16.58.3
ftp IN CNAME server1
mx IN CNAME server1
mx2 IN CNAME server2
www IN CNAME server2Archivos de zona de resolución inversa
❯ cat /etc/bind/db.172.16.58
;
; BIND reverse data file for local loopback interface
;
$ORIGIN 58.16.172.in-addr.arpa
$TTL 86400
@ IN SOA dns1.domain.com. hostmaster.domain.com. (
2001062501 ; serial
21600 ; refresh after 6 hours
3600 ; retry after 1 hour
604800 ; expire after 1 week
86400 ) ; minimum TTL of 1 day
IN NS ns1.domain.com.
IN NS ns2.domain.com.
10 IN PTR server1.domain.com.
12 IN MX mx.domain.com.
...SNIP...Configuraciones peligrosas
Algunas de las configuraciones que podemos ver a continuación conducen a vulnerabilidades. Porque DNS puede llegar a ser muy complicado, y es muy fácil que los errores se cuelen en este servicio, forzando a un administrador a trabajar alrededor del problema hasta encontrar una solución exacta. Esto a menudo lleva a liberar elementos para que partes de la infraestructura funcionen según lo previsto y deseado. En estos casos, la funcionalidad tiene más prioridad que la seguridad, lo que da lugar a errores de configuración y vulnerabilidades.
| Opción | Descripción |
|---|---|
allow-query | Define qué hosts pueden enviar solicitudes al servidor DNS. |
allow-recursion | Define qué hosts pueden enviar solicitudes recursivas al servidor DNS. |
allow-transfer | Define qué hosts pueden recibir transferencias de zona desde el servidor DNS. |
zone-statistics | Recoge datos estadísticos de zonas. |
Footprinting del servicio
Consultar los servidores de nombres autoritativos directamente contra el servidor DNS objetivo:
❯ dig ns domain.local @172.16.58.10
; <<>> DiG 9.16.1-Ubuntu <<>> ns domain.local @172.16.58.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45010
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: ce4d8681b32abaea0100000061475f73842c401c391690c7 (good)
;; QUESTION SECTION:
;domain.local. IN NS
;; ANSWER SECTION:
domain.local. 604800 IN NS ns.domain.local.
;; ADDITIONAL SECTION:
ns.domain.local. 604800 IN A 172.16.58.20
;; Query time: 0 msec
;; SERVER: 172.16.58.10#53(172.16.58.10)
;; WHEN: So Sep 19 18:04:03 CEST 2021
;; MSG SIZE rcvd: 107Dig - Consulta de versión del servidor
❯ dig CH TXT version.bind 172.16.58.60
; <<>> DiG 9.10.6 <<>> CH TXT version.bind
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47786
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; ANSWER SECTION:
version.bind. 0 CH TXT "9.10.6-P1"
;; ADDITIONAL SECTION:
version.bind. 0 CH TXT "9.10.6-P1-Debian"
;; Query time: 2 msec
;; SERVER: 172.16.58.60#53(172.16.58.60)
;; WHEN: Wed Jan 05 20:23:14 UTC 2023
;; MSG SIZE rcvd: 101- Revela la versión exacta de BIND en ejecución, útil para correlacionar con CVEs conocidos de esa versión específica.
Dig - Consulta ANY
❯ dig any domain.local @172.16.58.10
; <<>> DiG 9.16.1-Ubuntu <<>> any domain.local @172.16.58.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7649
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 064b7e1f091b95120100000061476865a6026d01f87d10ca (good)
;; QUESTION SECTION:
;domain.local. IN ANY
;; ANSWER SECTION:
domain.local. 604800 IN TXT "v=spf1 include:mailgun.org include:_spf.google.com include:spf.protection.outlook.com include:_spf.atlassian.net ip4:172.16.58.50 ip4:172.16.58.51 ip4:172.16.58.52 ~all"
domain.local. 604800 IN TXT "atlassian-domain-verification=t1rKCy68JFszSdCKVpw64A1QksWdXuYFUeSXKU"
domain.local. 604800 IN TXT "MS=ms97310371"
domain.local. 604800 IN SOA domain.local. root.domain.local. 2 604800 86400 2419200 604800
domain.local. 604800 IN NS ns.domain.local.
;; ADDITIONAL SECTION:
ns.domain.local. 604800 IN A 172.16.58.20
;; Query time: 0 msec
;; SERVER: 172.16.58.10#53(172.16.58.10)
;; WHEN: So Sep 19 18:42:13 CEST 2021
;; MSG SIZE rcvd: 437Dig - Transferencia de zona (AXFR)
Si allow-transfer no está correctamente restringido, se puede solicitar una transferencia de zona completa y obtener todos los registros del dominio de un solo golpe:
❯ dig axfr domain.local @172.16.58.10
; <<>> DiG 9.16.1-Ubuntu <<>> axfr domain.local @172.16.58.10
;; global options: +cmd
domain.local. 604800 IN SOA domain.local. root.domain.local. 2 604800 86400 2419200 604800
domain.local. 604800 IN TXT "MS=ms97310371"
domain.local. 604800 IN TXT "atlassian-domain-verification=t1rKCy68JFszSdCKVpw64A1QksWdXuYFUeSXKU"
domain.local. 604800 IN TXT "v=spf1 include:mailgun.org include:_spf.google.com include:spf.protection.outlook.com include:_spf.atlassian.net ip4:172.16.58.50 ip4:172.16.58.51 ip4:172.16.58.52 ~all"
domain.local. 604800 IN NS ns.domain.local.
app.domain.local. 604800 IN A 172.16.58.30
internal.domain.local. 604800 IN A 172.16.58.40
mail1.domain.local. 604800 IN A 172.16.58.31
ns.domain.local. 604800 IN A 172.16.58.20
domain.local. 604800 IN SOA domain.local. root.domain.local. 2 604800 86400 2419200 604800
;; Query time: 4 msec
;; SERVER: 172.16.58.10#53(172.16.58.10)
;; WHEN: So Sep 19 18:51:19 CEST 2021
;; XFR size: 9 records (messages 1, bytes 520)- Una zona transferible sin restricciones es un hallazgo de alto valor: revela toda la estructura interna de hosts del dominio en una sola consulta, sin necesidad de fuerza bruta.
Dig - Transferencia de zona (AXFR) - Subzona interna
Repitiendo la transferencia contra una subzona descubierta (internal.domain.local), a menudo se obtienen aún más hosts internos:
❯ dig axfr internal.domain.local @172.16.58.10
; <<>> DiG 9.16.1-Ubuntu <<>> axfr internal.domain.local @172.16.58.10
;; global options: +cmd
internal.domain.local. 604800 IN SOA domain.local. root.domain.local. 2 604800 86400 2419200 604800
internal.domain.local. 604800 IN TXT "MS=ms97310371"
internal.domain.local. 604800 IN TXT "atlassian-domain-verification=t1rKCy68JFszSdCKVpw64A1QksWdXuYFUeSXKU"
internal.domain.local. 604800 IN TXT "v=spf1 include:mailgun.org include:_spf.google.com include:spf.protection.outlook.com include:_spf.atlassian.net ip4:172.16.58.50 ip4:172.16.58.51 ip4:172.16.58.52 ~all"
internal.domain.local. 604800 IN NS ns.domain.local.
dc1.internal.domain.local. 604800 IN A 172.16.58.21
dc2.internal.domain.local. 604800 IN A 172.16.58.22
mail1.internal.domain.local. 604800 IN A 172.16.58.32
ns.internal.domain.local. 604800 IN A 172.16.58.20
vpn.internal.domain.local. 604800 IN A 172.16.58.40
ws1.internal.domain.local. 604800 IN A 172.16.58.41
ws2.internal.domain.local. 604800 IN A 172.16.58.42
wsus.internal.domain.local. 604800 IN A 172.16.58.33
internal.domain.local. 604800 IN SOA domain.local. root.domain.local. 2 604800 86400 2419200 604800
;; Query time: 0 msec
;; SERVER: 172.16.58.10#53(172.16.58.10)
;; WHEN: So Sep 19 18:53:11 CEST 2021
;; XFR size: 15 records (messages 1, bytes 664)- Aquí se descubren hosts críticos como
dc1/dc2(controladores de dominio),vpn,wsusy estaciones de trabajo (ws1,ws2) — información que normalmente requeriría mucha fuerza bruta manual.
nslookup
nslookup es una herramienta de consulta DNS más sencilla que dig, disponible tanto en Linux como en Windows. Es útil para comprobaciones rápidas cuando no se necesita el detalle completo que da dig.
Consulta básica (registro A) desde Linux:
❯ nslookup domain.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: domain.com
Address: 172.16.58.10Especificar el tipo de registro con -type= (en este ejemplo, un registro TXT de un subdominio específico):
❯ nslookup -type=TXT info.domain.local 172.16.58.10
Server: 172.16.58.10
Address: 172.16.58.10#53
info.domain.local text =
"greetings from the TXT record body"- El último argumento (
172.16.58.10) especifica el servidor DNS a consultar; si se omite, usa el resolver configurado por defecto del sistema. - Otros tipos comunes:
-type=MX,-type=NS,-type=SOA,-type=ANY.
Consulta inversa (PTR) de una IP:
❯ nslookup -type=PTR 172.16.58.10Nota:
nslookuptambién existe de forma nativa en Windows (nslookup.exe), con la misma sintaxis. Es especialmente relevante en escenarios de post-explotación donde solo se dispone de un host Windows comprometido (sin Kali a mano): al ser una utilidad nativa, entra dentro de las técnicas "Living off the Land" (LOLBAS) para hacer reconocimiento DNS sin instalar herramientas adicionales.
Fuerza bruta de subdominios vía DNS
Usando una wordlist (como las de SecLists) contra el servidor DNS directamente:
❯ for sub in $(cat /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-110000.txt);do dig $sub.domain.local @172.16.58.10 | grep -v ';\|SOA' | sed -r '/^\s*$/d' | grep $sub | tee -a subdomains.txt;doneAutomatizando el proceso con dnsenum, que combina resolución, fuerza bruta y detección de transferencia de zona en una sola herramienta:
❯ dnsenum --dnsserver 172.16.58.10 --enum -p 0 -s 0 -o subdomains.txt -f /opt/useful/SecLists/Discovery/DNS/subdomains-top1million-110000.txt domain.local
dnsenum VERSION:1.2.6
.
.
.--dnsserver: especifica el servidor DNS objetivo, en vez de usar el resolver por defecto.-p 0 -s 0: desactiva el escaneo de rangos de red (Whois) y de motores de búsqueda, para enfocarse solo en la fuerza bruta de subdominios.-f: indica la wordlist a usar.-o: guarda los resultados encontrados en un archivo.
Ejemplo de resultados obtenidos:
dc1.internal.domain.local. 604800 IN A 172.16.58.21
dc2.internal.domain.local. 604800 IN A 172.16.58.22
mail1.internal.domain.local. 604800 IN A 172.16.58.32
ns.internal.domain.local. 604800 IN A 127.0.0.1
vpn.internal.domain.local. 604800 IN A 172.16.58.40
ws1.internal.domain.local. 604800 IN A 172.16.58.41
ws2.internal.domain.local. 604800 IN A 172.16.58.42
wsus.internal.domain.local. 604800 IN A 172.16.58.33Explotación adicional
Abuso de Dynamic DNS Update (allow-update)
Si la zona permite actualizaciones dinámicas sin autenticación (como en el ejemplo de named.conf.local con allow-update), se puede inyectar un registro propio en la zona usando nsupdate, sin necesidad de acceso al servidor:
❯ nsupdate
> server 172.16.58.10
> zone domain.local
> update add evil.domain.local 600 A 172.16.58.99
> send- Si la zona no exige una
key(TSIG) para las actualizaciones, este comando puede crear o sobrescribir registros arbitrarios. - Esto puede usarse para apuntar un subdominio interno a una IP controlada por el atacante (por ejemplo, para interceptar tráfico o realizar phishing interno), o incluso para sobrescribir un registro existente y desviar tráfico legítimo.
Subdomain Takeover
Cuando un registro CNAME apunta a un servicio externo (S3, Azure, GitHub Pages, Heroku, etc.) que ya fue eliminado o nunca fue reclamado, es posible registrar ese recurso en el proveedor correspondiente y tomar control total del subdominio:
❯ dig cname old-app.domain.com
old-app.domain.com. 3600 IN CNAME old-app.s3-website-us-east-1.amazonaws.com.- Si el bucket
old-appen S3 ya no existe, cualquiera puede crear un bucket con ese mismo nombre y "reclamar" el subdominio, sirviendo contenido propio (incluyendo phishing) bajo un dominio de confianza. - Herramientas como
subjackocan-i-take-over-xyz(lista de referencia) automatizan la detección de este tipo de configuraciones huérfanas.
Abuso de Dynamic DNS Update
Si la zona permite allow-update sin autenticación (como se ve en el ejemplo de named.conf.local con allow-update { key rndc-key; }; mal configurado o sin key real), es posible inyectar/modificar registros propios en la zona usando nsupdate, sin pasar por el panel del registrador:
❯ nsupdate <<EOF
server 172.16.58.10
zone domain.local
update add evil.domain.local 600 A 172.16.58.99
send
EOF- Esto puede usarse para crear un subdominio que apunte a una IP controlada por el atacante (por ejemplo, para alojar un sitio de phishing bajo un subdominio legítimo), o para sobrescribir un registro existente y redirigir tráfico.
- En un entorno de Active Directory, un
allow-updatedemasiado permisivo (o el uso de "Nonsecure and secure" en DNS dinámico de Windows) es un vector conocido de escalada, ya que un usuario de dominio de bajo privilegio puede llegar a registrar sus propios registros DNS.
Subdomain Takeover
Cuando un registro CNAME apunta a un servicio de terceros (S3, Azure, GitHub Pages, Heroku, etc.) que ya fue eliminado o nunca se reclamó, el subdominio queda "colgando". Si el atacante registra ese mismo recurso en el proveedor externo, el subdominio pasa a servir contenido controlado por el atacante, bajo un dominio de apariencia legítima.
❯ dig cname olddemo.domain.local
olddemo.domain.local. 300 IN CNAME olddemo-bucket.s3.amazonaws.com.Si al visitar ese bucket S3 aparece un error de "NoSuchBucket" o similar, es indicio de que el recurso está libre para ser reclamado:
❯ curl -s https://olddemo-bucket.s3.amazonaws.com- Herramientas como
subjackonuclei(con templates detakeovers) automatizan esta detección contra listas grandes de subdominios.