Mejores prácticas para asegurar un API REST / servicio web [cerrado]

828

Al diseñar una API o servicio REST, ¿existen mejores prácticas establecidas para tratar con la seguridad (Autenticación, Autorización, Gestión de Identidad)?

Al crear una API SOAP, tiene WS-Security como guía y existe mucha literatura sobre el tema. He encontrado menos información sobre cómo asegurar puntos finales REST.

Si bien entiendo que REST intencionalmente no tiene especificaciones análogas a WS- * espero que hayan surgido las mejores prácticas o los patrones recomendados.

Cualquier discusión o enlaces a documentos relevantes sería muy apreciada. Si es importante, estaríamos usando WCF con mensajes serializados POX / JSON para nuestros API / Servicios REST creados utilizando v3.5 de .NET Framework.

Nathan
fuente
1
¿Conoces alguna aplicación real completa que use buenos patrones y prácticas con API REST y servicios web en github?
PreguntonCojoneroCabrón

Respuestas:

298

Como dijo tweakt, Amazon S3 es un buen modelo para trabajar. Sus firmas de solicitud tienen algunas características (como la incorporación de una marca de tiempo) que ayudan a proteger contra la repetición de solicitudes accidentales y maliciosas.

Lo bueno de HTTP Basic es que prácticamente todas las bibliotecas HTTP lo admiten. Por supuesto, necesitará requerir SSL en este caso porque enviar contraseñas de texto sin formato a través de la red es casi universalmente algo malo. Basic es preferible a Digest cuando se usa SSL porque incluso si la persona que llama ya sabe que se requieren credenciales, Digest requiere un viaje de ida y vuelta adicional para intercambiar el valor nonce. Con Basic, las personas que llaman simplemente envían las credenciales la primera vez.

Una vez que se establece la identidad del cliente, la autorización es realmente solo un problema de implementación. Sin embargo, puede delegar la autorización a algún otro componente con un modelo de autorización existente. Una vez más, lo bueno de Basic aquí es que su servidor termina con una copia en texto plano de la contraseña del cliente que simplemente puede pasar a otro componente dentro de su infraestructura según sea necesario.

Greg Hewgill
fuente
3
SSL es una parte importante de la seguridad, pero no todas las aplicaciones requieren ese nivel de cifrado. Si alguien roba en tránsito lo que vas a publicar públicamente en Twitter, ¿es un inconveniente tan significativo? Para la mayoría de las API, se preferirá el cifrado SSL. Los requisitos de infraestructura de SSL son algo más altos que con el texto sin formato y ningún servidor de almacenamiento en caché intermedio (leer aquí basado en borde) puede participar en el almacenamiento en caché del contenido al que se accede repetidamente. Tenga cuidado, su escalabilidad puede verse afectada si necesita absolutamente el cifrado ofrecido.
Norman H
36
@ NormanH: Su argumento es engañoso, porque si alguien puede ver la transacción completa que uso para publicar en Twitter, entonces podría suplantarme y publicar sus propios mensajes a mi nombre.
Greg Hewgill
3
Citando de wikipedia sobre la autenticación implícita, "la autenticación de acceso implícita es uno de los métodos acordados que un servidor web puede utilizar para negociar credenciales con el navegador web de un usuario. Aplica una función hash a una contraseña antes de enviarla a través de la red, que es más seguro que la autenticación de acceso básica, que envía texto sin formato ". cuál sería una forma estándar de lograr lo que mencioné anteriormente. (Ver en.wikipedia.org/wiki/Digest_access_authentication para más detalles)
Norman H
55
"sending plaintext passwords over the net is almost universally a bad thing"- ¿Puedes dar más detalles sobre el "casi"? ¿Cuándo no es una mala idea?
toniedzwiedz
2
@GregHewgill incluso en una red privada, no quisiera que mis usuarios puedan interceptar las contraseñas de los demás. La única situación en la que puedo pensar, en la que está bien enviar una contraseña a través de una red es cuando el usuario está solo en la red. El hecho de que tales cosas sucedan en otros lugares no es una razón para permitirlo.
toniedzwiedz
115

No hay estándares para REST que no sean HTTP. Hay servicios REST establecidos por ahí. Te sugiero que les eches un vistazo y entiendas cómo funcionan.

Por ejemplo, tomamos prestadas muchas ideas del servicio REST S3 de Amazon cuando desarrollamos las nuestras. Pero optamos por no usar el modelo de seguridad más avanzado basado en firmas de solicitud. El enfoque más simple es la autenticación básica HTTP sobre SSL. Tienes que decidir qué funciona mejor en tu situación.

Además, recomiendo el libro RESTful Web Services de O'reilly. Explica los conceptos básicos y proporciona algunas mejores prácticas. En general, puede tomar el modelo que proporcionan y asignarlo a su propia aplicación.

Mark Renouf
fuente
66
RESTful Web Services es definitivamente un gran libro. Una lectura obligada en esta área. Fue francamente inspirador.
EdgarVerona
66
¿Cómo es que @aehlke ha recibido tantos votos a favor por ese comentario considerando (1) que no existe una especificación REST y (2) la Disertación de Fielding sobre los estilos arquitectónicos y el diseño de arquitecturas de software basadas en red menciona explícitamente REST y HTTP en 6.3: REST aplicado a HTTP.
20
HTTP no es un requisito para REST.
nategood
1
El libro RESTful Web Services está disponible de forma gratuita en su sitio web: crummy.com/writing/RESTful-Web-Services
icc97
Estaba planeando leer el libro y luego me di cuenta de que está dirigido principalmente al formato XML. ¿Debo usar este libro considerando la popularidad de JSON? O no depende del formato de intercambio de datos. Necesita orientación
Bhargav Jhaveri
72

También es posible que desee echar un vistazo a OAuth , un protocolo abierto emergente para la autorización basada en tokens que se dirige específicamente a las apis http.

Es muy similar al enfoque adoptado por flickr y recuerda los apis de "descanso" de la leche (no necesariamente buenos ejemplos de apis relajantes, pero buenos ejemplos del enfoque basado en tokens).

John Spurlock
fuente
3
Pero parece que oAuth de dos patas, que creo que es lo que se necesita aquí, no está cubierto (falta de información) tanto como el de 3 patas.
redben
44
OAuth se trata de la delegación de autorización, es decir, yo, el propietario de la información / cuenta, deja que el servicio A interactúe con mis datos en el servicio B (por ejemplo, dejo que Twitter escriba en mi facebook). No es autorización en el sentido más amplio que se trata de controlar lo que los usuarios pueden hacer con los recursos (datos, información, servicios ...). Aquí es donde interviene XACML. XACML le permite definir políticas de autorización sobre quién puede hacer qué.
David Brossard
60

Hay una gran lista de verificación en Github :

Autenticación

  • No reinvente la rueda en Autenticación, generación de tokens, almacenamiento de contraseñas. Usa los estándares.

  • Max RetryFunciones de uso y cárcel en Iniciar sesión.

  • Use el cifrado en todos los datos confidenciales.

JWT (JSON Web Token)

  • Use una clave aleatoria complicada (JWT Secret) para hacer que el bruto fuerce la ficha muy difícil.

  • No extraiga el algoritmo de la carga útil. Forzar el algoritmo en el backend (HS256 o RS256).

  • Haga que la expiración del token ( TTL, RTTL) sea lo más corta posible.

  • No almacene datos confidenciales en la JWTcarga útil, se pueden decodificar fácilmente.

OAuth

  • Valide siempre el redirect_urilado del servidor para permitir solo las URL incluidas en la lista blanca.

  • Siempre trate de intercambiar por código y no por tokens (no permitir response_type=token).

  • Utilice el parámetro de estado con un hash aleatorio para evitar CSRFel OAuthproceso de autenticación.

  • Defina el alcance predeterminado y valide los parámetros de alcance para cada aplicación.

Acceso

  • Limite las solicitudes (aceleración) para evitar ataques DDoS / fuerza bruta.

  • Use HTTPS en el lado del servidor para evitar MITM (Man In The Middle Attack)

  • Use el HSTSencabezado con SSL para evitar el ataque SSL Strip.

Entrada

  • Use el método HTTP adecuado de acuerdo con la operación: GET(leer), POST(crear), PUT/PATCH(reemplazar / actualizar) y DELETE(para eliminar un registro), y responda 405 Method Not Allowedsi el método solicitado no es apropiado para el recurso solicitado.

  • Validar el tipo de contenido a petición Acceptde cabecera (Negociación de contenido) para permitir sólo a su formato compatible (por ejemplo application/xml, application/json, etc) y responder con la 406 Not Acceptablerespuesta si no emparejado.

  • Validar content-typede datos publicada como aceptes (por ejemplo application/x-www-form-urlencoded, multipart/form-data, application/json, etc.).

  • Valide la entrada del usuario para evitar vulnerabilidades comunes (por ejemplo, XSS, inyección de SQL, ejecución remota de código, etc.).

  • No use datos confidenciales (credenciales, contraseñas, tokens de seguridad o claves API) en la URL, pero use el Authorizationencabezado estándar .

  • Use un servicio API Gateway para habilitar el almacenamiento en caché, las Rate Limitpolíticas (por ejemplo, Cuota, detención de picos, límite de velocidad concurrente) e implemente los recursos de API dinámicamente.

Procesando

  • Compruebe si todos los puntos finales están protegidos detrás de la autenticación para evitar un proceso de autenticación interrumpido.

  • Se debe evitar la identificación del recurso propio del usuario. Use / me / orders en lugar de / user / 654321 / orders.

  • No incremente automáticamente las ID. Use UUID en su lugar.

  • Si está analizando archivos XML, asegúrese de que el análisis de entidades no esté habilitado para evitar XXE (ataque de entidad externa XML).

  • Si está analizando archivos XML, asegúrese de que la expansión de la entidad no esté habilitada para evitar la bomba Billion Laughs / XML a través del ataque de expansión de entidad exponencial.

  • Use un CDN para cargar archivos.

  • Si está tratando con una gran cantidad de datos, use Trabajadores y Colas para procesar la mayor cantidad posible en segundo plano y devolver la respuesta rápidamente para evitar el Bloqueo HTTP.

  • No se olvide de apagar el DEBUG OFF.

Salida

  • Enviar X-Content-Type-Options: nosniffencabezado.

  • Enviar X-Frame-Options: denyencabezado.

  • Enviar Content-Security-Policy: default-src 'none'encabezado.

  • Retire las huellas digitales de cabeceras - X-Powered-By, Server, X-AspNet-Versionetc.

  • Fuerza content-typepara su respuesta, si regresa, application/jsonentonces su tipo de contenido de respuesta es application/json.

  • No devuelva datos confidenciales como credenciales, contraseñas, tokens de seguridad.

  • Devuelva el código de estado adecuado de acuerdo con la operación completada. (por ejemplo 200 OK, 400 Bad Request, 401 Unauthorized, 405 Method Not Allowed, etc).

Andrejs
fuente
1
Buena lista, aunque un poco obstinada, y comienza con una tontería: "No use la autenticación básica Use autenticación estándar (por ejemplo, JWT, OAuth)". No puede obtener más estándar y que Basic Auth, y tiene su lugar, especialmente para las API donde los clientes no son navegadores (para los navegadores JWT suele ser más adecuado). OAuth, por otro lado, está utilizando otro conjunto de compromisos para la autenticación y no es realmente comparable a Basic Auth y JWT.
johndodo
Tienes razón, BasicAuth con HTTPS es común, pero es muy debatido: security.stackexchange.com/questions/988/… . Eliminaré este punto de todos modos.
Andrejs
43

Estoy un poco sorprendido de que aún no se haya mencionado SSL con certificados de cliente. De acuerdo, este enfoque solo es realmente útil si puede contar con la comunidad de usuarios identificados por certificados. Sin embargo, varios gobiernos / empresas los emiten a sus usuarios. El usuario no tiene que preocuparse por crear otra combinación de nombre de usuario / contraseña, y la identidad se establece en todas y cada una de las conexiones para que la comunicación con el servidor pueda ser completamente apátrida, no se requieren sesiones de usuario. (No implica que alguna / todas las otras soluciones mencionadas requieran sesiones)

stinkymatt
fuente
De hecho, utilizamos esto para algunas integraciones, así como túneles vpn cifrados para admitir sistemas más antiguos que no controlamos y que no pueden comunicarse a través de https.
Casey
Los certificados de cliente pueden causar problemas cuando necesita equilibrio de carga ... se puede hacer, pero es menos sencillo.
Jeremy Logan
2
@fiXedd: lo contrario ha sido mi experiencia con certificados de clientes porque son realmente apátridas. Las conexiones autenticadas por el certificado del cliente se pueden equilibrar con un equilibrador de carga tonto sin tener en cuenta la adherencia de la conexión porque requieren un estado compartido absolutamente cero entre el cliente y el servidor.
stinkymatt
44
Oh, puedes hacerlo ... solo puedes hacer que el balanceador de carga reenvíe el tráfico TCP, pero no puedes, por ejemplo, hacer que el balanceador de carga sea el punto de terminación para el SSL.
Jeremy Logan
¿Sigue siendo seguro si los certificados del cliente y su autoridad raíz están autofirmados? La autoridad raíz se importará a las autoridades de certificados raíz de confianza del cliente.
Joyce
38

Todos en estas respuestas han pasado por alto el verdadero control / autorización de acceso.

Si, por ejemplo, sus API / servicios web REST se refieren a PUBLICAR / OBTENER registros médicos, es posible que desee definir una política de control de acceso sobre quién puede acceder a los datos y en qué circunstancias. Por ejemplo:

  • los médicos pueden OBTENER la historia clínica de un paciente con el que tienen una relación de atención
  • nadie puede PUBLICAR datos médicos fuera de las horas de práctica (por ejemplo, de 9 a 5)
  • los usuarios finales pueden OBTENER los registros médicos que poseen o los registros médicos de los pacientes de quienes son el tutor
  • las enfermeras pueden ACTUALIZAR el registro médico de un paciente que pertenece a la misma unidad que la enfermera.

Para definir e implementar esas autorizaciones específicas, deberá utilizar un lenguaje de control de acceso basado en atributos llamado XACML, el Lenguaje de marcado de control de acceso extensible.

Las otras normas aquí son para lo siguiente:

  • OAuth: id. federación y delegación de autorización, por ejemplo, dejar que un servicio actúe en mi nombre en otro servicio (Facebook puede publicar en mi Twitter)
  • SAML: federación de identidad / SSO web. SAML tiene mucho que ver con quién es el usuario.
  • Estándares WS-Security / WS- *: se centran en la comunicación entre los servicios SOAP. Son específicos del formato de mensajería a nivel de aplicación (SOAP) y tratan aspectos de la mensajería, por ejemplo, confiabilidad, seguridad, confidencialidad, integridad, atomicidad, eventos ... Ninguno cubre el control de acceso y todos son específicos de SOAP.

XACML es independiente de la tecnología. Se puede aplicar a aplicaciones java, .NET, Python, Ruby ... servicios web, API REST y más.

Los siguientes son recursos interesantes:

David Brossard
fuente
2
No entiendo por qué no puede simplemente implementar un sistema de tokens que obtendrá al usuario y sus permisos, que esencialmente serán lo mismo.
Stan
Puede adoptar un enfoque basado en tokens. Eso también funciona bien, pero aún necesita la lógica que define qué permisos obtienen los usuarios, en otras palabras, qué permisos insertar dentro del token. Eso es lo que XACML puede ayudarlo a lograr. También evita la hinchazón simbólica.
David Brossard
2
Como comentario adicional, ¿qué aporta "9 a 5" a la seguridad? ¿Como si los atacantes solo estuvieran activos por la noche? Por no hablar de las graves implicaciones de uso, como si los médicos solo trabajaran de "9 a 5".
Roland
Ese es un requisito común en escenarios de salud. Echa un vistazo a HL7 por ejemplo. También hay escenarios de romper el vidrio en caso de que un médico necesite acceso fuera del horario de atención. En cuanto a los piratas informáticos, una vez que están en todas las apuestas están apagadas
David Brossard
1
Algunos de mis colegas están investigando eso de hecho. Gracias @SimplyG.
David Brossard
25

He usado OAuth varias veces, y también he usado algunos otros métodos (BASIC / DIGEST). Sugiero de todo corazón a OAuth. El siguiente enlace es el mejor tutorial que he visto sobre el uso de OAuth:

http://hueniverse.com/oauth/guide/

Rob Ottaway
fuente
Aunque esta es una respuesta muy antigua relacionada con OAuth 1.0, vale la pena señalar que el autor del enlace que usted cita tenía esto que decir sobre OAuth 2.0 : "Llegué a la conclusión de que OAuth 2.0 es un mal protocolo ... En comparación con OAuth 1.0, la especificación 2.0 es más compleja, menos interoperable, menos útil, más incompleta y, lo más importante, menos segura ". . Para ser claros, el comentario que estoy citando se hizo varios años después de que publicaste tu respuesta.
skomisa
17

Una de las mejores publicaciones que he encontrado con respecto a la Seguridad en lo que respecta a REST ha terminado en 1 RainDrop . Las API de MySpace usan OAuth también por seguridad y usted tiene acceso completo a sus canales personalizados en el código RestChess, con el que hice mucha exploración. Esto se demostró en Mix y puedes encontrar la publicación aquí .

degnome
fuente
Gracias por el enlace (1 RainDrop): una discusión muy interesante sobre la seguridad en lo que respecta a SOAP v REST
Nathan
15

Gracias por el excelente consejo. Terminamos usando un encabezado HTTP personalizado para pasar un token de identidad del cliente al servicio, en preparación para integrar nuestra API RESTful con el próximo marco de identidad Zermatt de Microsoft. He descrito el problema aquí y nuestra solución aquí . También tomé el consejo de tweakt y compré RESTful Web Services , un libro muy bueno si está creando una API RESTful de cualquier tipo.

Nathan
fuente
1
Este enfoque me suena sospechoso. ¿Qué impide que un atacante use el token de identidad para enmascarar al cliente? HTTPS no protege la URL o los encabezados la última vez que revisé ...
Gili
2
Hmmm ... no estoy seguro de que tengas razón en eso. Creo que, a excepción de los pocos encabezados necesarios para comprender qué tipo de encriptación se requiere, todos los demás encabezados están encriptados.
Nathan
51
Eso está mal. HTTPS protege TODO. Dice: Protocolo de enlace TCP ... Protocolo de enlace TLS ... <ENCRYPTED> GET / foo 200 OK ... desmontaje </ENCRYPTED>.
Mark Renouf
1
Tenga en cuenta que también puede pasar un token como una cookie (en lugar de un encabezado personalizado). Esto se comporta bien en los navegadores, ya que utiliza un encabezado HTTP con comportamientos estándar en la mayoría de los juegos de herramientas y aplicaciones. En el lado del servicio, la cookie no tiene que relacionarse con una sesión, puede usarla para comunicar cualquier token que desee.
Bruce Alderson
11
La máquina Wayback es algo hermoso: descripción del problema y solución
cjc343
14

OWASP (Open Web Application Security Project) tiene algunas hojas de trucos que cubren todos los aspectos del desarrollo de aplicaciones web. Este proyecto es una fuente de información muy valiosa y confiable. Con respecto a los servicios REST, puede verificar esto: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet

WelsonJR
fuente
7

Recomendaría OAuth 2/3. Puede encontrar más información en http://oauth.net/2/

Abhijit Gaikwad
fuente
8
Tenga cuidado de explicar por qué recomendaría la versión 2 cuando sigue siendo en gran medida incompleta. En mi humilde opinión, la versión 1.0a sigue siendo una solución sólida para la mayoría de las aplicaciones.
Butifarra
6

Busqué mucho sobre la seguridad tranquila de ws y también terminamos usando token a través de cookies del cliente al servidor para autenticar las solicitudes. Utilicé Spring Security para la autorización de solicitudes en servicio porque tuve que autenticar y autorizar cada solicitud en función de las políticas de seguridad especificadas que ya estaban en DB.

Parisa Kachoui
fuente
6

El hecho de que el mundo SOAP esté bastante bien cubierto con estándares de seguridad no significa que sea seguro de forma predeterminada. En primer lugar, los estándares son muy complejos. La complejidad no es muy buena amiga de la seguridad y las vulnerabilidades de implementación, como los ataques de envoltura de firmas XML, son endémicas aquí.

En cuanto al entorno .NET, no ayudaré mucho, pero "Construir servicios web con Java" (un ladrillo con ~ 10 autores) me ayudó mucho a comprender la arquitectura de seguridad WS- * y, especialmente, sus peculiaridades.

kravietz
fuente
4

REST en sí no ofrece estándares de seguridad, pero cosas como OAuth y SAML se están convirtiendo rápidamente en los estándares en este espacio. Sin embargo, la autenticación y la autorización son solo una pequeña parte de lo que debe tener en cuenta. Muchas de las vulnerabilidades conocidas relacionadas con las aplicaciones web se aplican mucho a las API REST. Debe tener en cuenta la validación de entrada, el craqueo de sesión, los mensajes de error inapropiados, las vulnerabilidades internas de los empleados, etc. Es un gran tema.

Robert Morschel
fuente
4

Quiero agregar (en línea con stinkeymatt), la solución más simple sería agregar certificados SSL a su sitio. En otras palabras, asegúrese de que su url sea HTTPS: //. Eso cubrirá su seguridad de transporte (por el dinero). Con la URL RESTful, la idea es mantenerlo simple (a diferencia de WS * security / SAML), puede usar oAuth2 / openID connect o incluso Basic Auth (en casos simples). Pero aún necesitará SSL / HTTPS. Verifique la seguridad de ASP.NET Web API 2 aquí: http://www.asp.net/web-api/overview/security (Artículos y videos)

Manish Jain
fuente
3

Como @Nathan terminó con un simple encabezado HTTP, y algunos habían dicho OAuth2 y certificados SSL del lado del cliente. La esencia de esto es ... su API REST no debería tener que manejar la seguridad, ya que realmente debería estar fuera del alcance de la API.

En cambio, se debe colocar una capa de seguridad encima, ya sea un Encabezado HTTP detrás de un proxy web (un enfoque común como SiteMinder, Zermatt o incluso Apache HTTPd), o tan complicado como OAuth 2.

La clave es que las solicitudes deberían funcionar sin ninguna interacción del usuario final. Todo lo que se necesita es garantizar que la conexión a la API REST esté autenticada. En Java EE tenemos la noción de a userPrincipalque se puede obtener en un HttpServletRequest. También se gestiona en el descriptor de despliegue que un patrón de URL puede ser seguro, por lo que el código REST API ya no necesita verificar.

En el mundo WCF, usaría ServiceSecurityContext.Currentpara obtener el contexto de seguridad actual. Necesita configurar su aplicación para requerir autenticación.

Hay una excepción a la declaración que tenía arriba y es el uso de un nonce para evitar repeticiones (que pueden ser ataques o que alguien simplemente envíe los mismos datos dos veces). Esa parte solo se puede manejar en la capa de aplicación.

Arquímedes Trajano
fuente
3

Para la seguridad de aplicaciones web, debe echar un vistazo a OWASP ( https://www.owasp.org/index.php/Main_Page ) que proporciona hojas de referencia para varios ataques de seguridad. Puede incorporar tantas medidas como sea posible para asegurar su aplicación. Con respecto a la seguridad API (autorización, autenticación, gestión de identidad), hay varias formas como ya se mencionó (Basic, Digest y OAuth). Hay agujeros de bucle en OAuth1.0, por lo que puede usar OAuth1.0a (OAuth2.0 no es ampliamente adoptado debido a preocupaciones con la especificación)

java_geek
fuente
2

Ha pasado un tiempo, pero la pregunta sigue siendo relevante, aunque la respuesta podría haber cambiado un poco.

Un API Gateway sería una solución flexible y altamente configurable. Probé y usé KONG bastante y realmente me gustó lo que vi. KONG proporciona una API REST de administrador propia que puede usar para administrar usuarios.

Express-gateway.io es más reciente y también es una API Gateway.

Matt Bannert
fuente