Seguridad de los esquemas de autenticación REST

Fondo:

Estoy diseñando el esquema de autenticación para un servicio web REST. Esto no “realmente” necesita ser seguro (es más un proyecto personal) pero quiero hacerlo lo más seguro posible como ejercicio / experiencia de aprendizaje. No quiero usar SSL porque no quiero la molestia y, sobre todo, el gasto de configurarlo.

Estas preguntas SO fueron especialmente útiles para comenzar:

  • Autenticación RESTful
  • Mejores prácticas para asegurar una API REST / servicio web
  • ¿Ejemplos de las mejores API web de SOAP / REST / RPC? ¿Y por qué te gustan? ¿Y qué les pasa?

Estoy pensando en usar una versión simplificada de la autenticación de Amazon S3 (me gusta OAuth pero parece demasiado complicado para mis necesidades). Estoy agregando un nonce generado aleatoriamente , proporcionado por el servidor, a la solicitud, para evitar ataques de repetición.

Para llegar a la pregunta:

Tanto S3 como OAuth dependen de la firma de la URL de solicitud junto con algunos encabezados seleccionados. Ninguno de los dos firma el cuerpo de la solicitud para solicitudes POST o PUT. ¿No es esto vulnerable a un ataque man-in-the-middle, que mantiene la url y los encabezados y reemplaza el cuerpo de la solicitud con los datos que el atacante quiere?

Parece que puedo protegerme de esto al incluir un hash del cuerpo de la solicitud en la cadena que se firma. ¿Esto es seguro?

Una respuesta anterior solo menciona SSL en el contexto de la transferencia de datos y en realidad no cubre la autenticación.

Realmente está preguntando por la autenticación segura de los clientes de la API REST. A menos que use la autenticación de cliente TLS, SSL por sí solo NO es un mecanismo de autenticación viable para una API REST. SSL sin autenticación de cliente solo autentica el servidor , lo cual es irrelevante para la mayoría de las API REST porque realmente desea autenticar al cliente .

Si no usa la autenticación de cliente TLS, deberá usar algo así como un esquema de autenticación basado en resumen (como el esquema personalizado de Amazon Web Service) o OAuth 1.0a o incluso autenticación HTTP básica (pero solo a través de SSL).

Estos esquemas autentican que la solicitud fue enviada por alguien esperado. TLS (SSL) (sin autenticación de cliente) asegura que los datos enviados a través del cable permanecen sin moderar. Son preocupaciones separadas, pero complementarias.

Para los interesados, he ampliado una pregunta sobre SO sobre los esquemas de autenticación HTTP y cómo funcionan .

REST significa trabajar con los estándares de la web, y el estándar para la transferencia “segura” en la web es SSL. Cualquier otra cosa va a ser algo funky y requerirá un esfuerzo de implementación adicional para los clientes, que deberán tener bibliotecas de cifrado disponibles.

Una vez que se compromete con SSL, en realidad no se requiere nada sofisticado para la autenticación en principio. Nuevamente puedes ir con estándares web y usar autenticación HTTP básica (nombre de usuario y token secreto enviados junto con cada solicitud) ya que es mucho más simple que un protocolo de firma elaborado y sigue siendo efectivo en el contexto de una conexión segura. Solo necesita asegurarse de que la contraseña nunca pase por alto el texto simple; por lo tanto, si alguna vez se recibe la contraseña a través de una conexión de texto sin formato, es posible que incluso deshabilite la contraseña y envíe el desarrollador. También debe asegurarse de que las credenciales no se registren en ningún lugar al recibirlas, del mismo modo que no registraría una contraseña normal.

HTTP Digest es un enfoque más seguro ya que evita que se pase el token secreto; en cambio, es un hash que el servidor puede verificar en el otro extremo. Aunque puede ser excesivo para aplicaciones menos sensibles si ha tomado las precauciones mencionadas anteriormente. Después de todo, la contraseña del usuario ya se transmite en texto sin formato cuando inician sesión (a menos que esté haciendo un cifrado de JavaScript de lujo en el navegador), y también sus cookies en cada solicitud.

Tenga en cuenta que con las API, es mejor para el cliente pasar tokens (cadenas generadas aleatoriamente) en lugar de la contraseña con la que el desarrollador inicia sesión en el sitio web. Por lo tanto, el desarrollador debe poder iniciar sesión en su sitio y generar nuevos tokens que se puedan usar para la verificación de la API.

La razón principal para usar un token es que se puede reemplazar si está comprometido, mientras que si la contraseña se ve comprometida, el propietario puede iniciar sesión en la cuenta del desarrollador y hacer lo que quiera con ella. Una ventaja adicional de los tokens es que puedes emitir tokens múltiples a los mismos desarrolladores. Tal vez porque tienen múltiples aplicaciones o porque quieren tokens con diferentes niveles de acceso.

(Actualizado para cubrir las implicaciones de hacer que la conexión solo sea SSL).

O puede usar la solución conocida para este problema y usar SSL. Los certificados autofirmados son gratuitos y es un proyecto personal, ¿no?

Si necesita el hash del cuerpo como uno de los parámetros en la URL y esa URL se firma a través de una clave privada, entonces un ataque de hombre en el medio solo podría reemplazar el cuerpo con el contenido que generaría el mismo hash Fácil de hacer con los valores de hash MD5 ahora al menos y cuando SHA-1 está roto, bueno, usted obtiene la imagen.

Para proteger el cuerpo de alteraciones, deberá solicitar una firma del cuerpo, que es menos probable que un ataque de hombre en el medio pueda romperse, ya que no conocerían la clave privada que genera la firma. .

De hecho, la autenticación S3 original permite que se firme el contenido, aunque con una firma MD5 débil. Simplemente puede aplicar su práctica opcional de incluir un encabezado Content-MD5 en el HMAC (cadena a ser firmada).

http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

Su nuevo esquema de autenticación v4 es más seguro.

http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Recuerde que sus sugerencias dificultan que los clientes se comuniquen con el servidor. Deben comprender su solución innovadora y encriptar los datos en consecuencia, este modelo no es tan bueno para la API pública (a menos que sea amazon \ yahoo \ google ..).

De todos modos, si debe encriptar el contenido del cuerpo, le sugiero que revise las normas y soluciones existentes, como:

Encriptación XML (estándar W3C)

Seguridad XML