Antecedentes:
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 una experiencia de ejercicio / aprendizaje. No quiero usar SSL ya que no quiero la molestia y, sobre todo, el costo 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 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 , suministrado por el servidor, a la solicitud, para evitar ataques de repetición.
Para llegar a la pregunta:
Tanto S3 como OAuth confían en firmar la URL de solicitud junto con algunos encabezados seleccionados. Ninguno de ellos firma el cuerpo de la solicitud para las solicitudes POST o PUT. ¿No es esto vulnerable a un ataque de hombre en el medio, que mantiene la url y los encabezados y reemplaza el cuerpo de la solicitud con los datos que el atacante desea?
Parece que puedo protegerme de esto al incluir un hash del cuerpo de la solicitud en la cadena que se firma. ¿Es esto seguro?
Respuestas:
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á preguntando acerca de la autenticación segura de clientes de 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 del 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 resumen (como el esquema personalizado de Amazon Web Service) o OAuth 1.0a o incluso autenticación básica HTTP (pero solo a través de SSL).
Estos esquemas autentican que la solicitud fue enviada por alguien esperado. TLS (SSL) (sin autenticación del cliente) asegura que los datos enviados a través del cable permanezcan sin control. Son preocupaciones separadas, pero complementarias.
Para aquellos interesados, he ampliado una pregunta SO sobre los esquemas de autenticación HTTP y cómo funcionan .
fuente
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 poco rara y requerirá un esfuerzo de implementación adicional para los clientes, que tendrá que 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. Puede volver a usar los estándares web y usar la autenticación básica HTTP (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 sigue siendo efectivo en el contexto de una conexión segura. Solo necesita asegurarse de que la contraseña nunca pase sobre texto sin formato; así que si alguna vez se recibe la contraseña a través de una conexión de texto sin formato, incluso puede deshabilitar la contraseña y enviarle 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 se transmita 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 inicia sesión (a menos que esté haciendo un cifrado JavaScript sofisticado en el navegador), y también sus cookies en cada solicitud.
Tenga en cuenta que con las API, es mejor que el cliente pase 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 debería 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 reemplazarse 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. Quizás 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 sea solo SSL).
fuente
O podría usar la solución conocida para este problema y usar SSL. Los certificados autofirmados son gratuitos y es un proyecto personal, ¿verdad?
fuente
Si necesita el hash del cuerpo como uno de los parámetros en la URL y esa URL está firmada a través de una clave privada, entonces un ataque man-in-the-middle solo podría reemplazar el cuerpo con contenido que generaría el mismo hash Fácil de hacer con valores hash MD5 ahora al menos ahora y cuando SHA-1 está roto, bueno, obtienes la imagen.
Para evitar que el cuerpo sea manipulado, necesitaría una firma del cuerpo, que un ataque de hombre en el medio sería menos probable que pudiera romper ya que no sabrían la clave privada que genera la firma. .
fuente
De hecho, la autenticación inicial S3 no permite el contenido para ser firmado, aunque con una firma MD5 débil. Simplemente puede imponer su práctica opcional de incluir un encabezado Content-MD5 en el HMAC (cadena que se 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
fuente
Recuerde que sus sugerencias dificultan que los clientes se comuniquen con el servidor. Necesitan comprender su solución innovadora y cifrar los datos en consecuencia, este modelo no es tan bueno para API pública (a menos que sea amazon \ yahoo \ google ..).
De todos modos, si debe cifrar el contenido del cuerpo, le sugiero que consulte las normas y soluciones existentes como:
Cifrado XML (estándar W3C)
Seguridad XML
fuente