Tenemos una situación en la que la identidad de un usuario se puede verificar de la siguiente manera: el proveedor de la red conoce la identidad del usuario e inyecta encabezados seguros en la solicitud HTTP, que nuestros servidores pueden usar para autenticar al usuario.
Estamos escribiendo aplicaciones cliente-servidor y queremos usar este mecanismo para autenticar automáticamente al usuario. No podemos usar HTTPS de extremo a extremo para la solicitud de autenticación porque, obviamente, la red no pudo inyectar encabezados en ese caso.
EDITAR: configuración aproximadamente equivalente:
(cliente < -VPN- > proxy HTTP) < -internet- > nuestro servidor
Suponga que la VPN (sección en negrita) es segura y el usuario está autenticado en la VPN.
El cliente genera una solicitud HTTP. Un proxy dentro de la red conoce la identidad del cliente y genera un token que se agrega automáticamente a los encabezados en la solicitud HTTP con proxy. Todo esto sucede en un dominio seguro y, por lo tanto, no puede ser comprometido. (Desafortunadamente, no podemos cambiar nada en la configuración de VPN, como que el proxy realice una solicitud HTTPS en su lugar).
Nuestro servidor puede consultar a la red (de forma segura) para determinar la identidad del cliente que inició la solicitud.
Suposiciones:
- Este requisito de HTTP es un hecho y no se puede cambiar.
- Un atacante no puede engañar el proceso de verificación de identidad presentando encabezados falsos.
- Un atacante podría interceptar / comprometer la solicitud / respuesta HTTP.
- El servidor no tiene estado (por lo tanto, no se almacenan claves de un solo uso del lado del servidor).
- El almacenamiento de una clave privada en la aplicación cliente no es una opción, ya que podría verse comprometida
- La solicitud / respuesta HTTP se utilizará para autenticar automáticamente al usuario, pero todas las demás interacciones antes (si es necesario) y después se realizarán a través de HTTPS.
Esto es lo que hemos intentado hasta ahora:
- El cliente obtiene una clave pública
PK
del servidor a través de HTTPS - El cliente genera una clave simétrica
SK
- El cliente cifra
SK
usandoPK
y lo envía al servidor a través de HTTP - El servidor verifica la identidad del usuario y genera el token de autenticación
AT
- El servidor cifra
AT
usandoSK
- > %código% - El servidor firma
E(AT,SK)
usando su clave privada y lo envía al cliente - El cliente usa
E(AT,SK)
para verificar la firma - El cliente usa
PK
para descifrarSK
dandoE(AT,SK)
- El cliente usa
AT
para autenticar todo el tráfico HTTPS subsiguiente.
(Y probablemente deberíamos usar pares de claves separados para el cifrado y la firma, pero ignoremos eso por ahora).
Por lo que puedo ver, esto es seguro contra intrusos (ya que no tendrán AT
), pero si un atacante malintencionado puede modificar la solicitud HTTP, no hay nada que impida que generen su propia clave simétrica en lugar de SK
, cifrándolo con SK
, reemplazando la carga útil de solicitud con eso y el servidor no tendrá idea de que no está hablando con el cliente real. Entonces, el servidor felizmente cifrará un PK
válido y lo enviará de vuelta al atacante, quien podrá proceder con impunidad.
¿Hay una manera de apuntalar este agujero? ¿Es incluso posible hacer esto con un servidor sin estado?
EDITAR: si el servidor puede detectar la manipulación y abortar el proceso de autenticación, eso sería suficiente. "Esto no es posible porque X" también es una respuesta válida, si se puede demostrar.