8 min de lectura

La protección contra rebinding de DNS exige una resolución en tiempo de ejecución

Protección contra rebinding de DNS para acciones HTTP de agentes: resuelve en tiempo de ejecución, rechaza respuestas inseguras, fija cada conexión y prueba reintentos y redirecciones.

La protección contra rebinding de DNS exige una resolución en tiempo de ejecución

Una aprobación para api.example.test no aprueba cualquier dirección que ese nombre devuelva más tarde. Si un agente puede hacer una solicitud HTTP autenticada, el rebinding de DNS convierte una decisión obsoleta sobre un nombre de host en una ruta hacia un servicio local, un endpoint de metadatos en la nube o un plano de control interno. La inserción de credenciales puede funcionar exactamente como se diseñó. Lo que falló fue la decisión sobre el destino.

He visto equipos crear pantallas de aprobación cuidadosas y después dejar que la biblioteca HTTP resuelva el nombre en el último momento posible sin comprobar la respuesta. Es fácil pasar por alto esa brecha porque el DNS normal se comporta correctamente. Un atacante no necesita que el DNS normal coopere. Necesita un nombre que controle, una vida útil de caché corta y un cliente que confunda un nombre de host con un destino permanente.

La protección contra rebinding de DNS exige una búsqueda en tiempo de ejecución. Resuelve justo antes de abrir la conexión, inspecciona el resultado completo, elige una dirección permitida y conecta con esa dirección exacta. Conserva el nombre de host original para HTTP y la validación TLS. Repite el trabajo cada vez que el cliente abra otra conexión, siga una redirección o cambie de protocolo.

La aprobación identifica una clase de destino, no una dirección IP para siempre

Un nombre de host es una instrucción para resolver, no una identidad estable de un par de red. La distinción parece quisquillosa hasta que un agente recibe una URL desde una incidencia, un registro de compilación, la respuesta de una herramienta u otro servicio. El agente puede pedir aprobación para llamar a reports.partner.test; quien aprueba ve un destino público verosímil. Minutos después, el mismo nombre puede responder con 127.0.0.1, una dirección IPv6 de loopback o una dirección accesible solo dentro de la red de la máquina.

La secuencia habitual de rebinding tiene dos fases. Durante la primera, el servidor DNS autoritativo devuelve una dirección pública. El cliente o revisor acepta el nombre de host, a veces después de una solicitud previa similar a la de un navegador. Durante la segunda, el atacante cambia la respuesta y depende de la expiración, una reconexión, una redirección, un reintento o una segunda solicitud para activar otra búsqueda. El servicio de destino ve una solicitud desde una máquina local, donde los cortafuegos de red suelen conceder más acceso que a Internet público.

Una puerta de enlace de agentes presenta una versión más grave de este problema. Puede adjuntar un token bearer, credenciales básicas o un encabezado de autorización personalizado solo después de que una persona apruebe la acción. Si la puerta de enlace verifica el proceso del agente pero no la dirección del par, puede entregar una credencial auténtica al lugar equivocado. Una solicitud a un servicio administrativo local quizá ni necesite la credencial. El atacante puede usar la solicitud únicamente para que la máquina lea una respuesta que el agente pueda recibir después.

No lo resuelvas guardando para siempre la primera dirección IP resuelta. Los servicios públicos usan balanceo de carga, cambios de dirección e IPv6. La afirmación segura es más limitada: cada conexión debe usar una dirección que haya superado la validación cuando comenzó esa conexión. Una aprobación anterior puede autorizar el nombre de host y el uso de la credencial. No puede justificar una dirección posterior que pertenezca a una red bloqueada.

Resuelve justo antes de abrir el socket

El orden de las operaciones determina si la comprobación sirve de algo. Resuelve el nombre de host, valida la respuesta del resolvedor, elige una dirección y pasa esa dirección directamente a la rutina de conexión. Si validas una dirección y después llamas a una API de conveniencia que vuelve a resolver el nombre de host, habrás comprobado un destino y conectado a otro.

Mantén separados cuatro valores durante toda la solicitud:

  • origin_host es el nombre de host que aprobó el usuario y que debe cubrir el certificado.
  • peer_ip es la única dirección validada seleccionada para este socket.
  • port es el puerto solicitado después de que el cliente aplique sus reglas de puertos permitidos.
  • scheme determina si el cliente exige TLS.

Para HTTPS, conecta el socket TCP a peer_ip, pero envía origin_host como encabezado HTTP Host y usa origin_host para SNI y la verificación del certificado. Un certificado para la dirección IP no es un sustituto. Si el certificado no coincide con el nombre de host, la solicitud debe fallar. Desactivar la validación de certificados para facilitar la fijación de direcciones sustituye un error de enrutamiento por otro mucho peor.

Un límite mínimo de conexión puede verse así:

origin_host = parse_url(request_url).host
answers = resolver.lookup_all(origin_host)
allowed = [ip for ip in answers if public_routable(ip)]
if allowed is empty:
    fail("DNS answer contains no permitted address")

peer_ip = choose_one(allowed)
socket = tcp_connect(peer_ip, request_port)
tls = tls_handshake(socket, server_name=origin_host, verify_name=origin_host)
send_http(tls, host_header=origin_host)

Este esquema dice intencionadamente lookup_all. Una búsqueda de una sola dirección oculta un fallo habitual: el resolvedor devuelve a la vez una dirección IPv4 pública permitida y una dirección IPv6 de loopback. Una biblioteca puede preferir IPv6 aunque la aplicación solo haya inspeccionado IPv4. Rechaza el nombre de host cuando se bloquee alguna respuesta, o define una regla de selección estricta que pase solo direcciones validadas al conector. Rechazar respuestas mixtas es más fácil de auditar y deja al atacante menos margen para explotar el comportamiento de carreras de conexión.

La palabra «justo» importa. Resuelve antes de que se abra el socket, no cuando el agente redacta una solicitud, no cuando aparece la tarjeta de aprobación y no cuando el usuario guarda una credencial. Sigue habiendo un pequeño intervalo entre la búsqueda y la conexión, pero el cliente ya ha elegido una dirección y no necesita consultar DNS de nuevo para ese socket.

Filtrar IPv4 privadas es solo la primera barrera

RFC 1918 reserva rangos IPv4 para redes privadas. Ofrece tres bloques conocidos: 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16. Bloquearlos es necesario para un cliente expuesto a Internet, pero tratar esa lista como toda la defensa es un error habitual y costoso.

Un filtro de destinos debe rechazar categorías de direcciones que no puedan tratarse de forma segura como públicas. Como mínimo, rechaza loopback, direcciones no especificadas, link-local, multicast, direcciones de uso privado y direcciones locales únicas IPv6. Rechaza las formas IPv6 mapeadas a IPv4 después de normalizarlas, porque ::ffff:127.0.0.1 sigue teniendo en la práctica efecto de loopback. Considera inválidos los identificadores de zona IPv6 en URL remotas. No dejes que la ortografía textual determine la seguridad; analiza la dirección en forma binaria y clasifícala ahí.

Varios rangos merecen una decisión explícita de producto, no un valor predeterminado accidental. Las direcciones NAT de grado operador en 100.64.0.0/10 no son accesibles globalmente. Los rangos de documentación y benchmarking no deberían aparecer como destinos de producción normales. El rango IPv4 link-local puede alcanzar servicios de metadatos en algunas configuraciones de nube. Las direcciones IPv6 link-local requieren un ámbito de interfaz y nunca deberían surgir de una solicitud a un nombre de host público. Para una puerta de enlace de acciones externas, el valor predeterminado más seguro es permitir únicamente direcciones unicast globales normales, con excepciones identificadas para un modo de despliegue interno separado.

No uses una comprobación de prefijo de cadena. 127.1, 127.0.0.1, formatos enteros aceptados por un analizador permisivo, la compresión IPv6 y las formas mapeadas la vuelven poco fiable. Analiza el host de la URL como nombre DNS o como literal IP. Si es un literal IP, clasifícalo directamente. Si es un nombre DNS, resuélvelo y clasifica cada dirección devuelta. Rechaza nombres malformados antes de resolverlos.

Aquí también los equipos confunden DNS público con accesibilidad pública. Un resolvedor puede devolver una dirección pública que se enruta a través de un proxy corporativo, una VPN o una ruta de red de horizonte dividido. La respuesta DNS es una entrada, no una promesa sobre toda la ruta. El filtrado de direcciones evita el rebinding directo hacia rangos locales evidentes. Las reglas de salida de red aún deben impedir rutas de acceso que el host puede alcanzar pero que el producto no debería usar.

Los CNAME y las respuestas mixtas requieren una sola decisión

Un CNAME no vuelve seguro a un nombre. Delega la respuesta final en otro nombre, que a su vez puede cambiar o devolver un conjunto mixto de respuestas. El resolvedor normalmente sigue esa cadena antes de entregar a la aplicación registros A y AAAA, así que la aplicación debe juzgar las direcciones finales que recibe. Si la API del resolvedor expone la cadena, regístrala para el diagnóstico, pero no bases la aplicación de la política en que el primer nombre pareciera conocido.

Un valor predeterminado firme es sencillo: si cualquier respuesta final para un nombre de host solicitado pertenece a una categoría bloqueada, rechaza la solicitud. Esto puede rechazar un servicio que publique una dirección privada inaccesible junto a una pública, pero esa configuración ya genera clientes impredecibles. Una puerta de enlace que envía credenciales debe pedir al propietario del servicio que corrija el registro DNS en vez de elegir silenciosamente una respuesta conveniente.

Algunos equipos prefieren «usar cualquier respuesta permitida». La regla es popular porque mantiene más integraciones en funcionamiento. También crea comportamientos difíciles de reproducir: un orden del resolvedor funciona, otro conecta con algún lugar bloqueado, y una implementación Happy Eyeballs inicia intentos IPv6 e IPv4 en momentos distintos. Si eliges esa vía, la capa de conexión debe recibir solo las direcciones permitidas elegidas y nunca recurrir al nombre de host original. Una biblioteca HTTP genérica a menudo no ofrece esa garantía.

Registra pruebas suficientes para explicar un rechazo. El registro de la solicitud debe incluir el nombre de host original, el puerto, el conjunto de direcciones resueltas, la dirección de par seleccionada si existe, el resultado de la política y un identificador de correlación de solicitud. No registres credenciales ni cuerpos de respuesta solo por comodidad al depurar. Los fallos de seguridad DNS suelen aclararse con la lista de direcciones por sí sola.

Los grupos de conexiones son seguros solo si preservan el par

Protege tus claves de API con Sallyport
Sallyport inserta las credenciales HTTP por sí mismo, así que el agente nunca recibe el secreto.

Una conexión TLS reutilizada no realiza una búsqueda DNS nueva y no debería necesitarla. El socket ya tiene una dirección de par elegida y validada cuando se abrió. Un cliente puede reutilizar esa conexión exacta para otra solicitud al mismo origen si lo permiten las reglas normales de origen HTTP y las comprobaciones de certificado.

Una conexión nueva es distinta. Los grupos suelen ocultar reconexiones tras un tiempo de inactividad, un fallo de transporte, un límite de flujos HTTP/2 o un cambio en el estado del proxy. Si el grupo pide al sistema operativo conectar de nuevo por nombre de host, ha abierto la ventana de rebinding. Coloca el resolvedor y el conector debajo del grupo, no junto a la primera solicitud.

La coalescencia de conexiones exige precaución. HTTP/2 puede reutilizar una conexión TLS para más de un nombre de host cuando el certificado los cubre y el par es adecuado. Un navegador general puede aceptar ese equilibrio. Una puerta de enlace de acciones debe hacer explícita la decisión de destino para cada origen. No supongas que un socket abierto para un nombre de host aprobado puede llevar una solicitud con credenciales para otro solo porque el certificado enumera ambos nombres. El alcance de la aprobación, la autoridad HTTP y la reutilización de conexiones son decisiones independientes.

Los reintentos tienen la misma forma. Un reintento después de un fallo de conexión es un nuevo intento saliente. Vuelve a resolver, reclasifica, elige una dirección y abre un socket nuevo. Nunca almacenes en caché un resultado permitido más tiempo que la conexión que autorizó. Puedes almacenar brevemente resultados bloqueados para reducir trabajo repetido, pero no conviertas esa caché en una autoridad de enrutamiento sin revisión.

Los cambios a mitad de llamada no permiten a un atacante mover una conexión TCP establecida a una IP nueva. TCP ya eligió su par. El peligro está en la ruta de código que crea una conexión de reemplazo, sigue una redirección, actualiza un protocolo o emite otra solicitud después de la primera respuesta. Probar una sola solicitud satisfactoria no cubre las rutas que usan los clientes de producción bajo carga.

Las redirecciones son solicitudes salientes independientes

Una redirección cambia la URI de destino. Trátala como una acción nueva, aunque la biblioteca HTTP la llame una función de conveniencia. Analiza el valor de Location, rechaza esquemas no admitidos, resuelve su nombre de host en tiempo de ejecución, valida sus respuestas y comprueba su puerto antes de conectar. Transferir automáticamente encabezados de autorización a través de un cambio de origen es otro error de fuga de credenciales, así que elimínalos salvo que el nuevo origen tenga su propia decisión explícita de autorización.

Limita las redirecciones a un número pequeño y fijo. Un servidor de pruebas de rebinding puede rotar nombres y respuestas en cada salto, y las redirecciones ilimitadas convierten una acción saliente sencilla en una cadena opaca. Registra cada salto con el origen de partida, el origen de destino, el conjunto de direcciones, el par seleccionado, el código de estado y el motivo de cualquier rechazo.

Las comprobaciones DNS también deben rodear funciones de protocolo fáciles de pasar por alto. Un proxy HTTP cambia quién recibe la conexión TCP inicial, así que valida la dirección del proxy y define después qué puede resolver el proxy. De lo contrario, un túnel CONNECT puede trasladar la búsqueda del nombre de host a un componente que no ejecuta las mismas comprobaciones. Los webhooks, las URL de devolución de llamada, los endpoints de almacenamiento de objetos y los registros de paquetes merecen el mismo tratamiento cuando un agente puede influir en su destino.

Una regla que bloquea respuestas DNS privadas no vuelve seguras las URL arbitrarias. No impide que un servidor público ejecute un comando peligroso, devuelva una respuesta enorme o redirija hacia un servicio aprobado pero hostil. La defensa contra rebinding de DNS es un límite. Debe ser lo bastante precisa para que nadie la confunda con un lenguaje de políticas de propósito general.

Prueba el resolvedor y el conector como una unidad

Ejecuta la puerta de enlace de acciones para Mac
Usa una aplicación Mac firmada que siempre está en ejecución y tiene el núcleo de la bóveda integrado, no un demonio independiente.

Las pruebas unitarias que introducen 127.0.0.1 en un clasificador de direcciones son necesarias, pero insuficientes. El fallo ocurre cuando el cliente pasa un nombre de host por varias capas y una de ellas realiza una resolución sin protección. Tus pruebas deben observar el destino real del socket.

Crea una zona de prueba autoritativa controlada con un nombre como flip.test. En su primera búsqueda, devuelve un endpoint público de prueba que registre una solicitud inocua. En la siguiente, devuelve una dirección bloqueada. Después fuerza una segunda conexión cerrando el primer endpoint tras su respuesta. El resultado esperado no es una segunda solicitud correcta con una advertencia en los registros. El conector debe rechazarla antes de abrir un socket a la dirección bloqueada.

Usa una matriz de pruebas que cambie una condición cada vez:

  1. Devuelve una respuesta IPv4 pública y luego una respuesta IPv4 de loopback tras un TTL bajo.
  2. Devuelve una dirección IPv4 permitida junto a ::1 en el mismo conjunto de respuestas.
  3. Devuelve un CNAME cuya respuesta final cambie de pública a local única IPv6.
  4. Devuelve una redirección a un segundo nombre de host que se resuelva a una dirección bloqueada.
  5. Cierra una conexión agrupada y verifica que el reintento reciba una validación nueva.

Añade una aserción en el límite de red. Un conector simulado debe registrar la IP numérica y el puerto que recibió. La prueba debe fallar si recibe un nombre de host, porque eso significa que otro resolvedor aún puede ejecutarse después de la validación. En las pruebas de integración, coloca un listener en el puerto de loopback bloqueado y confirma que registra cero conexiones. Una solicitud rechazada que llega al listener ya cruzó el límite que pretendías proteger.

Las pruebas con TTL cortos importan porque revelan cachés en lugares inesperados: el resolvedor de la aplicación, el sistema operativo, un proxy, un tiempo de ejecución de lenguaje o la biblioteca HTTP. Prueba tanto un resolvedor que respete el TTL como otro que devuelva una respuesta modificada inmediatamente. La seguridad no puede depender de que una caché concreta sea lenta o rápida.

La aprobación y la validación de direcciones responden preguntas distintas

Saca las credenciales de los prompts
Envía las llamadas HTTP del agente por Sallyport en lugar de entregar tokens bearer al agente.

La aprobación por sesión responde «¿qué proceso de agente puede actuar durante esta ejecución?». La aprobación por llamada responde «¿este uso de credenciales merece ahora una decisión humana?». La validación DNS responde «¿qué par de red puede recibir esta conexión?». Combinar todo esto en una sola solicitud de aprobación hace que la interfaz parezca más simple, pero oculta un cambio importante en aquello que la persona aprobó.

Muestra el nombre de host y el puerto en una superficie de aprobación, pero no finjas que un nombre de host es una dirección de par inmutable. La implementación debe validar la dirección en tiempo de ejecución aunque la persona haya visto un aviso segundos antes. Si el resultado está bloqueado, deniega la acción e indica el nombre de host y la categoría de dirección clasificada. Un usuario puede corregir un registro DNS erróneo; no puede aprobar de forma útil una carrera de rebinding invisible.

La puerta de la bóveda de Sallyport, la autorización de sesión y las aprobaciones de credenciales por llamada controlan quién puede invocar una acción y cuándo una persona debe confirmarla. Su ruta de acciones HTTP sigue necesitando la misma disciplina de destino en tiempo de ejecución, porque una bóveda que nunca entrega un secreto a un agente también debe evitar enviar ese secreto a una respuesta DNS en la que el usuario no quería confiar.

No añadas un motor de reglas de formato libre para resolver este problema limitado. El comportamiento central puede seguir siendo determinista: rechazar respuestas no públicas para acciones HTTP externas, resolver al crear la conexión, vincular el socket a la dirección elegida y reevaluar en cada conexión nueva. Una regla pequeña con un límite comprobable es más fácil de mantener correcta que una página de excepciones que nadie puede explicar.

Los registros deben mostrar el destino que realmente se usó

Un registro de auditoría que solo contiene el nombre de host no puede responder a la pregunta que importa tras un incidente: ¿adónde fue el socket? Guarda tanto el origen solicitado como la dirección de par elegida para cada conexión permitida. En los intentos denegados, guarda el conjunto de respuestas devueltas y la clasificación que provocó la denegación. Mantén la marca de tiempo cerca de la creación de la conexión para que un investigador pueda correlacionarla con el comportamiento del resolvedor.

Evita afirmar una certeza que el registro no puede demostrar. Si la biblioteca HTTP recibe solo un nombre de host, el registro de auditoría puede decir que la aplicación solicitó un nombre de host; no puede probar el par numérico. Corrige el conector antes de pulir la entrada de auditoría. Las pruebas deben proceder de la capa que controla el socket.

Para un historial de auditoría resistente a manipulaciones, incluye los registros de decisiones DNS en la misma secuencia que los eventos de autorización, conexión, redirección y respuesta. Sallyport genera sus diarios Sessions y Activity a partir de un registro de auditoría cifrado, encadenado por hash e inaccesible para escritura, y sp audit verify puede verificar esa cadena sin conexión sobre texto cifrado. Eso solo sirve si el registro de acción incluye el destino resuelto en vez de un nombre de host tranquilizador pero incompleto.

Empieza por la fábrica de conexiones. Encuentra cada ruta que acepte un nombre de host, haz que devuelva un par numérico validado y obliga a la API de sockets a rechazar nombres de host sin procesar. Cuando se cumpla ese invariante, los TTL cortos y los cambios de respuesta pasarán a ser casos de prueba normales en lugar de una sorpresa de seguridad esperando tras la próxima reconexión.

FAQ

¿Qué es el rebinding de DNS?

Es un ataque DNS en el que un nombre de host primero se resuelve a una dirección pública aceptable y más tarde a una dirección interna o local. Si un cliente aprobado confía en el nombre de host sin comprobar la dirección a la que se conecta realmente, el atacante puede redirigir la siguiente solicitud.

¿El rebinding de DNS puede eludir una aprobación basada en el nombre de host?

Sí. Un nombre de host puede ser inocuo cuando alguien lo aprueba y peligroso cuando el cliente vuelve a conectarse más tarde. La aprobación debe vincularse al destino que usa la pila de red en esa solicitud concreta, no solo a un nombre recordado.

¿Cómo resuelvo de forma segura un nombre de host público antes de una solicitud HTTP?

Resuelve el nombre de host justo antes de conectar, valida todas las direcciones devueltas, elige una dirección permitida y conéctate a ella. Mantén la verificación del nombre de host TLS vinculada al nombre original y repite el proceso en cada conexión o redirección nueva.

¿Un TTL de DNS corto es automáticamente sospechoso?

No. Un TTL bajo indica cuánto tiempo puede un resolvedor almacenar una respuesta en caché, pero no demuestra que la siguiente respuesta sea segura. Trata cada resolución nueva como entrada no confiable, incluso una respuesta que llega segundos después de la anterior.

¿Qué direcciones IP debe bloquear un cliente HTTP de agente?

Bloquea direcciones de loopback, no especificadas, privadas, link-local, multicast, de documentación, NAT de grado operador y rangos locales IPv6, salvo que el usuario haya creado explícitamente un modo interno de confianza separado. Comprobar solo los rangos IPv4 RFC 1918 deja abiertas varias rutas hacia servicios locales.

¿Importan los registros CNAME para las defensas contra rebinding de DNS?

Comprueba cada dirección de la cadena completa. Un alias que parece público puede apuntar mediante registros CNAME a una respuesta privada, y un resolvedor puede devolver varios registros A y AAAA con propiedades de seguridad distintas.

¿Debe un cliente volver a resolver DNS en cada solicitud?

Puede hacerlo. Las conexiones agrupadas existentes deben conservar su dirección de par ya validada, mientras que un socket nuevo necesita una resolución y validación nuevas. No reutilices silenciosamente una decisión antigua sobre un nombre de host para aprobar una conexión TCP nueva.

¿Las redirecciones HTTP suponen un riesgo de rebinding de DNS?

Rechaza la redirección hasta que el cliente resuelva y valide su destino como un destino nuevo. Gestionar una redirección es una nueva acción saliente, aunque la solicitud inicial fuera a un host público aprobado.

¿Cómo puedo probar la protección contra rebinding de DNS?

Crea una prueba DNS controlada que devuelva primero una dirección pública y después una dirección local bloqueada, y comprueba que la segunda conexión nunca se abra. Prueba también respuestas A y AAAA mixtas, cadenas CNAME, conexiones reutilizadas y direcciones que cambian mientras una solicitud está en curso.

¿La autorización de procesos evita el rebinding de DNS?

Un proceso de agente firmado te dice quién solicitó una acción, mientras que las comprobaciones de destino en tiempo de ejecución indican adónde irá la acción. Necesitas ambas: la autorización del proceso no vuelve seguro un destino de rebinding, y el filtrado de direcciones no puede decidir si el proceso solicitante debe usar una credencial.

Sallyport

Sallyport ejecuta llamadas de API y comandos SSH por tu agente de IA. Las claves se quedan en una bóveda local de tu Mac; tú apruebas cada ejecución y cada acción queda en un registro sellado.

© 2026 Sallyport · Código abierto bajo Apache-2.0 · Oleg Sotnikov