// Engineering Log
HTTP, HTTPS y TLS: Parte 12 — Ataques a nivel HTTP: smuggling, suplantación del Host, CSRF, XSS, SSRF y envenenamiento de caché
Publicado el 21.10.2026
// Ruta rapida
Este articulo pertenece al tema Servidores e infraestructura.
HTTPS protege los datos en tránsito, pero no sabe nada sobre lo que hay dentro de la petición. La mayor parte de los ataques a sitios se realiza sobre conexiones completamente cifradas y aprovecha las peculiaridades del propio HTTP: cómo los proxies y la aplicación analizan de forma diferente una misma petición, cómo el navegador adjunta automáticamente cookies, cómo la aplicación confía en cabeceras. En esta parte se describen las clases principales de esos ataques — cómo funcionan y qué configurar para protegerse. Debes comprobar lo descrito solo en tus sistemas o con permiso escrito del propietario.
Request smuggling: desincronización entre proxy y aplicación
Casi siempre hay un proxy delante de la aplicación — Nginx, HAProxy, CDN. Si el proxy y la aplicación determinan de forma distinta dónde termina una petición y empieza la siguiente, un atacante puede “colar” dentro de su petición el comienzo de otra.
En HTTP/1.1 la longitud del cuerpo la definen dos cabeceras: Content-Length y Transfer-Encoding: chunked. El estándar exige que si están ambas se use Transfer-Encoding, pero las implementaciones fallan:
POST / HTTP/1.1
Host: example.ru
Content-Length: 13
Transfer-Encoding: chunked
0
SMUGGLEDUn proxy que mira Content-Length pasa todo el cuerpo a la aplicación. La aplicación, que mira Transfer-Encoding, ve el fin de la petición en 0, y SMUGGLED se considera el comienzo de la siguiente petición en la misma conexión. Esa “siguiente” petición se concatena con la petición de otro usuario que llegó por la misma conexión entre el proxy y la aplicación. Resultado — respuesta ajena, robo de cookies, evasión de reglas de acceso en el proxy.
Variaciones: Transfer-Encoding: xchunked o con un espacio antes de los dos puntos, que una parte ignora y otra no; discrepancias al traducir HTTP/2 a HTTP/1.1 en el proxy (H2.CL, H2.TE); Upgrade: h2c, que el proxy deja pasar a la aplicación.
Protección:
- mantén el proxy y los servidores de aplicación actualizados — estos errores se corrigen en cada versión;
- el proxy debe rechazar peticiones ambiguas con ambas cabeceras o al menos eliminar
Content-Lengthy no reenviarlo; comprueba cómo se comporta tu conjunto, no solo el proxy; - entre el proxy y la aplicación usa HTTP/2 cuando sea posible — en él la longitud se define por frames y no hay ambigüedades;
- no pases a la aplicación la cabecera
Upgrade: h2c.
Falsificación de la cabecera Host
Host lo proporciona el cliente, y la aplicación que construye enlaces a partir de él confía en esa entrada del usuario. Un ejemplo clásico — restablecer la contraseña: la aplicación envía un correo con el enlace https://{Host}/reset?token=…. El atacante solicita el restablecimiento de la víctima con Host: attacker.example, la víctima recibe un correo real con un enlace a un sitio ajeno, entra — y el token de restablecimiento llega al atacante.
Protección:
- en Nginx configura
default_server, que responda a nombres desconocidos con el código 444 (cerrar la conexión), y pasa a la aplicación solo peticiones conserver_nameconocidos; - en la aplicación define nombres permitidos (en Django —
ALLOWED_HOSTS) y construye enlaces absolutos desde la configuración, no desde la cabecera; - lo mismo aplica a
X-Forwarded-Host: no lo aceptes de clientes.
server {
listen 80 default_server;
listen 443 ssl default_server;
ssl_reject_handshake on;
return 444;
}Envenenamiento de caché y engaño de caché
Envenenamiento de caché (cache poisoning). Un CDN o proxy cachea una respuesta por clave — normalmente esquema, host y ruta. Si la respuesta depende de una cabecera que no entra en la clave (por ejemplo, X-Forwarded-Host se usa en las URLs de los scripts de la página), un atacante envía una petición con la cabecera falsificada, el caché guarda la página corrupta y la sirve a todos los visitantes.
Engaño de caché (cache deception). La situación inversa: el caché decide que /account/profile.css es un fichero estático por la extensión. La aplicación ignora el “sufijo” y sirve la página personal del usuario. Un atacante envía un enlace a la víctima, su página personal entra al caché compartido, y el atacante la lee desde ahí.
Protección:
- en páginas personales usa
Cache-Control: privateono-store; el CDN debe respetar las cabeceras de la aplicación y no cachear solo por extensión; - si la respuesta depende de una cabecera, añádela a
Varyo a la clave del caché; - la aplicación debe responder 404 a rutas inexistentes como
/account/profile.css, y no devolver la página/account/profile.
CSRF: petición en nombre del usuario
El navegador adjunta automáticamente las cookies del sitio a las peticiones, desde donde sea que provengan. Si el usuario ha iniciado sesión en bank.example.ru y luego abre una página de un atacante con un formulario que se envía automáticamente a https://bank.example.ru/transfer, la petición irá con la cookie de sesión del usuario. Esto es falsificación de petición entre sitios (CSRF).
Protección:
- SameSite en las cookies. Con
SameSite=Lax(valor por defecto en los navegadores modernos) las cookies no se envían en peticiones POST desde otros sitios. No pongasSameSite=Nonesin necesidad; - token CSRF — un valor aleatorio en el formulario que el servidor compara con la sesión. Está presente en todos los frameworks populares;
- comprobación de
Originen peticiones que modifican estado: debe coincidir con tu sitio; - no cambies datos por GET:
SameSite=Laxpermite transiciones por enlaces, y un GET que cambie datos funcionaría.
CORS no protege contra CSRF: impide que la página lea la respuesta, pero la petición del formulario sale y se ejecuta.
XSS y Content-Security-Policy
Cross-site scripting (XSS) — inyección de JavaScript ajeno en una página de tu sitio: vía un comentario, nombre de usuario, parámetro de búsqueda mostrado sin escape. El script se ejecuta a nombre del sitio: lee la página, envía peticiones con las cookies del usuario, modifica formularios.
La protección es en varias capas:
- escapar toda la entrada de usuario al mostrarla; los motores de plantillas lo hacen por defecto, peligrosos son los lugares donde el escape está desactivado (
|safe,v-html,dangerouslySetInnerHTML,innerHTML); - cookie de sesión con
HttpOnly— el script no podrá leerla; - Content-Security-Policy — aunque se inyecte un script, el navegador no lo ejecutará si la fuente no está permitida:
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'Los scripts inline se permiten solo con un valor único nonce, que el servidor genera por cada respuesta y coloca en <script nonce="r4nd0m">. 'unsafe-inline' en script-src prácticamente anula la protección contra XSS. Implementa CSP primero con Content-Security-Policy-Report-Only, recopilando informes de violaciones, y activa el bloqueo cuando dejen de llegar informes.
SSRF: peticiones a nombre del servidor
Si la aplicación descarga algo según una URL proporcionada por el usuario — una imagen para la vista previa, un webhook, una importación por enlace — un atacante puede indicar una dirección interna: http://127.0.0.1:8080/admin, http://10.0.0.5:9200/, la dirección de metadatos de la nube http://169.254.169.254/. La petición saldrá desde dentro de tu red, donde puede no haber firewall y a menudo no hay autenticación. Mediante los metadatos de la nube se pueden obtener claves temporales de acceso a la cuenta en la nube.
Protección:
- verifica la dirección después de resolver el nombre: prohíbe rangos privados, locales y reservados (
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1,fc00::/7); - verifica también cada redirección: una URL externa puede redirigir a una interna;
- protégete contra cambio de DNS entre la verificación y la petición (DNS rebinding): conéctate a la IP que verificaste;
- en nubes activa el modo protegido de metadatos (en AWS — IMDSv2, que requiere token en la cabecera);
- lo mejor — aislar esas peticiones en un servicio o proxy separado sin acceso a la red interna.
Inyección CRLF y splitting de respuesta
Las cabeceras en HTTP/1.1 se separan con \r\n. Si la aplicación inserta entrada del usuario en una cabecera sin validar — por ejemplo, en Location al redirigir — el atacante envía %0d%0a y adjunta sus propias cabeceras o incluso el cuerpo de la respuesta: establecer cookie, inyectar script, envenenar el caché. Los frameworks modernos prohiben saltos de línea en cabeceras, pero código casero y bibliotecas antiguas son vulnerables.
En Nginx hay una trampa propia: $uri está decodificado, y en return 302 https://$host$uri; a través de %0d%0a se puede inyectar una cabecera. Usa $request_uri — se pasa en su forma original y codificada.
Redirecciones abiertas
Una URL del tipo https://example.ru/login?next=https://attacker.example que después del login redirige al usuario a un sitio ajeno. En sí no es un hack, pero el enlace empieza con tu dominio y genera confianza en correos de phishing, y en OAuth una redirección así puede filtrar el token.
Protección: permite en next solo rutas relativas dentro de tu sitio o direcciones de una lista. La comprobación “empieza por /” no es suficiente: //attacker.example es la URL de otro sitio.
Clickjacking
Un atacante embeberá tu sitio en un iframe transparente encima de su propia página, y el usuario, creyendo pulsar un botón en la página ajena, pulsa “Eliminar cuenta” o “Confirmar pago” en la tuya. Protección — prohibir embebido:
Content-Security-Policy: frame-ancestors 'none'
X-Frame-Options: DENYAuto-chequeo en 10 minutos
Los comandos abajo verifican los problemas más frecuentes. Ejecútalos solo contra tus sitios; example.ru — tu dominio, 192.0.2.10 — la IP de tu servidor.
Host desconocido. Una petición con un nombre ajeno a la IP de tu servidor no debe llegar a la aplicación:
curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: evil.example' http://192.0.2.10/
# bien: 000 (Nginx cerró la conexión con return 444) o 4xx; mal: 200 con la página del sitio
curl -sk -o /dev/null -w '%{http_code}\n' --resolve evil.example:443:192.0.2.10 https://evil.example/
# bien: 000 — el handshake fue rechazado (ssl_reject_handshake)Reflejo de X-Forwarded-Host. Un nombre falsificado no debe aparecer en enlaces de la página:
curl -s -H 'X-Forwarded-Host: evil.example' https://example.ru/ | grep -c evil.example # debe ser 0Flags de cookie. La cookie de sesión debe tener Secure, HttpOnly y SameSite:
curl -sI https://example.ru/login | grep -i '^set-cookie'Cabeceras de seguridad:
for h in strict-transport-security content-security-policy x-content-type-options \
referrer-policy x-frame-options permissions-policy; do
printf '%-28s ' $h; curl -sI https://example.ru/ | grep -qi "^$h:" && echo HAY || echo NO
doneRedirección abierta. Sustituye los parámetros que tu sitio usa para volver tras el login (next, return, redirect, url):
curl -s -o /dev/null -w '%{http_code} -> %{redirect_url}\n' 'https://example.ru/login?next=//evil.example'
# mal: redirección a evil.exampleInyección CRLF:
curl -sI 'https://example.ru/%0d%0aX-Injected:%20yes' | grep -ci '^x-injected' # debe ser 0Método TRACE debe estar desactivado:
curl -si -X TRACE https://example.ru/ | head -1 # 405 o 403Páginas personales y caché. Abre una página accesible solo tras iniciar sesión dos veces con la cookie de sesión y una sin ella:
curl -sI -b 'session=TU_SESION' https://example.ru/account | grep -iE '^(cache-control|x-cache|cf-cache-status|age)'En la respuesta debe aparecer Cache-Control: private o no-store, y en el CDN un fallo o bypass del caché (MISS, BYPASS, DYNAMIC), sin la cabecera Age.
SSRF. Si el sitio tiene funciones de descarga por URL (avatar desde dirección, importación, webhooks), pásales las direcciones http://127.0.0.1:22/ y http://169.254.169.254/latest/meta-data/. La aplicación debe rechazarlas, no devolver el contenido ni un error de conexión con detalles.
Request smuggling es difícil de comprobar manualmente. Para eso hay la extensión HTTP Request Smuggler para Burp Suite y la utilidad smuggler.py; ejecútalas en un entorno de prueba con la misma cadena de proxies que en producción.
Qué comprobar
- Proxy y servidores de aplicación actualizados; peticiones con
Content-LengthyTransfer-Encodingsimultáneos no llegan a la aplicación de forma ambigua. - Existe
default_serverque cierra peticiones conHostdesconocido. - Páginas personales no son cacheadas por el CDN.
- Cookies de sesión:
Secure; HttpOnly; SameSite=Lax. - Existe CSP sin
'unsafe-inline'para scripts y conframe-ancestors. - Las peticiones del servidor a direcciones proporcionadas por usuarios no llegan a la red interna.
- Los parámetros de redirección se validan contra una lista.
Para comprobación automática sirven OWASP ZAP y Burp Suite: contienen escáneres para todas las clases de ataques citadas. Ejecútalos en un entorno de prueba — el escaneo activo crea registros, envía formularios y puede dañar datos.
// Tarea parecida
Si estas resolviendo algo parecido
Este articulo pertenece a uno de los temas principales de trabajo. Puedes seguir leyendo sobre el tema, ir a la pagina principal para entender a que me dedico o abrir directamente los servicios.
Tema del articulo
Servidores e infraestructura
VPS, Linux, stack web, migraciones, hosting, bases de datos y operacion base.
Tareas frecuentes de esta tema
- Migrar un sitio o servicio a un nuevo servidor
- Configurar Linux, Nginx, base de datos y copias de seguridad
- Entender por que el sistema funciona de forma inestable
// Siguiente paso
Si necesitas ayuda con este tema y no solo otro articulo, es mejor ir directo a la pagina del servicio. La pagina principal y la seleccion de materiales quedan como rutas secundarias.
Abrir servicios// Reviews
Reseñas relacionadas
Gracias a Mijaíl por su disposición. Hablamos por teléfono; me explicó cómo hacerlo yo mismo. Es la segunda vez que recurro a él: todo genial y muy rápido.
Gracias a Михаил por su amabilidad. Hablamos por teléfono, me explicó cómo hacerlo por mi cuenta. Es la segunda vez que recurro, todo genial y rápido.
Quiero expresar mi enorme agradecimiento al especialista que me configuró las URLs amigables en OpenCart. Fue fácil y sencillo, y me alegra haber encontrado finalmente a un profesional que lo hizo todo con calidad y sin complicaciones. Antes cambié a cuatro especialistas y cada vez surgían problemas con la configuración, pero esta persona resolvió la tarea a la perfección.
Quiero expresar mi enorme agradecimiento al especialista que me configuró las URLs amigables en OpenCart. Configurar las URLs amigables resultó fácil y sencillo, y me alegra haber finalmente encontrado a un profesional …
Excelente trabajo, no es la primera vez que recurro; encuentra soluciones a problemas complejos. Lo recomiendo.
Excelente trabajo, recurro no por primera vez, encuentra soluciones a problemas complejos. Recomiendo.
¡Excelente trabajo! Cumplió con la tarea a tiempo y sin errores. Fue un placer colaborar, lo recomiendo.
¡Excelente trabajo! Completó la tarea encomendada a tiempo y sin errores. Fue un placer colaborar, lo recomiendo.
Excelente especialista, se adentró en el problema, lo entendió y lo solucionó. Lo recomiendo.
Excelente especialista, se involucró en el problema, lo entendió y lo solucionó. Recomiendo.
Corrección de la expresión regular en location de nginx
21.03.2024 · ★ 5/5
Había que resolver un problema con el certificado SSL en el servidor, que había sido emitido mediante Ngnix Proxy manager. Mijaíl aclaró todos los detalles de cómo tengo todo configurado, pidió accesos para evaluar la viabilidad de la solución, ya que antes no se había enfrentado a un servicio similar. Se familiarizó rápidamente y resolvió mi problema. Colaboración perfecta)
Necesitaba resolver un problema con el certificado SSL en el servidor, que fue emitido a través de Ngnix Proxy manager. Mikhail aclaró todos los detalles sobre cómo tengo todo organizado, pidió accesos para evaluar la …
Diagnóstico de Nginx Proxy Manager en un contenedor Docker y solución del problema
15.03.2024 · ★ 5/5
// Contact
¿Necesitas ayuda?
Escríbeme y te ayudaré a resolver el problema
Respondo en un día laborable (03:00-13:00 GMT)
Или оставьте заявку здесь:
// Related