Cómo proteger una API REST solo para aplicaciones móviles de confianza

85

¿Cómo me aseguro de que mi API REST solo responda a las solicitudes generadas por clientes de confianza, en mi caso mis propias aplicaciones móviles? Quiero evitar que las solicitudes no deseadas provengan de otras fuentes. No quiero que los usuarios rellenen una clave de serie o lo que sea, debería suceder entre bambalinas, durante la instalación y sin que sea necesaria la interacción del usuario.

Por lo que sé, HTTPS es solo para validar el servidor con el que se está comunicando, es quien dice que es. Por supuesto, voy a utilizar HTTPS para cifrar los datos.

¿Hay una manera de lograr esto?

Actualización: El usuario puede realizar acciones de solo lectura, que no requieren que el usuario inicie sesión, pero también pueden realizar acciones de escritura, que sí requieren que el usuario inicie sesión (Autenticación mediante token de acceso). En ambos casos, quiero que la API responda a solicitudes provenientes únicamente de aplicaciones móviles de confianza.

La API también se utilizará para registrar una nueva cuenta a través de la aplicación móvil.

Actualización 2: Parece que hay varias respuestas a esto, pero sinceramente no sé cuál marcar como la respuesta. Algunos dicen que se puede hacer, otros dicen que no se puede hacer.

    
pregunta Supercell 20.11.2013 - 18:43

8 respuestas

44

No puedes.

Nunca puede verificar una entidad, cualquier entidad , ya sea una persona, un cliente de hardware o un cliente de software. Solo puede verificar que lo que le dicen a usted es correcto, luego asuma honestidad .

Por ejemplo, ¿cómo sabe Google que es Estoy iniciando sesión en mi cuenta de Gmail? Simplemente me piden un nombre de usuario y una contraseña, verifican eso , luego asumen honestidad porque ¿quién más tendría esa información? En algún momento, Google decidió que esto no era suficiente y agregó una verificación de comportamiento (en busca de un comportamiento extraño), pero aún se basa en la persona para hacer el comportamiento , luego validando el comportamiento .

Esto es exactamente lo mismo con la validación del Cliente. Solo puede validar el comportamiento del cliente, pero no el propio cliente.

Entonces, con SSL, puede verificar que el Cliente tiene un certificado válido o no, por lo que simplemente puede instalar su aplicación, obtener el Certificado y luego ejecutar todo el nuevo código.

Entonces la pregunta es: ¿Por qué es esto tan crítico? Si esta es una preocupación real, cuestionaría su elección de un cliente gordo. Tal vez debería ir con una aplicación web (para no tener que exponer su API).

También vea: Derrotar la validación del certificado SSL para aplicaciones de Android

y: En qué medida son seguros los certificados SSL de los clientes una aplicación móvil?

    
respondido por el Morons 20.11.2013 - 19:53
27

Estoy seguro de que te sientes cómodo al tratar con los inicios de sesión de los usuarios y con las comunicaciones a través de SSL, por lo que me centraré en lo que creo que es la parte más interesante de la pregunta: cómo garantizar que tu lectura solo las acciones, que no requieren que el usuario esté autenticado, ¿solo se aceptan desde sus propias aplicaciones cliente?

Antes que nada, existe el inconveniente que fNek insinuó en una respuesta anterior: las aplicaciones de sus clientes están en manos de usuarios potencialmente hostiles. Pueden ser examinados, sus comunicaciones inspeccionadas, su código desmontado. Nada de lo que voy a sugerir le permitirá garantizar que alguien no aplique ingeniería inversa a su cliente ni abuse de su API REST. Pero debería poner una barrera frente a cualquier intento casual.

De todos modos, un enfoque común es:

  • El cliente contiene un secreto
  • Al realizar una solicitud, concatena los parámetros de la solicitud con los secretos y hace un hash en el resultado.
  • Este hash se envía con la solicitud y el servidor lo verifica

por ejemplo, imagine una solicitud GET para /products/widgets

Digamos que el secreto del cliente es "OH_HAI_I_IZ_SECRET"

Concatene el verbo HTTP, la URL y el secreto:

GET/products/widgetsOH_HAI_I_IZ_SECRET

Y tome un hash de SHA-1 de eso:

4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Luego envíe eso, para que la solicitud sea para:

GET /products/widgets?hash=4156023ce06aff06777bef3ecaf6d7fdb6ca4e02

Finalmente, para evitar que alguien reproduzca al menos solicitudes individuales, también tome una marca de hora y agréguela a los parámetros y al hash. p.ej. en este momento, en tiempo de Unix, es 1384987891. Agregue eso a la concatenación:

GET/products/widgetsOH_HAI_I_IZ_SECRET1384987891

Hash that:

2774561d4e9eb37994d6d71e4f396b85af6cacd1

Y enviar:

GET /products/widgets?time=1384987891&hash=2774561d4e9eb37994d6d71e4f396b85af6cacd1

El servidor verificará el hash y también verificará que la marca de tiempo es actual (por ejemplo, dentro de los 5 minutos para permitir que los relojes no estén perfectamente sincronizados)

¡Advertencia! Ya que estás hablando de aplicaciones móviles, existe un riesgo claro de que el teléfono de alguien tenga el reloj equivocado. O zona horaria incorrecta. O algo. Agregar el tiempo al hash probablemente afectará a algunos usuarios legítimos, así que usa esa idea con precaución.

    
respondido por el Carson63000 20.11.2013 - 23:53
12

Para cualquier persona interesada, en Android puede verificar que la solicitud que recibió se envió desde su aplicación.

En resumen, cuando carga su aplicación en google, la firma, con una clave única que solo usted (y google) conoce.

El proceso de verificación es (ish) así:

  1. su aplicación va a google y solicita el token de autenticación
  2. tu aplicación envía el token de forma segura a tu back-end
    1. su back-end va a google y comprueba el token de autenticación que obtuvo de su aplicación.
    2. su back-end luego verifica si la clave única con la que su aplicación ha firmado coincide, si no, significa que no fue su aplicación ...

el blog completo que lo explica y cómo implementarlo se puede encontrar aquí: enlace

    
respondido por el ndori 12.04.2016 - 11:20
5

Ok, vale la pena mencionar antes de comenzar que para la mayoría de las aplicaciones esto es excesivamente excesivo. Para la mayoría de los casos de uso, simplemente tener un solo certificado válido y / o token es más que suficiente. Si se trata de hacer algo difícil como descompilar su aplicación, entonces la mayoría de los hackers no se molestarán a menos que proporcione datos muy valiosos. Pero hey, ¿dónde está la diversión en esa respuesta?

Entonces, lo que puede hacer es configurar una criptografía asimétrica algo así como la firma digital que se utiliza para firmar programas. Cada aplicación puede tener un certificado individual emitido por una única CA y verificado cuando su usuario se conecta. (ya sea cuando se registra por primera vez o cuando se instala por primera vez) Cuando se autentica ese certificado, puede asegurar aún más su aplicación al registrar ese certificado como válido para un identificador de dispositivo dado (como ID de Android )

    
respondido por el Tom Squires 21.11.2013 - 00:36
4

Como @Morons mencionó en su respuesta, es muy difícil verificar la entidad en el otro extremo de la conexión.

La forma más sencilla de proporcionar cierto nivel de autenticidad es hacer que el servidor verifique un secreto que solo la entidad real sabría. Para un usuario, ese podría ser un nombre de usuario y una contraseña. Para una pieza de software donde no hay ningún usuario, puede incrustar un secreto.

El problema con estos enfoques es que debe confiar un poco en el cliente. Si alguien hace una ingeniería inversa de su aplicación o le roba su contraseña, puede pretender ser usted.

Puede tomar medidas para hacer que sea más difícil extraer la información secreta ocultándola en el ejecutable. Herramientas como ProGuard, que es un ofuscador para Java, pueden ayudar con esto. No sé mucho sobre ofuscación en otros idiomas, pero es probable que existan herramientas similares. El uso de una conexión TLS ayuda a evitar que las personas se detengan en su tráfico, pero no previene un ataque MITM. Fijación puede ayudar a resolver ese problema.

Trabajo para una compañía llamada CriticalBlue (¡Revelación completa!) que tiene un producto llamado Approov que trata de resolver este problema de confianza . Funciona para Android / iOS actualmente y proporciona un mecanismo para que nuestros servidores verifiquen la integridad de la aplicación cliente. Lo hace haciendo que el cliente calcule una respuesta a un desafío aleatorio. El cliente tiene que calcular la respuesta utilizando los atributos del paquete de aplicaciones instaladas que son difíciles de falsificar e incluye algunos mecanismos sofisticados contra la manipulación indebida.

Devuelve un token que luego puede enviar como prueba de autenticidad a su API.

La diferencia importante con este enfoque es que aunque sería posible deshabilitar la verificación de autenticidad en el cliente, si lo hiciera, no obtendría el token de autenticación que necesita para verificar su aplicación con el servidor. La biblioteca también está estrechamente unida a las características del ejecutable en el que se encuentra, por lo que sería muy difícil integrarla en una aplicación falsa y hacer que funcione.

Hay un análisis de costo / beneficio que cualquier desarrollador de API debe hacer para decidir qué tan probable es que alguien intente piratear su API y lo costoso que puede ser. Una simple comprobación secreta en la aplicación previene ataques triviales, pero protegerse contra un atacante más decidido es probablemente mucho más complicado y potencialmente costoso.

    
respondido por el ThePragmatist 25.07.2016 - 18:10
0

SSL asegurará el canal de comunicación.

El inicio de sesión correcto emitirá un token de autenticación a través de una conexión encriptada.

El token de autenticación se pasará a su API REST en todas las solicitudes posteriores.

    
respondido por el CodeART 20.11.2013 - 19:09
0

No sería demasiado seguro, pero podría agregar algún tipo de código secreto o incluso una firma digital. Desventaja: debe incluirse en la aplicación, lo que facilita su obtención si sabe lo que hace.

    
respondido por el fNek 20.11.2013 - 19:59
0
  

Por lo que sé, HTTPS es solo para validar el servidor con el que se está comunicando, es quien dice que es.

De hecho, puede usar SSL para autenticar tanto al cliente como al servidor. O, dicho de otra manera, "sí, puede usar certificados de cliente".

Tendrás que ...

  • mire la biblioteca SSL que está usando para determinar cómo especificar los certificados de cliente en el dispositivo móvil,
  • escriba el código o configure su servidor HTTPS para que solo acepte conexiones de clientes registrados y de confianza.
  • cree un mecanismo para agregar certificados de cliente de confianza en su servidor
  • cree un mecanismo para eliminar de su servidor los certificados de cliente que ya no son de confianza

Puede hacer que la aplicación móvil almacene el certificado donde lo desee. Ya que desea que la autenticación sea específica de la aplicación, debe considerar almacenar el certificado en una ubicación de disco protegida (en Android, podría crear una tabla de "configuración" en su base de datos SQLite, y una fila para su certificado y otra para su clave privada) .

    
respondido por el atk 20.11.2013 - 21:15

Lea otras preguntas en las etiquetas