Seguridad de esquemas de autenticación REST
authentication oauth (6)
Fondo:
Estoy diseñando el esquema de autenticación para un servicio web REST. Esto "realmente" no necesita ser seguro (es más un proyecto personal), pero quiero hacerlo lo más seguro posible como una experiencia de ejercicio / aprendizaje. No quiero usar SSL porque no quiero la molestia y, sobre todo, el costo de configurarlo.
Estas preguntas de SO fueron especialmente útiles para comenzar:
- Autenticación REST
- Mejores prácticas para asegurar un servicio web / API REST
- ¿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 nonce , proporcionado por el servidor, a la solicitud, para evitar ataques de repetición.
Para llegar a la pregunta:
Tanto S3 como OAuth se basan en firmar la URL de solicitud junto con algunos encabezados seleccionados. Ninguno de los dos firma el cuerpo de solicitud para solicitudes POST o PUT. ¿No es esto vulnerable a un ataque de hombre en medio, que mantiene la url y los encabezados y reemplaza el cuerpo de la solicitud por cualquier información que el atacante quiera?
Parece que puedo protegerme contra esto al incluir un hash del cuerpo de la solicitud en la cadena que se firma. ¿Es esto seguro?
De hecho, la autenticación S3 original sí permite la firma del contenido, aunque con una firma MD5 débil. Simplemente puede imponer su práctica opcional de incluir un encabezado Content-MD5 en el HMAC (cadena a firmar).
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
O podría usar la solución conocida para este problema y usar SSL. Los certificados autofirmados son gratuitos y es un proyecto personal, ¿no?
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 será un tanto funky y requerirá un esfuerzo de implementación adicional para los clientes, que tendrán que tener bibliotecas de cifrado disponibles.
Una vez que te comprometes con SSL, en realidad no se requiere nada sofisticado para la autenticación. De nuevo, puede utilizar los estándares web y usar la autenticación HTTP básica (nombre de usuario y token secreto enviado junto con cada solicitud) ya que es mucho más simple que un protocolo de firma elaborado y aún es efectivo en el contexto de una conexión segura. Solo debes asegurarte de que la contraseña nunca pase por texto sin formato; por lo tanto, si alguna vez se recibe la contraseña a través de una conexión de texto sin formato, incluso puede desactivar la contraseña y enviar un correo electrónico al desarrollador. También debe asegurarse de que las credenciales no se registren en ningún lugar al recibirlas, al igual que no registraría una contraseña normal.
HTTP Digest es un enfoque más seguro ya que evita que el token secreto se transmita; 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 sofisticado 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 puedan usarse para la verificación de API.
La razón principal para usar un token es que puede ser reemplazado si está comprometido, mientras que si la contraseña está comprometida, el propietario podría iniciar sesión en la cuenta del desarrollador y hacer lo que quiera con ella. Otra ventaja de los tokens es que puede emitir varios tokens 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 realizar la conexión solo con SSL).
Recuerde que sus sugerencias dificultan la comunicación de los clientes con el servidor. Deben entender su solución innovadora y cifrar 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 cifrar el contenido del cuerpo, le sugeriría que revise los estándares y soluciones existentes como:
Encriptación XML (estándar W3C)
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 contenido que generaría mismo hash. Fácil de hacer con valores de hash MD5 ahora al menos y cuando SHA-1 se rompe, bueno, obtienes la imagen.
Para proteger el cuerpo de la manipulación, necesitaría una firma del cuerpo, lo cual es menos probable que un ataque de hombre en el medio pueda romper ya que no sabrían la clave privada que genera la firma. .
Una respuesta anterior solo mencionaba SSL en el contexto de la transferencia de datos y en realidad no cubría la autenticación.
Realmente estás preguntando acerca de la autenticación segura de los clientes de la API REST. A menos que esté utilizando la autenticación de cliente TLS, SSL 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 como un esquema de autenticación basado en compendios (como el esquema personalizado de Amazon Web Service) o OAuth 1.0a o incluso la autenticación HTTP básica (pero solo con SSL).
Estos esquemas autentican que la solicitud fue enviada por alguien esperado. TLS (SSL) (sin autenticación de cliente) garantiza que los datos enviados a través del cable permanezcan sin control. Son preocupaciones separadas, pero complementarias.
Para aquellos interesados, he expandido una pregunta SO sobre los Esquemas de autenticación HTTP y cómo funcionan .