1Por qué importa
Quien controla la resolución de nombres controla el destino de todo tu tráfico sin tocar tu código ni tus credenciales. No hace falta romper TLS: basta con que el nombre apunte a otro sitio y esperar a que alguien, en algún punto de la cadena, no verifique el certificado o acepte el aviso del navegador. En la práctica, la mitad de los ataques de intermediario empiezan aquí y no en la criptografía.
Hay un segundo motivo, menos vistoso y más frecuente: DNS es el mejor canal encubierto que existe en una red corporativa. Casi todos los perímetros permiten consultas salientes porque sin ellas no funciona nada, y muchos no las registran. Un nombre de subdominio puede transportar datos, y una respuesta puede transportar instrucciones. La fase 14 va a construir la detección de eso; aquí se construye el modelo que la hace posible.
Y hay un tercero, puramente operativo. La mayoría de las incidencias que parecen “la red va mal” son problemas de resolución: una caché con una entrada vieja, un resolutor que responde otra cosa dentro que fuera, un tiempo de vida de registro mal elegido durante una migración. Saber leer una resolución completa ahorra más horas que casi ninguna otra habilidad de esta fase.
El entregable es un diagrama tuyo de la resolución, con una marca en cada punto donde alguien puede responder antes que el legítimo, y al lado la defensa que aplica en ese punto concreto. No sirve una defensa genérica: lo que protege la última milla no protege la caché del recursivo.
2Conceptos
- Resolutor stub: la biblioteca del sistema que hace la consulta por ti. No recorre nada, solo pregunta.
- Resolutor recursivo: el que sí recorre la jerarquía y guarda el resultado en caché.
- Servidor autoritativo: el que tiene la respuesta original para una zona.
- Registro:
AyAAAApara direcciones,CNAMEpara alias,MXpara correo,TXTpara todo lo demás. - TTL: cuánto tiempo puede guardarse una respuesta en caché. Es una decisión de seguridad además de una de rendimiento.
- DHCP: el protocolo que te entrega dirección, ruta por defecto y resolutor al conectarte.
- ARP: el que traduce una dirección de red en una dirección física dentro del mismo segmento.
- DNSSEC: firmas sobre las respuestas DNS. Da autenticidad e integridad, nunca confidencialidad.
3Explicación profunda
Una resolución completa tiene más pasos de los que la gente imagina, y cada salto es una oportunidad. Tu proceso llama a la biblioteca del sistema. Esa biblioteca mira primero el archivo de hosts, después consulta al resolutor configurado. Ese resolutor, si es recursivo, pregunta a la raíz por el dominio de primer nivel, al dominio de primer nivel por el servidor de la zona, y a ese servidor por el registro concreto. Guarda el resultado durante el tiempo que diga el TTL y te lo devuelve. En tu laboratorio la cadena es corta porque el resolutor embebido de Docker responde por los nombres de servicio, pero la estructura es la misma.
El problema de diseño es que una respuesta DNS clásica no está autenticada de ninguna forma. El cliente acepta la primera respuesta que llegue con el identificador de transacción y el puerto de origen correctos, sobre UDP, sin firma. De ahí salen las cuatro familias de envenenamiento. Se puede mentir en la última milla, respondiendo antes que el resolutor legítimo si estás en el mismo segmento. Se puede mentir a la caché del recursivo, adivinando el identificador o aprovechando un fallo de implementación. Se puede mentir en el autoritativo, si alguien toma control de la zona o del registrador. Y se puede mentir sin tocar DNS, cambiando qué resolutor usas: eso es lo que hace un DHCP falso.
DHCP merece esa mención aparte porque casi nadie lo lee como lo que es: una entrega de confianza. Cuando un equipo se conecta, difunde una petición y acepta la primera oferta que llega. Esa oferta no trae solo una dirección: trae la ruta por defecto y el resolutor DNS. Quien conteste primero decide por dónde sale todo tu tráfico y quién traduce todos tus nombres. No hay credenciales de por medio ni verificación posible; es un protocolo que se diseñó para redes donde el cable ya era la autenticación.
ARP está un escalón por debajo y es todavía más crudo. Para hablar con un equipo del mismo segmento hace falta su dirección física; ARP la pide a gritos y cualquiera puede contestar. Peor: muchos sistemas aceptan respuestas que nadie pidió y actualizan su tabla con ellas. Un atacante que anuncia ser la puerta de enlace consigue que el tráfico de sus vecinos pase por él, sin explotar ninguna vulnerabilidad. El protocolo está funcionando exactamente como fue especificado; ese es el problema.
Las defensas hay que colocarlas con precisión porque resuelven cosas distintas. DNSSEC firma las respuestas: te dice que lo que recibes es lo que publicó el dueño de la zona, y detecta manipulación en cualquier punto intermedio. No cifra nada: quien mire el cable sigue viendo qué nombres consultas. DoT y DoH hacen lo contrario: cifran el transporte entre tú y tu resolutor, así que el vecino de red deja de ver tus consultas, pero no te dicen nada sobre si el resolutor te está mintiendo. Son complementarias, y el error de diseño más común de esta lección es creer que una sustituye a la otra.
Una opinión, y la señalo como tal: en una red que controlas, el control más rentable no es criptográfico sino topológico. Un segmento donde solo un equipo puede ser servidor DHCP, donde los clientes no se ven entre sí y donde el resolutor es fijo, elimina de golpe la última milla entera. DNSSEC y DoH resuelven lo que queda, que es mucho menos.
4Ejemplo sencillo
# Llegar a una casa en una ciudad desconocida DHCP en la estacion te dan un plano, un guia y una salida recomendada. Aceptas el primero que se acerca. Nadie comprueba su credencial. DNS le preguntas al guia "donde vive Ana?" y te da una direccion. Tu no verificas nada: te fias de que el guia sepa y no mienta. ARP ya en la calle correcta, gritas "quien es el numero 12?" y alguien levanta la mano. Tampoco compruebas que sea verdad. # Y las tres defensas, que NO son intercambiables DNSSEC la direccion viene firmada por el ayuntamiento: sabes que es la autentica, aunque todo el mundo oiga lo que preguntaste. DoH hablas con el guia en un idioma que nadie mas entiende: nadie sabe por quien preguntas, pero el guia puede mentirte igual. topologia solo hay un guia autorizado en la estacion y los viajeros no pueden hablar entre ellos. Se acabaron los guias falsos.
5Ejemplo técnico
Así se lee una consulta real. Esta es del laboratorio de esta lección, preguntando por un nombre de servicio del propio compose:
Tres campos importan para seguridad y casi nunca se miran. El
identificador de la cabecera, que es lo único que ata la respuesta a la
pregunta en el DNS clásico: dieciséis bits, y por eso los ataques históricos de
envenenamiento consistían en adivinarlo. Las banderas: rd
dice que pediste recursión y ra que el servidor la ofrece; falta
ad, que aparecería si la respuesta estuviera validada con DNSSEC.
Y el TTL: seiscientos segundos durante los que cualquier mentira que
haya entrado en la caché se sigue sirviendo aunque el origen ya esté corregido.
| Punto de la cadena | Quién puede mentir | Qué lo detiene |
|---|---|---|
| Archivo de hosts local | Cualquiera con escritura en el sistema | Integridad del sistema de ficheros; ya es post-compromiso |
| Resolutor entregado por DHCP | Quien conteste primero en el segmento | Resolutor fijo por configuración, y control de puertos DHCP |
| Última milla hasta el recursivo | Cualquier equipo del mismo segmento | DoT o DoH hasta el resolutor, y segmentación |
| Caché del recursivo | Quien acierte identificador y puerto, o explote la implementación | Validación DNSSEC, aleatorización de origen |
| Zona autoritativa | Quien controle la zona o el registrador | Bloqueo en el registrador y segundo factor; DNSSEC no cubre esto |
| Resolución de dirección física | Cualquier equipo del segmento, con ARP | Aislamiento entre clientes y tablas estáticas donde tenga sentido |
La última fila de la tabla es la que más sorprende a quien viene de la seguridad de aplicaciones: DNSSEC no protege de que alguien tome el control de tu zona. Firma lo que publica el titular; si el titular pasa a ser otro, la firma sigue siendo válida. Ese riesgo se mitiga en el registrador, no en el protocolo.
6Diagrama
Ver el mismo diagrama como código Mermaid (editable)
flowchart LR
APP[aplicacion] --> STUB[resolutor del sistema]
STUB --> REC[recursivo con cache]
REC --> AUT[jerarquia autoritativa]
DHCP[DHCP falso] --> STUB
ARP[ARP suplantado] --> STUB
POI[cache envenenada] --> REC
SEC[zona secuestrada] --> AUT
7Código
Una resolución auditable se parece más a esto que a un ping. El
script compara lo que responden dos caminos distintos y avisa cuando no
coinciden, que es la señal barata de que algo está reescribiendo respuestas:
#!/bin/sh # auditar-resolucion.sh — dentro del laboratorio propio. # Compara la vista de dos resolutores y marca las diferencias. set -eu NOMBRES="app db entrada" for n in $NOMBRES; do # 1. lo que responde el resolutor configurado del sistema directa=$(docker compose exec -T cliente dig +short "$n" | head -1) # 2. lo que ve otro contenedor de la misma red, por si difieren segunda=$(docker compose exec -T sniffer getent hosts "$n" | awk '{print $1}') if [ "$directa" = "$segunda" ]; then echo "ok $n" else echo "DIFIEREN $n ($directa vs $segunda)" fi # 3. el TTL importa: es la ventana en la que una mentira sobrevive docker compose exec -T cliente dig "$n" | awk '/ANSWER SECTION/{getline; print " ttl:", $2}' done # 4. y lo que de verdad se envia por el cable, para no fiarse de la salida echo "== captura de las consultas ==" docker compose exec -T -d sniffer sh -c "tcpdump -i any -w /tmp/dns.pcap port 53" docker compose exec -T cliente sh -c "for n in app db entrada; do getent hosts \$n >/dev/null; done" docker compose exec -T sniffer sh -c "pkill tcpdump; tcpdump -r /tmp/dns.pcap | head -20"
Lo que hace útil al script es el paso 4. Los tres primeros se fían de lo que las herramientas dicen haber hecho; el cuarto mira el cable. Cuando alguien está interceptando resolución, la diferencia entre esas dos fuentes es el primer indicio, y a veces el único.
8Qué puede salir mal
Confiar en el nombre como si fuera identidad. Un servicio que autoriza por nombre de origen, o que decide qué es “interno” por el sufijo del dominio, delega su control de acceso en un protocolo sin autenticación.
Poner DoH y dar el problema por resuelto. Cifrar el canal hasta el resolutor esconde tus consultas del vecino, y a cambio concentra toda la confianza en un tercero que ahora ve el historial completo de tu red. Es un cambio de modelo de amenaza, no una mejora automática.
TTL largos durante una migración. Un tiempo de vida de un día significa que una respuesta equivocada, o envenenada, se sigue sirviendo un día entero después de haber corregido el origen. La ventana de daño la elegiste tú al publicar el registro.
Dejar registros colgando. Un CNAME que apunta a un
recurso que ya no existe permite que otro reclame ese recurso y se quede con
tu nombre. Es de los hallazgos más baratos de encontrar y de los más
rentables de explotar.
9Cómo lo abusaría un atacante
La vía más cómoda no es envenenar una caché: es llegar antes. En un segmento compartido, responder a una petición DHCP más rápido que el servidor legítimo entrega al cliente una ruta por defecto y un resolutor controlados por el atacante. A partir de ahí no hace falta ningún exploit: todo el tráfico pasa por él porque el cliente lo pidió.
Si el DHCP está protegido, queda ARP. Anunciar repetidamente ser la puerta de enlace consigue el mismo efecto sobre los vecinos que aceptan respuestas no solicitadas, que son muchos más de los que uno esperaría. Lo que hace peligrosa esta técnica es lo silenciosa que resulta: no hay conexión fallida, no hay error en ninguna aplicación, y el usuario ve exactamente lo que esperaba ver.
Después del acceso, DNS cambia de papel y se convierte en el canal. Un agente que no puede abrir conexiones salientes casi siempre puede resolver nombres, así que los datos se trocean y se envían como etiquetas de subdominio de una zona que el atacante controla. Contra eso no sirve bloquear puertos: hay que mirar el volumen, la entropía de los nombres y la frecuencia de consultas por dominio, que es justo lo que la fase de detección va a construir.
10Cómo defenderlo
- Fija el resolutor por configuración en los sistemas que importan, en vez de aceptar el que entregue la red.
- Aísla los clientes entre sí en los segmentos donde no necesiten hablarse. Elimina la última milla entera, ARP incluido.
- Valida DNSSEC en tu resolutor recursivo, y comprueba que de verdad lo hace: la bandera
aden la respuesta es la prueba. - Cifra hasta el resolutor con DoT o DoH cuando la red intermedia no sea tuya, sabiendo que eso mueve la confianza, no la elimina.
- Elige el TTL como una decisión de riesgo: corto antes de una migración, corto en lo que puede necesitar corrección urgente.
- Inventaría tus registros y borra los que apuntan a recursos que ya no controlas. Es la defensa completa contra el secuestro de subdominio.
- Registra las consultas salientes. Sin ese log no hay forma de ver un canal encubierto ni de investigar después.
11Laboratorio
Es el mismo laboratorio de la lección anterior. Si lo destruiste, vuelve a levantarlo:
cd cursos/seguridad/labs/lab-net-captura
docker compose up -d --build
Primero mira quién resuelve por ti y qué te responde. La resolución del laboratorio la sirve el resolutor embebido de Docker, dentro de tu propia máquina:
docker compose exec cliente cat /etc/resolv.conf
docker compose exec cliente dig app
docker compose exec cliente dig +short db entrada
Ahora captura la consulta en el cable. El sniffer comparte
la pila de red de app, así que ve todo lo que llega a ese
contenedor:
Ahora demuéstrate el envenenamiento más simple que existe. Escribe una
entrada falsa en el archivo de hosts del cliente, apuntando
un nombre del laboratorio a otro contenedor del laboratorio, y comprueba
que curl se lo cree sin protestar:
docker compose exec cliente sh -c "getent hosts db >> /etc/hosts.bak; getent hosts db | sed 's/db/app-falso/' >> /etc/hosts"
docker compose exec cliente getent hosts app-falso
docker compose down -v
12Ejercicios
Coloca cinco defensas en su punto
Para cada defensa, di en qué punto de la cadena actúa y qué ataque de esta lección no detiene: (1) DNSSEC; (2) DoH; (3) aislamiento de clientes en el segmento; (4) resolutor fijo por configuración; (5) bloqueo del dominio en el registrador.
(1) DNSSEC actúa sobre la respuesta en toda la cadena y no detiene el secuestro de la zona ni oculta lo que consultas. (2) DoH actúa entre tú y el resolutor y no detiene que ese resolutor mienta. (3) El aislamiento actúa en el segmento y elimina ARP y DHCP falsos, pero no toca la caché del recursivo. (4) El resolutor fijo neutraliza el DHCP falso y no hace nada contra un recursivo comprometido. (5) El bloqueo en el registrador es lo único que cubre el secuestro de zona, y no protege ningún salto de la resolución.
Clave: ninguna cubre más de un punto. Si en tu respuesta alguna “lo resuelve todo”, está mal colocada.
Suplanta un nombre del laboratorio
Consigue que curl http://app/ desde el cliente
acabe hablando con otro contenedor del mismo compose, sin tocar el
docker-compose.yml ni parar nada. Después explica qué capa
usaste y qué defensa de la lección lo habría impedido.
entrada con getent hosts entrada y escribe una línea en /etc/hosts asociándola al nombre app.# dentro del contenedor cliente cp /etc/hosts /etc/hosts.bak getent hosts entrada | sed 's/entrada.*/app/' >> /etc/hosts curl -s http://app/salud # responde "entrada ok", no la app # revertir cp /etc/hosts.bak /etc/hosts
La capa usada no es DNS: es el archivo de hosts, que la biblioteca del sistema consulta antes. La lección es que la resolución tiene un paso local que gana a cualquier defensa de red, y por eso este ataque concreto solo lo detiene la integridad del propio sistema. Ninguna defensa de esta lección lo habría impedido, y decirlo es parte de la respuesta correcta.
Clave: se evalúa que identifiques la capa y que digas explícitamente que DNSSEC y DoH no cubren este caso.
Cuenta los bits del envenenamiento clásico
El ataque histórico contra la caché de un recursivo consistía en adivinar el identificador de la consulta. Investiga fuera de esta lección y responde: ¿cuántos bits había que adivinar antes de la aleatorización del puerto de origen y cuántos después?, ¿por qué el ataque descrito en 2008 era tan rápido pese a esos bits?, y ¿qué papel juega el TTL en él?
Dieciséis bits del identificador, a los que la aleatorización del puerto de origen añade en torno a otros dieciséis, dependiendo del rango disponible. La técnica de 2008 fue rápida porque no intentaba envenenar el nombre objetivo directamente: consultaba subdominios inexistentes, que nunca están en caché y por tanto permiten reintentar de forma continua, e inyectaba la respuesta falsa en la sección de delegación.
Ese es exactamente el papel del TTL: cuando atacas un nombre que ya está en caché tienes una sola oportunidad y luego esperas horas; cuando atacas nombres que nunca están en caché, tienes intentos ilimitados. La defensa duradera fue DNSSEC, y la inmediata, la aleatorización.
Clave: unos 32 bits tras la aleatorización. Lo evaluable es que expliques por qué consultar nombres inexistentes elimina la espera del TTL.
Red Team · monta el canal encubierto
Dentro del lab-net-captura, y solo dentro de él: usa consultas
de nombres para sacar información del contenedor cliente hacia
un observador, sin abrir ninguna conexión. El observador es el
sniffer, que ya está capturando. Demuestra que puedes leer en
la captura una cadena que elijas.
dig $(echo secreto-lab | base64 | tr -d '=').app y busca esa etiqueta en la captura del sniffer.# en el cliente: el dato viaja en la PREGUNTA docker compose exec cliente sh -c 'dig +short $(echo secreto-lab | base64 | tr -d "=").app' # en el sniffer: la consulta aparece aunque no exista el nombre docker compose exec sniffer sh -c 'tcpdump -r /tmp/dns.pcap | grep -i c2vjcmv'
El canal funciona porque una consulta se transmite entera antes de que nadie decida si el nombre existe. En una red real, el atacante controla la zona del sufijo, así que la consulta llega hasta su servidor autoritativo aunque el perímetro bloquee todas las conexiones salientes. Aquí el sufijo es un nombre del laboratorio y el observador es tu propio sniffer, pero el mecanismo es idéntico.
Clave: lo importante es entender que no hubo conexión saliente. Si tu solución abrió un socket hacia algún sitio, has resuelto otro ejercicio.
Blue Team · detecta ese canal en la captura
Con la captura del ejercicio anterior, escribe los criterios que usarías para separar consultas normales de consultas de exfiltración. Después aplícalos a tu propia captura y comprueba cuántos falsos positivos producen sobre el tráfico legítimo del laboratorio.
Cuatro criterios sirven casi siempre: longitud media de las etiquetas muy por encima de lo habitual; número de subdominios únicos bajo un mismo dominio padre en una ventana corta; proporción alta de respuestas de nombre inexistente; y entropía del nombre, que en datos codificados es mucho mayor que en nombres escritos por humanos.
Sobre el laboratorio, ninguno de los cuatro dispara con el tráfico legítimo, porque los nombres son cortos, pocos y siempre resuelven. En una red real el ajuste es más difícil: hay servicios legítimos que generan subdominios únicos, empezando por las propias redes de distribución de contenido, y ese es el origen de casi todos los falsos positivos de esta detección.
Clave: el entregable son los criterios con umbrales concretos. Guárdalos: en la fase 14 se convierten en una regla.
Architecture Challenge · resolución para una plataforma con agentes
Diseña la resolución de nombres de una plataforma donde corren cargas de trabajo que ejecutan código poco confiable, incluidos agentes automáticos. Define: qué resolutor usa cada carga, si permites resolución de nombres externos y con qué política, cómo registras las consultas, y qué haces con el hecho de que DNS sea un canal de salida incluso sin conexiones.
Una propuesta defendible: resolutor propio y obligatorio por segmento, sin posibilidad de que la carga elija otro, con lista de permitidos por espacio de nombres. Las cargas que solo hablan con servicios internos no resuelven nada externo, y eso es una decisión de un renglón que elimina el canal encubierto por completo. Las que sí lo necesitan pasan por una lista revisada y su tráfico de resolución se registra con identidad de carga, no solo con dirección de origen.
Sobre el canal encubierto conviene ser honesto: si permites resolución externa arbitraria, la exfiltración por nombres es posible y solo te queda detectarla. Por eso la decisión importante no es la detección, sino cuántas cargas necesitan de verdad esa capacidad. En una plataforma de agentes, esa lista suele ser mucho más corta de lo que el equipo cree.
Clave: no hay una única respuesta. Se evalúa que separes las cargas por necesidad real de resolución externa y que reconozcas el límite de la detección.
13Preguntas de comprensión
¿Qué garantiza, por defecto, que una respuesta DNS la haya emitido quien dice haberla emitido?
Lo único que ata respuesta y pregunta es el identificador de transacción y el puerto de origen. Eso es correlación, no autenticación.
ARP no tiene autenticación. ¿Cuál es la consecuencia práctica?
Y lo consigue sin explotar nada: el protocolo funciona como se especificó. Por eso la defensa es topológica, no de parcheo.
Un servidor DHCP falso te entrega una dirección y además…
Con esas dos cosas controla por dónde sale tu tráfico y quién traduce tus nombres, sin tocar ninguna aplicación.
En el laboratorio, dig app responde con una dirección. ¿Quién la sirve?
La red del laboratorio es interna y no sale a ninguna parte. Toda la resolución de nombres de servicio ocurre dentro del host.
14Reto adicional
Audita los registros de un dominio que controles
Toma un dominio tuyo y haz el inventario completo de sus registros. Para cada uno responde: ¿a qué recurso apunta?, ¿ese recurso sigue existiendo y bajo tu control?, ¿qué TTL tiene y por qué ese y no otro? Marca los que apuntan a servicios de terceros, que son los candidatos a secuestro.
CNAME hacia un servicio externo es el caso de riesgo.TXT: suelen acumular verificaciones de servicios que dejaste de usar hace años.El patrón que aparece casi siempre es el mismo: dos o tres alias hacia plataformas que se probaron y se abandonaron, y una colección de registros de texto con verificaciones de servicios que ya nadie usa. Los alias abandonados son el hallazgo grave: si el recurso al que apuntan se puede volver a reclamar, cualquiera puede servir contenido bajo tu nombre, con certificado válido incluido, porque la validación de dominio se hace precisamente por DNS.
Sobre los TTL, la respuesta útil es que casi nadie los ha elegido: son los que puso la herramienta. Elegirlos es una decisión de riesgo, y basta con distinguir dos casos: lo que necesitaría corrección urgente lleva TTL corto; lo estable puede llevarlo largo y ahorrar consultas.
Clave: el entregable es la lista de registros con destino no controlado. Cada uno de ellos es un riesgo escribible con el vocabulario de la fase 01.
15Resumen
- La resolución tiene varios saltos y cada uno se puede envenenar de una forma distinta. No hay una defensa única.
- DNS clásico no autentica nada: lo único que ata respuesta y pregunta es un identificador de dieciséis bits y el puerto de origen.
- DHCP entrega confianza, no solo direcciones: la ruta por defecto y el resolutor van en el mismo paquete.
- ARP funciona exactamente como se especificó, y por eso la suplantación en el segmento no necesita ninguna vulnerabilidad.
- DNSSEC da autenticidad; DoT y DoH dan confidencialidad hasta el resolutor. Ninguna sustituye a la otra, y ninguna cubre el secuestro de la zona.
- El TTL es la duración de una mentira que ya entró en caché, así que elegirlo es una decisión de seguridad.
- DNS es un canal de salida incluso cuando todas las conexiones están bloqueadas.
16Mis notas
Estas notas se guardan solo en este navegador. No se envían a ningún servidor. Expórtalas desde el panel de progreso si cambias de máquina.
17Recursos
Los comentarios se cargan solo si los pides, desde GitHub Discussions. No se carga nada de terceros mientras no pulses.