Secretos de OAuth en aplicaciones móviles

137

Al usar el protocolo OAuth, necesita una cadena secreta obtenida del servicio al que desea delegar. Si está haciendo esto en una aplicación web, simplemente puede almacenar el secreto en su base de datos o en el sistema de archivos, pero ¿cuál es la mejor manera de manejarlo en una aplicación móvil (o una aplicación de escritorio para el caso)?

Almacenar la cadena en la aplicación obviamente no es bueno, ya que alguien podría encontrarlo fácilmente y abusar de él.

Otro enfoque sería almacenarlo en su servidor y hacer que la aplicación lo recupere en cada ejecución, sin almacenarlo nunca en el teléfono. Esto es casi tan malo, porque tienes que incluir la URL en la aplicación.

La única solución viable que se me ocurre es obtener primero el token de acceso de forma normal (preferiblemente usando una vista web dentro de la aplicación), y luego enrutar todas las comunicaciones adicionales a través de nuestro servidor, lo que agregaría el secreto a los datos solicitados y se comunicaría con el proveedor Por otra parte, soy un novato en seguridad, así que realmente me gustaría escuchar las opiniones de algunas personas conocedoras sobre esto. No me parece que la mayoría de las aplicaciones lleguen a estas longitudes para garantizar la seguridad (por ejemplo, Facebook Connect parece asumir que usted pone el secreto en una cadena directamente en su aplicación).

Otra cosa: no creo que el secreto esté involucrado en solicitar inicialmente el token de acceso, por lo que podría hacerse sin involucrar a nuestro propio servidor. ¿Estoy en lo correcto?

Felixyz
fuente
Lo siento si no entiendo lo obvio, pero ¿cuál es el problema con el almacenamiento de los códigos en la base de datos de la aplicación? Debido a que esos tokens se generan y almacenan después de que el usuario autenticó su cuenta, debería ser seguro asumir que dicho usuario desea que el dispositivo móvil almacene el acceso para tener acceso.
Poke
Incluso después de que el usuario lo haya autorizado a acceder a su cuenta (por ejemplo, en Twitter), debe usar un secreto que obtuvo del servicio al que intenta acceder. Este secreto se utiliza en todas las comunicaciones con su servidor, junto con la clave de autenticación y algunas otras claves. Entonces, sí, puede almacenar la clave de acceso, pero el secreto no debe almacenarse, ya que podría usarse con cualquier clave de autenticación para abusar del servicio. Una vez más, estaría feliz de ser corregido por personas que saben más sobre esto.
Felixyz
1
OAuth ofrece un método de autenticación que asegura los datos de inicio de sesión del usuario original. Para hacerlo posible, se genera una nueva combinación de inicio de sesión única que solo funciona junto con la combinación de teclas de la aplicación única . El gran beneficio sobre el almacenamiento de los datos de inicio de sesión del usuario es que son completamente seguros después de la primera autorización y, en cualquier caso de violación, el usuario simplemente puede revocar el acceso de la autorización. Y, por supuesto, no guardar el secreto no tendría sentido, ya que el usuario necesitaría volver a autenticarse en ese momento (y eso no es lo que el usuario quiere al dar acceso a la aplicación).
empuje
@poke La clave de autenticación que se obtiene cuando el usuario aprueba su aplicación con el proveedor debe guardarse, pero el token secreto que recibió del proveedor antes de lanzar la aplicación no debería (en el caso de una aplicación de escritorio o móvil; si es una aplicación web, obviamente, puede almacenar la clave en el servidor, como se indica en la pregunta).
Felixyz
44
Según mi comprensión de oAuth: en el caso de una aplicación de escritorio, es muy fácil rastrear / monitorear el tráfico HTTP / HTTPS con herramientas como esta ieinspector.com/httpanalyzer/index.html Por lo tanto, su token y token secreto se pueden encontrar muy fácilmente. Entonces, la única protección es su secreto de consumidor. Ahora, si su tienda es el secreto dentro de la aplicación y alguien puede encontrarlo, se convierte en un juego de niños hacerse pasar por cualquier otra aplicación como su aplicación. Corrígeme si estoy equivocado.
Varun

Respuestas:

38

Sí, este es un problema con el diseño de OAuth al que nos enfrentamos. Optamos por proxy todas las llamadas a través de nuestro propio servidor. OAuth no estaba completamente descartado con respecto a las aplicaciones de escritorio. No hay una solución perfecta para el problema que he encontrado sin cambiar OAuth.

Si lo piensa y hace la pregunta de por qué tenemos secretos, es principalmente para el suministro y la desactivación de aplicaciones. Si nuestro secreto se ve comprometido, entonces el proveedor solo puede revocar toda la aplicación. Como tenemos que incrustar nuestro secreto en la aplicación de escritorio, estamos un poco jodidos.

La solución es tener un secreto diferente para cada aplicación de escritorio. OAuth no facilita este concepto. Una forma es que el usuario vaya y cree un secreto por su cuenta e ingrese la clave por su cuenta en su aplicación de escritorio (algunas aplicaciones de Facebook hicieron algo similar durante mucho tiempo, haciendo que el usuario fuera y creara Facebook para configurar sus presupuestos personalizados y mierda). No es una gran experiencia para el usuario.

Estoy trabajando en la propuesta de un sistema de delegación para OAuth. El concepto es que, utilizando nuestra propia clave secreta que obtenemos de nuestro proveedor, podríamos emitir nuestro propio secreto delegado a nuestros propios clientes de escritorio (uno para cada aplicación de escritorio básicamente) y luego, durante el proceso de autenticación, enviamos esa clave al nivel superior proveedor que nos llama y vuelve a validar con nosotros. De esa manera, podemos revocar los secretos que emitimos para cada cliente de escritorio. (Tomando prestado mucho de cómo funciona esto desde SSL). Todo este sistema sería perfecto para los servicios web de valor agregado y para transmitir llamadas a un servicio web de terceros.

El proceso también podría realizarse sin devoluciones de llamadas de verificación de delegación si el proveedor de nivel superior proporciona una API para generar y revocar nuevos secretos delegados. Facebook está haciendo algo similar al permitir que las aplicaciones de Facebook permitan a los usuarios crear sub-aplicaciones.

Hay algunas conversaciones sobre el tema en línea:

http://blog.atebits.com/2009/02/fixing-oauth/ http://groups.google.com/group/twitter-development-talk/browse_thread/thread/629b03475a3d78a1/de1071bf4b820c14#de1071bf4b820c14

La solución de Twitter y Yammer es una solución de pin de autenticación: https://dev.twitter.com/oauth/pin-based https://www.yammer.com/api_oauth_security_addendum.html

Zac Bowling
fuente
Esto es muy interesante, aunque confirma lo que temía, que OAuth no es tan bueno para aplicaciones de escritorio / móviles. Por supuesto, un atacante primero tendría que obtener el secreto y luego también oler las credenciales de alguien, por lo que tomaría bastante determinación. La solución pin está bien para computadoras de escritorio, pero para imo de mano dura para dispositivos móviles.
Felixyz
¿Cómo ayudaría su esquema propuesto a los servicios web de valor agregado, ya que este problema no se aplica a ellos? Además, no veo cómo funcionaría con el proveedor que genera nuevos secretos, ya que necesitaría un "secreto maestro" para incluso solicitar esos nuevos secretos, por lo que al menos necesitaría una llamada a su propio servidor (que contiene el secreto principal). Pero eso es, por supuesto, mejor que enrutar todo el tráfico a través de su propio servidor. Aclaración muy bienvenida! ¡Y actualice aquí a medida que avance su propuesta!
Felixyz
55
Solo curiosidad: ¿cómo determina que lo que hace una llamada a su servidor proxy es legítimo?
davidtbernal
1
En respuesta a notJim: el riesgo principal de permitir que se divulgue su secreto de consumidor es que se pueden desarrollar aplicaciones maliciosas (o tontas) al usarlo, empañando su reputación y aumentando el riesgo de que su aplicación legítima se cierre por abuso / mal uso de API. Al enviar todas las llamadas que requieren tu secreto a través de una aplicación web que controlas, estás de nuevo en una posición en la que puedes observar patrones de abuso y revocar el acceso al usuario o el nivel de token de acceso antes de que la API que estás consumiendo decida cerrar abajo todo su servicio.
cuasistoico
Estoy de acuerdo con cuasistoic aquí, necesitará usar un navegador con SSL habilitado para atender la llamada oauth. Esto es bueno por varias razones, incluida la administración fácil de actualizaciones de seguridad en el futuro, y nada en la aplicación real necesitará actualizarse con el tiempo. Zac señala que Twitter propone una solución de PIN, que también pensé, porque no puedes confiar en la aplicación para obtener el código de forma segura. Sugiero usar un 'Nonce' con un cifrado moderno junto con el PIN y el secreto para representar las solicitudes a través del servidor web.
Mark
18

Con OAUth 2.0, puede almacenar el secreto en el servidor. Use el servidor para adquirir un token de acceso que luego moverá a la aplicación y podrá hacer llamadas desde la aplicación al recurso directamente.

Con OAuth 1.0 (Twitter), se requiere el secreto para realizar llamadas API. Proxying llamadas a través del servidor es la única manera de garantizar que el secreto no se vea comprometido.

Ambos requieren algún mecanismo que el componente de su servidor sepa que es su cliente quien lo llama. Esto tiende a hacerse durante la instalación y el uso de un mecanismo específico de la plataforma para obtener una identificación de aplicación de algún tipo en la llamada a su servidor.

(Soy el editor de la especificación OAuth 2.0)

Dick Hardt
fuente
2
¿Puedes dar más detalles sobre el "mecanismo específico de la plataforma para obtener una identificación de aplicación de algún tipo"? ¿Cómo es el componente del servidor para verificar la identidad del cliente? Creo que esto se puede hacer con el aprovisionamiento de clientes. Por ejemplo, implemente un certificado SSL nuevo y único para cada cliente. ¿Es eso lo que quieres decir? Si es más complejo que esto, ¿tal vez pueda referirse a un artículo más detallado?
Cheeso
2
Recuerdo que algunas personas de seguridad hablaron sobre cómo se podría hacer esto. Hay una llamada al sistema operativo que devuelve un token firmado que luego puede enviar a su servidor y verificar. Lo siento, no tengo los detalles. Es un error que podría usar algunos buenos ejemplos.
Dick Hardt
2
@DickHardt, pero en este escenario, ¿cómo se asegura de que la aplicación móvil sea realmente su aplicación y no fraudulenta?
Rafael Membrives
11

Una solución podría ser codificar el secreto de OAuth en el código, pero no como una cadena simple. Ofuscarlo de alguna manera - dividirlo en segmentos, cambiar los caracteres por un desplazamiento, rotarlo - hacer alguna o todas estas cosas. Un cracker puede analizar su código de bytes y encontrar cadenas, pero el código de ofuscación puede ser difícil de entender.

No es una solución infalible, sino barata.

Dependiendo del valor del exploit, algunos crackers geniales pueden hacer todo lo posible para encontrar su código secreto. Debe sopesar los factores: el costo de la solución del servidor mencionada anteriormente, el incentivo para que los crackers gasten más esfuerzos en encontrar su código secreto y la complejidad de la ofuscación que puede implementar.

Jayesh
fuente
1
Sí, creo que esto es razonable. Se necesitaría mucha determinación para que alguien extraiga primero el secreto del consumidor y luego arrebata las credenciales de la gente para hacer algo malo. Para las aplicaciones de alto perfil, no estoy seguro de que esto sea suficiente, pero para una aplicación promedio, creo que tienes razón, debes equilibrar el tiempo de implementación con una amenaza de seguridad bastante menor.
Felixyz
77
Todo lo que se necesita es que un usuario haga el esfuerzo y luego publique o comparta su secreto. Una vez que se revela su secreto, el riesgo de que su servicio se cierre completamente por abuso se dispara, y está completamente fuera de su control.
cuasistoico
8
La ofuscación no es seguridad en absoluto. Esto es peor que ninguna seguridad, porque le da al desarrollador una falsa sensación de seguridad. en.wikipedia.org/wiki/Security_through_obscurity
Paul Legato
8
"La ofuscación no es seguridad en absoluto. Esto es peor que ninguna seguridad, porque le da al desarrollador una falsa sensación de seguridad". Disparates. Nadie dice que la ofuscación contribuye a la buena seguridad. Pero si voy a distribuir un secreto de OAuth con mi apk, seguramente es mejor ofuscar que no. La ofuscación es lo que Google también recomienda al almacenar claves / secretos en la aplicación. Como mínimo, estas medidas mantienen a raya a los piratas informáticos casuales, lo que es mejor que nada. Las declaraciones generales como la suya equivalen a seguridad imperfecta sin seguridad. Eso simplemente no es cierto. Imperfecto es simplemente imperfecto.
hungryghost
1
La ofuscación NO ayuda, porque no importa cuánto cambio o codificación hagas, aún construyes la clave juntos y la usas para construir tu solicitud de API. Es bastante simple conectar dinámicamente las API en los lugares correctos para descargar la solicitud que está enviando incluso antes del cifrado HTTPS. Por lo tanto, no incruste claves secretas en su aplicación a menos que realmente no haya otra alternativa posible.
C0deH4cker
6

No almacene el secreto dentro de la aplicación.

Debe tener un servidor al que pueda acceder la aplicación a través de https (obviamente) y almacenar el secreto en él.

Cuando alguien desea iniciar sesión a través de su aplicación móvil / de escritorio, su aplicación simplemente reenviará la solicitud al servidor que luego agregará el secreto y lo enviará al proveedor de servicios. Su servidor puede decirle a su aplicación si tuvo éxito o no.

Luego, si necesita obtener información confidencial del servicio (Facebook, Google, Twitter, etc.), la aplicación pregunta a su servidor y su servidor se la dará a la aplicación solo si está correctamente conectada.

Realmente no hay ninguna opción, excepto almacenarla en un servidor. Nada del lado del cliente es seguro.

Nota

Dicho esto, esto solo lo protegerá contra un cliente malintencionado, pero no contra un cliente malintencionado y no contra otros clientes maliciosos (phishing) ...

OAuth es un protocolo mucho mejor en el navegador que en el escritorio / móvil.

Gudradain
fuente
1
¿No hace esto más fácil la vida del hacker? porque ahora, para acceder a los recursos del servidor, técnicamente solo necesitamos la identificación del cliente, ya que el servidor de todos modos agregará el secreto a la solicitud. ¿Me estoy perdiendo de algo?
Hudi Ilfeld
@HudiIlfeld Sí, te falta algo: el cliente debe iniciar sesión en el servidor. Mientras no inicie sesión, el servidor no devolverá nada. Una forma de administrar esto es después de enviar la credencial por primera vez, el servidor devuelve un token de acceso al cliente y luego el cliente envía este token de acceso con cada solicitud futura. Hay muchas opciones aquí.
Gudradain
4

Hay una nueva extensión para el Tipo de concesión de código de autorización llamada Clave de prueba para el intercambio de código (PKCE) . Con él, no necesitas un secreto de cliente.

PKCE (RFC 7636) es una técnica para proteger clientes públicos que no usan un secreto de cliente.

Se utiliza principalmente en aplicaciones nativas y móviles, pero la técnica también se puede aplicar a cualquier cliente público. Requiere soporte adicional por parte del servidor de autorización, por lo que solo es compatible con ciertos proveedores.

de https://oauth.net/2/pkce/

Para obtener más información, puede leer el RFC 7636 completo o esta breve introducción .

Johannes Filter
fuente
2

Aquí hay algo para pensar. Google ofrece dos métodos de OAuth ... para aplicaciones web, donde registra el dominio y genera una clave única, y para aplicaciones instaladas donde utiliza la clave "anónimo".

Tal vez he pasado por alto algo en la lectura, pero parece que compartir la clave única de su aplicación web con una aplicación instalada es probablemente más seguro que usar "anónimo" en el método oficial de aplicaciones instaladas.

LetMyPeopleCode
fuente
2

Con OAuth 2.0 simplemente puede usar el flujo del lado del cliente para obtener un token de acceso y luego usar este token de acceso para autenticar todas las solicitudes adicionales. Entonces no necesitas un secreto en absoluto.

Puede encontrar una buena descripción de cómo implementar esto aquí: https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified#mobile-apps

Joel Richard
fuente
Siempre que el servicio sea compatible con "el flujo del lado del cliente". Muchos no lo hacen, en cambio requieren la identificación del cliente y el secreto del cliente para obtener este token de acceso.
Damian Yerrick
0

No tengo mucha experiencia con OAuth, pero ¿no todas las solicitudes requieren no solo el token de acceso del usuario, sino también una clave y secreto de consumidor de la aplicación? Entonces, incluso si alguien roba un dispositivo móvil e intenta extraer datos de él, necesitaría una clave de aplicación y un secreto para poder hacer cualquier cosa.

Siempre pensé que la intención detrás de OAuth era que cada Tom, Dick y Harry que tuvieran un mashup no tuvieran que almacenar sus credenciales de Twitter en claro. Creo que resuelve ese problema bastante bien a pesar de sus limitaciones. Además, en realidad no fue diseñado con el iPhone en mente.

bpapa
fuente
Tienes razón, OAuth fue diseñado principalmente con aplicaciones web en mente y estoy seguro de que funciona bien para eso. Sí, necesita el token y el secreto del consumidor para firmar cada solicitud, y el problema es dónde almacenar el secreto. Si alguien roba la clave de acceso, no es un gran problema porque se puede revocar, pero si alguien obtiene la clave de consumidor, cada copia de su aplicación se verá comprometida.
Felixyz
OAuth 1 requirió firmar cada solicitud. OAuth 2 solo requiere el token de acceso. Ambos requieren la clave y el secreto al adquirir un token.
Dick Hardt
0

Estoy de acuerdo con Felixyz. OAuth, aunque es mejor que la autenticación básica, todavía tiene un largo camino por recorrer para ser una buena solución para aplicaciones móviles. He estado jugando con el uso de OAuth para autenticar una aplicación de teléfono móvil en una aplicación de Google App Engine. El hecho de que no pueda administrar de manera confiable el secreto del consumidor en el dispositivo móvil significa que lo predeterminado es usar el acceso 'anónimo'.

El paso de autorización del navegador de la implementación de Google App Engine OAuth lo lleva a una página donde contiene texto como: "El sitio <some-site> solicita acceso a su cuenta de Google para los productos enumerados a continuación"

YourApp (yourapp.appspot.com): no está afiliado a Google

etc.

Toma <some-site> del dominio / nombre de host utilizado en la URL de devolución de llamada que proporcione, que puede ser cualquier cosa en Android si utiliza un esquema personalizado para interceptar la devolución de llamada. Entonces, si usa el acceso 'anónimo' o su secreto de consumidor está comprometido, entonces cualquiera podría escribir un consumidor que engañe al usuario para que le dé acceso a su aplicación gae.

La página de autorización de Google OAuth también contiene muchas advertencias que tienen 3 niveles de gravedad dependiendo de si está usando 'anónimo', secreto del consumidor o claves públicas.

Cosas bastante aterradoras para el usuario promedio que no es técnicamente inteligente. No espero tener un alto porcentaje de finalización de registro con ese tipo de cosas en el camino.

Esta publicación de blog aclara cómo los secretos del consumidor realmente no funcionan con las aplicaciones instaladas. http://hueniverse.com/2009/02/should-twitter-discontinue-their-basic-auth-api/

Martin Bayly
fuente
0

También estoy tratando de encontrar una solución para la autenticación móvil OAuth y almacenar secretos dentro del paquete de aplicaciones en general.

Y una idea loca simplemente me golpeó: la idea más simple es almacenar el secreto dentro del binario, pero ofuscado de alguna manera, o, en otras palabras, almacenar un secreto cifrado. Entonces, eso significa que tienes que almacenar una clave para descifrar tu secreto, lo que parece habernos cerrado el círculo. Sin embargo, ¿por qué no usar una clave que ya está en el sistema operativo?

Entonces, para aclarar mi idea es que eliges una cadena definida por el sistema operativo, no importa cuál. Luego, encripte su secreto usando esta cadena como clave y guárdela en su aplicación. Luego, durante el tiempo de ejecución, descifre la variable usando la clave, que es solo una constante del sistema operativo. Cualquier hacker que eche un vistazo a su binario verá una cadena encriptada, pero ninguna clave.

¿Eso funcionará?

Daniel Thorpe
fuente
3
Buen pensamiento, pero no. El cracker solo vería el binario apuntando a la dirección de la constante del sistema operativo.
GrayB
0

Ninguna de estas soluciones impide que un hacker determinado detecte paquetes enviados desde su dispositivo móvil (o emulador) para ver el secreto del cliente en los encabezados http.

Una solución podría ser tener un secreto dinámico que esté formado por una marca de tiempo cifrada con una clave y algoritmo de cifrado de 2 vías privado. El servicio descifra el secreto y determina si la marca de tiempo es +/- 5 minutos.

De esta forma, incluso si el secreto se ve comprometido, el hacker solo podrá usarlo durante un máximo de 5 minutos.

Maximvs
fuente
-2

Como otros han mencionado, no debería haber ningún problema real con el almacenamiento local del secreto en el dispositivo.

Además de eso, siempre puede confiar en el modelo de seguridad basado en UNIX de Android: solo su aplicación puede acceder a lo que escribe en el sistema de archivos. Simplemente escriba la información en el objeto SharedPreferences predeterminado de su aplicación.

Para obtener el secreto, uno tendría que obtener acceso de root al teléfono Android.

Christopher Orr
fuente
3
Como quien menciono? Si te refieres al comentario de poke, mira mi respuesta that secret! = Clave de autenticación. Este último se puede almacenar de forma segura, el primero no. No sé acerca de Android, pero obtener acceso de root a un iPhone no es nada difícil. Tenga en cuenta que el secreto es el mismo en todas las instancias de la aplicación, por lo que un atacante solo tendría que obtener acceso a un binario. E incluso si no pudieran obtener acceso de root en el dispositivo, podrían tener en sus manos el binario en otro y extraer el token secreto de él.
Felixyz
1
solo para agregarlo, también es muy fácil
rootear