Seguridad de los esquemas de autenticación REST

228

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:

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?

dF.
fuente
66
Amazon S3 puede incluir un Content-MD5 como parte de la cadena del encabezado para evitar el ataque MITM que describa.
laz
8
MD5 es una función hash muy débil y su uso se ha desaconsejado durante muchos años: en.wikipedia.org/wiki/MD5 . Use SHA2 hoy en día. MD5 es lápiz labial en un cerdo con una crisis de identidad.
Henrik
66
Startcom proporciona certificados SSL gratuitos que no arrojan advertencias de certificados en los principales navegadores
Platón
55
@SeanKAnderson (despotricar: me parece absurdo cómo la gente habla de 99.99999% cuando Internet está bajo asedio por las agencias de espionaje que ya han automatizado MUCHOS ataques en 2008; es una forma muy extraña de lidiar con un problema real. "Naaah, no será un problema; para mi abuela no podría hackearlo"
Henrik
2
@Plato Recomiendo LetsEncrypt en estos días para
certificados

Respuestas:

168

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 .

Les Hazlewood
fuente
16
Exactamente. Lo único que SSL verifica en lo que respecta a su API es que la llamada con la que se está ocupando no se ha alterado en el camino. La API todavía no tiene idea de quién le está hablando o si deberían tener acceso o no.
Tim Gautier
1
Buena respuesta. También recomendaría echar un vistazo a estos excelentes recursos ... owasp.org/index.php/Web_Service_Security_Cheat_Sheet y owasp.org/index.php/REST_Security_Cheat_Sheet (DRAFT)
dodgy_coder
2
Solo un punto menor, pero el uso de SSL también tiene el beneficio adicional de prevenir las escuchas y los ataques del hombre en el medio.
dodgy_coder
@Les Hazlewood ¿Podría explicar cómo la autenticación HTTP básica sobre Https puede ayudar a determinar si el servidor sabe con quién está hablando?
Primavera
@Les Hazlewood aquí lo hice en una pregunta; tnx stackoverflow.com/questions/14043397/…
Primavera
60

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).

mahemoff
fuente
3
Creo que podría obtener un certificado GoDaddy ssl por unos $ 30 al año. Me sorprendió ver cuánto cuestan los certificados SSL de Verisign (¿$ 600 al año o algo así si no recuerdo mal?) Pero la opción GoDaddy es perfectamente factible.
Brian Armstrong el
19
A menos que esté utilizando la autenticación mutua SSL / TLS y el servidor confíe en el certificado utilizado por el usuario / cliente, entonces no ha autenticado al usuario en el servidor / aplicación. Debería hacer algo más para autenticar al usuario en el servidor / aplicación.
Pauld
55
Ryan: el cifrado SSL en estos días toma una muy pequeña cantidad de potencia de procesamiento en comparación con lo que se usa para generar una respuesta con un marco de aplicación web como Django o rieles, etc
Cameron Walsh
44
Los certificados de startcom son gratuitos y ampliamente reconocidos. cacert.org es una alternativa abierta con menos reconocimiento
Dima Tisnek
17
Esto no responde a la pregunta, que trata sobre la autenticación.
Sam Stainsby
8

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?

wowest
fuente
2
Los certificados autofirmados son gratuitos, pero AFAIK todavía necesita una IP estática.
dF.
8
@dF no existe el requisito de tener una IP estática, excepto ciertos requisitos de licencia de certificados comerciales pagados.
Chris Marisic 01 de
Si tiene el control de los almacenes de certificados en ambos extremos (clientes y servidor), esta puede ser una opción viable, pero ... la administración y distribución de certificados es probablemente mucho más compleja en la producción que en un entorno de desarrollo. Asegúrese de comprender las complejidades de esta alternativa antes de comprometerse con ella.
aled
5

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. .

ZaDDaZ
fuente
99
Crear una cadena que generará el mismo hash md5 que el contenido válido puede ser mucho más fácil de lo que debería ser, pero encontrar una versión malvada de contenido válido que tenga el mismo valor sigue siendo prohibitivamente difícil. Esta es la razón por la cual md5 ya no se usa para el hash de contraseñas, pero todavía se usa para verificar descargas.
Tim Gautier
1

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

LiorH
fuente