Redes · Lección 03

HTTP a fondo: métodos, cabeceras, cookies y proxies

HTTP parece un protocolo transparente hasta que cuentas cuántas manos tocan una petición antes de que llegue a tu aplicación. Entre el navegador y tu código hay casi siempre un proxy inverso, con frecuencia una red de distribución de contenido, a veces un balanceador y puede que un proxy directo del lado del cliente. Cada uno lee la petición entera y puede reescribirla. Esta lección te pone en el sitio del intermediario para que veas exactamente qué llega, qué se puede cambiar, y por qué confiar en una cabecera es delegar tu seguridad en quien la escribió.

Al terminar sabrás

  • Leer una petición y una respuesta HTTP línea a línea, sin misterio.
  • Distinguir los métodos por sus propiedades: seguro, idempotente, con efecto.
  • Explicar qué cabeceras se pueden falsificar y cuáles añade el intermediario.
  • Endurecer una cookie de sesión con los atributos correctos y saber qué protege cada uno.
  • Diferenciar un proxy directo de un proxy inverso por quién confía en quién.
  • Interceptar y modificar tu propio tráfico HTTP en un laboratorio.

1Por qué importa

Casi todas las decisiones de seguridad de una aplicación web se toman leyendo campos de una petición HTTP: quién eres por una cookie, qué puedes hacer por una cabecera, desde dónde vienes por otra. Si no tienes claro cuáles de esos campos los controla el cliente y cuáles el intermediario, vas a confiar en el sitio equivocado. La lista de fallos que salen de ahí es larga y aburridamente repetida.

El malentendido más caro es tratar HTTP como si fuera una conversación directa entre el navegador y tu código. No lo es. Entre ambos hay una cadena de intermediarios, y cada uno reescribe cosas: el proxy inverso añade la dirección real del cliente en una cabecera, la red de distribución cachea respuestas según otras, el balanceador reparte según una tercera. Un fallo de seguridad clásico es que la aplicación confíe en una cabecera que un intermediario debía haber reescrito pero no lo hizo, dejando pasar el valor que puso el cliente.

Y hay una razón de método. Esta lección es la que conecta la fase de redes con la de seguridad web que viene después. Todo lo que verás en autenticación, control de acceso o inyección ocurre dentro de una petición HTTP. Aprender a leerla y a modificarla ahora convierte esas lecciones en algo que puedes reproducir con tus manos en vez de creer.

El objetivo real

El entregable es un mapa de confianza de una petición: qué campo pone el cliente, qué campo pone cada intermediario, y en cuál de ellos puede confiar tu aplicación para tomar una decisión. Un campo que el cliente controla no puede sostener una decisión de autorización, y saber cuáles son esos campos es la mitad de la seguridad web.

2Conceptos

El vocabulario mínimo
  • Método: GET, POST, PUT, DELETE y compañía; declara la intención de la petición.
  • Seguro: un método que no debería cambiar el estado del servidor, como GET.
  • Idempotente: repetir la petición da el mismo resultado que hacerla una vez.
  • Cabecera: un par nombre-valor con metadatos; las hay de petición, de respuesta y de intermediario.
  • Cookie: estado que el servidor guarda en el cliente y que el cliente reenvía en cada petición al mismo origen.
  • Proxy directo: intermediario del lado del cliente; habla en nombre del cliente hacia cualquier servidor.
  • Proxy inverso: intermediario del lado del servidor; recibe por la aplicación y decide qué le pasa.
  • Origen: la terna esquema, host y puerto; es la unidad sobre la que el navegador aplica sus reglas.

3Explicación profunda

Una petición HTTP es texto con estructura: una línea de petición con método, ruta y versión; un bloque de cabeceras; una línea en blanco; y un cuerpo opcional. Esa simplicidad es la que permite leerla y escribirla a mano, y es también la que hace que cualquier intermediario del camino pueda alterarla sin esfuerzo. No hay nada en el protocolo que ate una cabecera a quien la escribió.

Los métodos tienen propiedades que importan para seguridad más de lo que parece. GET es seguro e idempotente: no debería cambiar nada, y por eso mandar una operación con efecto por GET es un error clásico que habilita ataques de petición forzada, porque un simple enlace o una imagen la disparan. POST no es idempotente, y esa es la razón de que un doble clic pueda cobrar dos veces. PUT y DELETE sí lo son. Diseñar la semántica correcta no es purismo: decide qué ataques son posibles y qué reintentos son seguros.

Las cabeceras hay que dividirlas en tres poblaciones y no mezclarlas nunca. Las que pone el cliente y por tanto controla por completo: User-Agent, Referer, cualquier cabecera personalizada. Ninguna de ellas puede sostener una decisión de seguridad, porque el cliente escribe lo que quiera. Las que pone el intermediario: X-Forwarded-For con la dirección real, X-Forwarded-Proto con el esquema original. Estas solo son fiables si tu aplicación únicamente es alcanzable a través de ese intermediario; si además escucha directamente, el cliente puede falsificarlas. Y las que pone el servidor en la respuesta, que son las que configuran al navegador: Set-Cookie, Content-Security-Policy, Strict-Transport-Security.

Las cookies son el mecanismo con más matices, porque cada atributo protege contra un ataque distinto y omitir uno abre una puerta concreta. HttpOnly impide que el código de la página lea la cookie, lo que limita el daño de un XSS a robar la sesión. Secure impide que viaje por texto claro, cerrando la captura en la red. SameSite controla si la cookie se envía en peticiones que vienen de otro sitio, que es la defensa de fondo contra la petición forzada. Un Domain demasiado amplio comparte la cookie con subdominios que quizá no controlas. No hay un atributo “seguro”: hay una combinación correcta para cada cookie según lo que guarde.

La distinción entre proxy directo y proxy inverso se entiende por la dirección de la confianza. Un proxy directo está del lado del cliente y actúa en su nombre: filtra su salida, oculta su origen, o intercepta su tráfico para inspeccionarlo. Un proxy inverso está del lado del servidor y protege la aplicación: termina el TLS, reparte carga, filtra peticiones y añade contexto. El mismo software hace de las dos cosas; lo que cambia es de qué lado de la frontera de confianza está y a quién representa. Confundirlos lleva a colocar el control en el sitio equivocado.

Una consecuencia que conviene interiorizar: la aplicación casi nunca ve al cliente de verdad. Ve lo que el último intermediario le contó del cliente. Por eso la seguridad web bien hecha define con precisión qué intermediario es de confianza, obliga a que todo el tráfico pase por él, y trata como sospechoso cualquier campo que ese intermediario no haya reescrito explícitamente.

4Ejemplo sencillo

# Una carta que pasa por varias manos

metodo         que quieres: "traeme" (GET), "guarda esto" (POST)
cabeceras      las notas al margen del sobre: idioma, remitente, sello
cuerpo         la carta dentro
cookie         una pulsera que te pusieron en la entrada y ensenas al volver

# Quien escribe cada nota al margen

el cliente      pone su remitente. Puede escribir el que quiera.
el proxy        tacha el remitente y escribe la direccion real desde
                donde llego la carta. En eso SI se puede confiar...
                ...solo si NADIE puede meter cartas sin pasar por el.

# Los atributos de la pulsera, uno por ataque

HttpOnly    la pulsera no se puede fotografiar desde dentro de la fiesta
Secure      la pulsera solo vale si entraste por la puerta buena
SameSite    la pulsera no funciona si te trajo alguien de otra fiesta
Lo que demuestra: el remitente lo escribe el cliente y no vale nada; la dirección real la escribe el proxy y vale solo si nadie puede saltárselo.

5Ejemplo técnico

Así se ve una petición cuando la lees desde el intermediario. Esta es la ruta /eco del laboratorio, que devuelve lo que la aplicación recibió de verdad, después de pasar por el proxy:

lo que llega a la app después del intermediario
curl -s -H "User-Agent: yo-mismo" -H "X-Rol: usuario" http://localhost:8092/eco metodo=GET ruta=/eco host=localhost agente=yo-mismo cookie= autorizacion= x-rol=administrador x-intermediario=lab-net-proxy x-forwarded-for=172.x.x.x x-forwarded-proto=http

Mira la línea x-rol. El cliente envió usuario y la aplicación recibió administrador, porque el intermediario reescribió esa cabecera por el camino. Ese es el punto entero de la lección: una aplicación que autorizara por X-Rol estaría confiando en algo que un intermediario puede poner a voluntad, y en algo que el cliente puede falsificar si consigue hablar con la aplicación sin pasar por el proxy.

CampoQuién lo controla¿Sostiene una decisión de seguridad?
User-Agent, RefererEl cliente, por completoNo, nunca
Cabeceras personalizadas del clienteEl clienteNo
X-Forwarded-ForEl intermediario, si reescribe; el cliente, si noSolo si la app es inalcanzable sin el proxy
Cookie de sesiónEl servidor la emite; el cliente la reenvíaSí, si está firmada o es opaca y bien atada
HostEl cliente, y a menudo se usa para enrutarNo sin validación explícita contra una lista

La tabla es el mapa de confianza que pedía el objetivo. La fila de X-Forwarded-For es la que más incidentes causa: parece fiable porque “la pone el proxy”, y deja de serlo en cuanto la aplicación escucha también por un camino que no pasa por el proxy.

6Diagrama

Una petición pasa del cliente al proxy inverso y de ahí a la aplicación; el proxy reescribe cabeceras y la aplicación solo ve lo que el proxy le cuenta cliente pone lo que quiere proxy inverso reescribe cabeceras aplicacion ve lo que le cuentan X-Rol: usuario X-Rol: administrador si la app tambien escucha directa: saltar el camino que hay que cerrar para que X-Forwarded-For sea fiable
Lo que demuestra: la fiabilidad de una cabecera de intermediario depende por completo de que no exista un camino que evite al intermediario. Si existe, la cabecera vuelve a ser controlada por el cliente.
Ver el mismo diagrama como código Mermaid (editable)
flowchart LR
    C[cliente: pone lo que quiere] --> P[proxy inverso: reescribe]
    P --> A[aplicacion: ve lo que le cuentan]
    C -. camino directo a cerrar .-> A

7Código

La configuración de una cookie de sesión es donde esta lección se vuelve código. Estos son los dos extremos, y la diferencia entre ellos es una lista de ataques:

# Cookie floja: la que emite el laboratorio a proposito
Set-Cookie: sesion=demo-de-laboratorio; Path=/

# Cookie endurecida: cada atributo cierra un ataque concreto
Set-Cookie: sesion=<valor opaco y aleatorio>;
            HttpOnly;          # el JS de la pagina no la lee: limita el XSS
            Secure;            # no viaja por HTTP en claro
            SameSite=Lax;      # no se envia en navegaciones desde otro sitio
            Path=/;            # alcance minimo dentro del origen
            Max-Age=3600       # caduca: una sesion robada no es eterna

Cada atributo de la versión endurecida corresponde a una entrada de la fase de seguridad web: HttpOnly aparece en la lección de XSS, SameSite en la de petición forzada, Secure en la de TLS que viene justo después de esta. Endurecer la cookie no es una casilla que marcar: es entender de qué te protege cada atributo, y por eso omitir uno es una decisión, no un olvido.

# Y la comprobacion, contra tu propio laboratorio
for attr in HttpOnly Secure SameSite; do
  if curl -sI http://localhost:8092/login | grep -i Set-Cookie | grep -qi "$attr"; then
    echo "presente  $attr"
  else
    echo "FALTA     $attr"
  fi
done

8Qué puede salir mal

Los cuatro errores clásicos

Autorizar por una cabecera que el cliente controla. Decidir que alguien es administrador porque envió X-Rol: administrador, o confiar en X-Forwarded-For cuando la aplicación es alcanzable sin pasar por el proxy. El cliente escribe esos valores.

Operaciones con efecto por GET. Un GET que borra o transfiere se dispara con un enlace, una imagen o una precarga del navegador. La semántica del método no es decorativa.

Cookies de sesión sin atributos. Sin HttpOnly un XSS se lleva la sesión; sin Secure la captura de red la lee; sin SameSite la petición forzada la usa. Tres puertas por omitir tres palabras.

Confiar en la cabecera Host sin validarla. Muchas aplicaciones construyen enlaces de recuperación de contraseña con el Host que envió el cliente. Cambiarlo redirige el enlace hacia un dominio del atacante.

9Cómo lo abusaría un atacante

Vista desde el otro lado

Lo primero que hace alguien que ataca una web es exactamente lo que vas a hacer en el laboratorio: ponerse un intermediario propio entre su navegador y la aplicación, para ver la petición cruda y modificarla campo a campo. No para explotar nada todavía, sino para entender qué campos existen y cuáles la aplicación parece leer para decidir.

Después prueba la confianza mal colocada. Envía X-Forwarded-For con una dirección interna, por si la aplicación cree que viene de dentro. Cambia el Host, por si eso reescribe enlaces. Inventa cabeceras de rol o de depuración, por si alguna quedó cableada. Ninguno de estos intentos rompe nada; simplemente comprueban si la aplicación confía en entradas que no debería, y con sorprendente frecuencia lo hace.

La tercera línea es la cookie. Si no tiene HttpOnly, cualquier XSS la convierte en robo de sesión. Si no tiene SameSite, una página del atacante puede disparar peticiones autenticadas en nombre de la víctima. Y si no tiene Secure, basta con estar en la red, que es justo lo que la fase anterior enseñó a conseguir. Las tres debilidades se detectan mirando una sola cabecera de respuesta.

10Cómo defenderlo

Qué hacer con esto mañana
  • No autorices por cabeceras que el cliente controla. La autorización se decide con la sesión validada, no con X-cualquier-cosa.
  • Haz que la aplicación solo sea alcanzable a través del proxy antes de confiar en una sola cabecera que el proxy reescriba.
  • Respeta la semántica de los métodos. Lo que cambia estado va por POST, PUT o DELETE, nunca por GET.
  • Endurece cada cookie con la combinación que corresponde a lo que guarda, y comprueba los atributos con una prueba automática.
  • Valida la cabecera Host contra una lista de valores esperados antes de usarla para construir nada.
  • Añade las cabeceras de respuesta de seguridad en el proxy, para que apliquen a toda la aplicación sin depender de cada endpoint.

11Laboratorio

Estado: laboratorio local lab-net-proxy
Targethttp://localhost:8092
Autorizaciónsistema local creado por ti para entrenamiento
Interceptar y modificar peticiones solo se hace contra tu propia aplicación. Hacerlo contra un servicio ajeno, aunque sea “solo para ver”, es un acceso no autorizado. Aquí el cliente, el intermediario y la aplicación son tuyos.

Levanta el laboratorio. Trae un cliente, un intermediario y la aplicación objetivo:

cd cursos/seguridad/labs/lab-net-proxy docker compose up -d --build docker compose ps

Primero mira la aplicación de frente, sin intermediario, y después a través de él. Compara las dos salidas de /eco:

la misma petición, con y sin intermediario
docker compose exec cliente curl -s http://app/eco metodo=GET ruta=/eco x-rol= x-forwarded-for= curl -s http://localhost:8092/eco metodo=GET ruta=/eco x-rol=administrador x-forwarded-for=172.x.x.x x-intermediario=lab-net-proxy # el intermediario invento x-rol y x-forwarded-for que tu no enviaste

Ahora observa lo que el intermediario registra de ti, cookie incluida, y comprueba que la cookie de sesión sale sin ningún atributo de seguridad:

curl -s -c galletas.txt http://localhost:8092/login curl -sI http://localhost:8092/login | grep -i set-cookie curl -s -b galletas.txt http://localhost:8092/eco docker compose logs --tail 5 intermediario

Y comprueba que el intermediario también modifica la respuesta, no solo la petición. La ruta /saldo sale reescrita; la misma por el camino directo, no:

curl -s http://localhost:8092/saldo curl -s http://localhost:8092/directo/saldo docker compose down -v

12Ejercicios

Clasifica cinco campos por confianza

Para cada uno, di quién lo controla y si tu aplicación podría usarlo para una decisión de seguridad: (1) User-Agent; (2) X-Forwarded-For con la app solo alcanzable por el proxy; (3) el mismo con la app también alcanzable directamente; (4) el valor de una cookie de sesión firmada; (5) la cabecera Host.

La pregunta clave siempre es la misma: ¿quién escribe este campo justo antes de que llegue a la app?
Para las de intermediario, la fiabilidad depende de que no exista un camino que salte el intermediario.
Los casos (2) y (3) son la misma cabecera con distinta topología, y por eso dan respuestas opuestas.
Solución

(1) Cliente, no sirve para nada de seguridad. (2) Intermediario fiable, porque no hay otro camino: se puede usar con cuidado. (3) Cliente disfrazado de intermediario, no sirve: el cliente puede ponerla al hablar directo con la app. (4) Servidor, sirve: la firma es lo que ata el valor a que lo emitió el servidor. (5) Cliente, no sirve sin validarla contra una lista de hosts esperados.

Clave: cliente · fiable · no fiable · fiable · no sin validar. El par (2)/(3) está bien resuelto solo si das respuestas distintas.

Endurece la cookie del laboratorio

La ruta /login emite una cookie sin ningún atributo. Modifica la configuración de la aplicación en el laboratorio para que emita la cookie endurecida, y demuestra con curl que los tres atributos están presentes. Explica qué ataque cierra cada uno.

La cookie se emite en conf/app.conf, en la línea add_header Set-Cookie.
Añade los atributos en la misma cabecera y vuelve a levantar el servicio de la app con up -d.
Comprueba con curl -sI sobre /login; el atributo Secure es honesto solo si de verdad sirves por HTTPS, así que aquí anótalo como pendiente para la lección siguiente.
Solución
# en conf/app.conf, ruta /login
add_header Set-Cookie "sesion=demo-de-laboratorio; Path=/; HttpOnly; SameSite=Lax; Max-Age=3600";

HttpOnly impide que un XSS lea la cookie desde el navegador; SameSite=Lax evita que la cookie viaje en peticiones iniciadas por otro sitio, que es la base de la petición forzada; Max-Age limita la vida de una sesión robada. Secure queda pendiente porque el laboratorio sirve HTTP en claro, y añadirlo aquí sería una casilla marcada sin efecto real: en f02-tls ese servicio pasa a HTTPS y entonces el atributo protege de verdad.

Clave: se evalúa que expliques por qué Secure no debe ponerse todavía. Marcarlo sin HTTPS es teatro de seguridad.

Investiga el contrabando de peticiones

Cuando dos intermediarios interpretan de forma distinta dónde acaba una petición, aparece una familia de ataques con nombre propio. Investiga fuera de esta lección y responde: ¿qué dos cabeceras entran en conflicto?, ¿por qué el desacuerdo entre proxy y aplicación permite “colar” una segunda petición?, y ¿qué defensa lo cierra de raíz?

Las dos cabeceras dicen, cada una a su manera, cuánto mide el cuerpo de la petición.
Busca por el término en inglés “request smuggling” y por las cabeceras Content-Length y Transfer-Encoding.
Si el proxy cree que la petición acaba en un punto y la aplicación en otro, lo que sobra para uno es el principio de otra petición para el otro.
Solución

El conflicto es entre Content-Length, que declara el tamaño del cuerpo en bytes, y Transfer-Encoding: chunked, que lo declara por trozos. Cuando una petición trae las dos y el proxy hace caso a una mientras la aplicación hace caso a la otra, discrepan sobre dónde termina el cuerpo. Los bytes que para el proxy son el final del cuerpo, para la aplicación son el comienzo de una segunda petición que el proxy no llegó a ver, y que por tanto no pasó por ninguno de sus controles.

La defensa de raíz es no permitir la ambigüedad: rechazar toda petición que traiga las dos cabeceras, normalizar el mensaje en el proxy antes de reenviarlo, y usar en lo posible protocolos donde el enmarcado no dependa de estas cabeceras. Es un buen recordatorio de que un intermediario no solo reescribe: también interpreta, y dos interpretaciones distintas son una vulnerabilidad.

Clave: Content-Length contra Transfer-Encoding. Lo evaluable es que expliques cómo el desacuerdo de enmarcado inyecta una petición no vista.

Red Team · falsifica la cabecera de confianza

Dentro del lab-net-proxy, y solo dentro: demuestra que la cabecera X-Forwarded-For solo es fiable cuando la aplicación es inalcanzable sin el proxy. Habla directamente con la aplicación, sáltate el intermediario y consigue que /eco refleje una dirección que tú elegiste.

El intermediario no es el único que puede hablar con la app. El contenedor cliente también está en la red interna.
Si envías tú la cabecera directamente a la app, no hay nadie que la reescriba.
Prueba docker compose exec cliente curl -s -H "X-Forwarded-For: dentro-de-la-red" http://app/eco.
Solución

Hablando directamente con app, la cabecera X-Forwarded-For que envía el cliente llega intacta, porque no hay intermediario que la sobrescriba. La aplicación reflejará la dirección que enviaste o lo que hayas puesto. La conclusión práctica es dura: una aplicación que decida “esto viene de la red interna” a partir de esa cabecera, y que además escuche por un camino que no pasa por el proxy, está tomando decisiones de seguridad con datos del atacante.

Por eso la defensa no es “validar la cabecera”, que es imposible, sino garantizar la topología: que la aplicación sea físicamente inalcanzable salvo a través del proxy. En el laboratorio eso se ve porque app no publica puertos, pero sí es alcanzable desde otros contenedores de su red, que es exactamente el hueco.

Clave: el hallazgo no es la cabecera falsificada, es entender que la fiabilidad era una propiedad de la topología, no del proxy.

Blue Team · qué registra el intermediario y qué no

Mira el formato de log del intermediario en conf/intermediario.conf y genera tráfico variado contra él. Responde: con lo que registra, ¿podrías distinguir una petición legítima de una con una cabecera de rol falsificada? ¿Qué campos añadirías al log para poder investigar la falsificación del ejercicio anterior?

El formato del intermediario ya registra la cookie y algunas cabeceras. Mira exactamente cuáles.
El ataque del ejercicio rojo no pasa por el intermediario, así que su log no lo ve. Piensa qué log sí lo vería.
Necesitarías el log de la propia aplicación, con el valor de las cabeceras de confianza tal y como le llegan, para detectar el salto.
Solución

El log del intermediario registra la petición, la cookie y varias cabeceras, así que sobre el tráfico que pasa por él se puede investigar bastante. El problema es que el ataque del ejercicio rojo no pasa por el intermediario: habla directo con la aplicación, y por tanto es invisible para ese log. La única forma de detectarlo es que la propia aplicación registre el valor de X-Forwarded-For tal y como le llega, y que ese log se compare con el del proxy: cualquier petición que la app vio y el proxy no, es un salto.

El campo clave que falta, otra vez, es la correlación: un identificador que el proxy inyecte y la app registre. Sin él, tienes dos logs que no se pueden cruzar, y el salto se pierde entre ambos.

Clave: el entregable es la lista de campos que permiten cruzar el log del proxy con el de la app. Es la misma correlación que la fase 14 va a implementar.

Architecture Challenge · dónde vive cada control HTTP

Diseña dónde colocarías cada control de una aplicación web con un proxy inverso delante: terminación de TLS, cabeceras de respuesta de seguridad, limitación de tasa, autorización y validación de entrada. Justifica qué va en el proxy y qué va en la aplicación, y explica qué pasa si la aplicación queda alcanzable sin pasar por el proxy.

Algunos controles se benefician de estar en un solo sitio para toda la aplicación; otros necesitan el contexto de negocio.
La autorización necesita saber quién es el usuario y qué pide. ¿Tiene el proxy ese contexto?
Todo control que dependa de que el proxy sea el único camino es tan fuerte como esa suposición. Empieza por asegurarla.
Solución

Una asignación razonable: en el proxy, la terminación de TLS, las cabeceras de respuesta de seguridad y una primera capa de limitación de tasa, porque son controles uniformes que conviene aplicar en un único sitio para toda la aplicación. En la aplicación, la autorización y la validación de entrada, porque necesitan el contexto de negocio que el proxy no tiene: qué recurso concreto se pide y qué le corresponde a este usuario. La validación de entrada, además, nunca se delega por completo, porque el proxy no conoce la forma de cada dato.

La condición que sostiene todo el diseño es que la aplicación sea inalcanzable salvo por el proxy. Si ese supuesto se rompe, cada control que estaba en el proxy desaparece para quien entra por el otro camino, y las cabeceras de confianza vuelven a estar en manos del cliente. Por eso la primera línea de esta arquitectura no es un control HTTP, es la segmentación de red que la fase siguiente construye.

Clave: no hay una única respuesta. Se evalúa que la autorización quede en la app, que las cabeceras uniformes queden en el proxy, y que nombres la topología como supuesto de todo lo demás.

13Preguntas de comprensión

Comprobación

Tu aplicación decide que alguien es administrador porque envió X-Rol: administrador. ¿Qué tiene de malo?

La autorización se decide con la sesión validada, no con un campo que el cliente escribe a voluntad.

¿Cuándo es fiable la cabecera X-Forwarded-For?

Su fiabilidad es una propiedad de la topología. Si existe un camino que salta el proxy, el cliente puede falsificarla.

¿Qué atributo de cookie limita el daño de un XSS a la sesión?

SameSite ataca la petición forzada y Secure la captura de red; el que corta la lectura desde el navegador es HttpOnly.

¿Por qué una operación que cambia estado no debe ir por GET?

GET es un método seguro por contrato: al usarlo para algo con efecto, cualquier cosa que cargue una URL ejecuta la operación.

0 / 4

14Reto adicional

Audita las cabeceras de un sitio tuyo

Toma una aplicación web que controles y audita sus cabeceras de respuesta. Para cada una de las de seguridad —Content-Security-Policy, Strict-Transport-Security, los atributos de las cookies— responde: ¿está?, ¿con qué valor?, ¿qué ataque cubre y contra cuál te deja expuesto su ausencia o su valor laxo?

curl -sI te da todas las cabeceras de respuesta de un vistazo.
Una CSP muy permisiva cuenta como ausente para la mayoría de los ataques que debería cubrir.
Mira si las cabeceras de seguridad las pone la aplicación o el proxy; si es el proxy, comprueba que aplican a todas las rutas.
Solución

El patrón habitual es que falten la mitad y que las presentes tengan valores por defecto. La Content-Security-Policy suele estar ausente o tan permisiva que no cubre el XSS que debería; la Strict-Transport-Security a menudo falta, dejando abierta la primera visita por HTTP; y las cookies casi siempre carecen de al menos un atributo. Lo interesante es que este mismo curso predica con el ejemplo: la CSP de estas páginas es la que estás auditando, y por eso el contenido interactivo no usa scripts en línea.

El entregable no es la lista de lo que falta, sino qué ataque habilita cada ausencia. Una cabecera sin ese razonamiento es una recomendación copiada; con él, es una decisión de riesgo escrita con el vocabulario de la fase 01.

Clave: cada hallazgo debe llevar el ataque que abre. “Falta HSTS” no es un hallazgo; “sin HSTS, la primera visita por HTTP es interceptable” sí lo es.

15Resumen

Puntos clave
  • Una petición HTTP es texto con estructura y cualquier intermediario del camino puede leerla y reescribirla.
  • Las cabeceras se dividen en las que pone el cliente, las que pone el intermediario y las que pone el servidor. Solo las terceras, y las de intermediario bajo condición, sostienen decisiones.
  • La fiabilidad de una cabecera de intermediario depende de que no exista un camino que salte al intermediario. Es topología, no protocolo.
  • Los métodos tienen semántica: GET es seguro, POST no es idempotente. Respetarla decide qué ataques son posibles.
  • Cada atributo de cookie cierra un ataque concreto. Omitir uno es una decisión, no un olvido, y Secure sin HTTPS es teatro.
  • Un proxy directo representa al cliente y uno inverso al servidor. La confianza va en direcciones opuestas.
¿Por qué no puedes autorizar por una cabecera personalizada del cliente?
Porque el cliente escribe su valor a voluntad. La autorización se decide con la sesión validada por el servidor.
¿Qué convierte a X-Forwarded-For en fiable o en falsificable?
Que exista o no un camino hacia la aplicación que evite al proxy. Si lo hay, el cliente la controla; si no, el proxy.
¿Qué protege SameSite en una cookie?
Impide que la cookie se envíe en peticiones iniciadas desde otro sitio, que es la base de la petición forzada.
¿En qué se diferencia un proxy directo de uno inverso?
En de qué lado de la frontera están: el directo actúa por el cliente, el inverso protege al servidor. El software puede ser el mismo.

16Mis notas

Cierre de la lección

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.