¿Cómo debe una aplicación almacenar sus credenciales?

26

Contexto

Al desarrollar aplicaciones de escritorio, ocasionalmente tendrá que almacenar credenciales en algún lugar para poder autenticar su aplicación. Un ejemplo de esto es un ID de la aplicación de Facebook + secreto , otra es credenciales de MySQL.

El almacenamiento de este texto plano en el código fuente de las aplicaciones no proporciona ninguna seguridad verdadera, ya que no es demasiado complicado para aplicar ingeniería inversa a un programa . Recopilar las credenciales de un servidor tampoco funcionará, ya que los piratas informáticos pueden realizar las solicitudes ellos mismos fácilmente. El cifrado de las credenciales almacenadas tampoco supondrá ninguna diferencia, ya que la aplicación necesitará acceso a la clave de descifrado para poder utilizar las credenciales.

Pregunta

¿Cómo se puede almacenar las credenciales específicas de una aplicación de forma segura? Preferiblemente cross-OS.

Nota: El lenguaje relevante es Java, sin embargo, creo (creo) que esta es una pregunta no específica del lenguaje.

    
pregunta Zar 17.09.2012 - 19:50
fuente

2 respuestas

22

Nunca contraseñas de código rígido o claves criptográficas en su programa.

La regla general es: las únicas credenciales que debe almacenar en la máquina de un usuario son las credenciales asociadas con ese usuario , por ejemplo, las credenciales que permiten al usuario iniciar sesión en su cuenta.

No debe almacenar sus credenciales de desarrollador en la máquina del usuario . Eso no es seguro.

Debe asumir que cualquier cosa almacenada en la máquina del usuario es conocida por el usuario, o puede ser aprendida fácilmente por el usuario. (Esta es la suposición correcta: no es difícil hacer ingeniería inversa de un binario de aplicación para aprender cualquier clave o secreto que pueda estar incrustado en él).

Una vez que entiendas este principio general, todo se vuelve fácil. Básicamente, necesita diseñar el resto de su sistema y su protocolo de autenticación para que el software del cliente pueda autenticarse usando solo aquellas credenciales que sean seguras de almacenar en el cliente.

Ejemplo 1. Supongamos que tiene una ID y clave de la aplicación de Facebook, asociadas con su aplicación (es decir, asociadas con su cuenta de desarrollador). ¿Incorpora el ID de la aplicación y la clave en el software de escritorio que envía a los usuarios? ¡No! Absolutamente no. Definitivamente no lo hace, porque eso permitiría a cualquiera de sus usuarios conocer su ID y clave de aplicación y enviar sus propias solicitudes, posiblemente dañando su reputación.

En cambio, encuentras otra manera. Por ejemplo, tal vez configure su propio servidor que tenga el ID y la clave de la aplicación y sea responsable de realizar las solicitudes a la plataforma de Facebook (sujeto a las limitaciones apropiadas y la limitación de velocidad). Entonces, su cliente se conecta a su servidor. Tal vez usted autentique a cada cliente haciendo que cada usuario configure su propia cuenta de usuario en su servidor, que almacene las credenciales de la cuenta en el cliente y que el cliente se autentique usando estas credenciales.

Puede hacer esto totalmente invisible para el usuario, haciendo que la aplicación cliente genere una nueva cuenta de usuario en la primera ejecución (generando sus propias credenciales de inicio de sesión, almacenándolas localmente y enviándolas al servidor). La aplicación cliente puede usar estas credenciales almacenadas para conectarse en el futuro (por ejemplo, sobre SSL) e iniciar sesión automáticamente cada vez que se ejecute la aplicación.

Observe que lo único que se almacena en la máquina de un usuario son las credenciales que permiten iniciar sesión en la cuenta de ese usuario, pero nada que permita iniciar sesión en las cuentas de otras personas, y nada que exponga las claves de la aplicación del desarrollador.

Ejemplo 2. Suponga que escribe una aplicación que necesita acceder a los datos del usuario en su cuenta de Google. ¿Les pide su nombre de usuario y contraseña de Google y los almacena en el almacenamiento local de la aplicación? Podría: eso estaría bien, porque las credenciales del usuario se almacenan en la máquina del usuario. El usuario no tiene incentivos para intentar piratear su propia máquina, porque ya conocen sus propias credenciales.

Aún mejor: use OAuth para autorizar su aplicación. De esta manera, su aplicación almacena un token OAuth en su almacenamiento local de aplicaciones, lo que le permite a su aplicación acceder a la cuenta de Google del usuario. También evita la necesidad de almacenar la contraseña de Google del usuario (que es particularmente sensible) en el almacenamiento local de la aplicación, por lo que reduce el riesgo de compromiso.

Ejemplo 3. Suponga que está escribiendo una aplicación que tiene una base de datos MySQL que se comparte entre todos los usuarios. ¿Toma la base de datos MySQL y la integra en el binario de la aplicación? ¡No! Cualquiera de sus usuarios podría extraer la contraseña y luego obtener acceso directo a su base de datos MySQL.

En su lugar, configura un servicio que proporciona la funcionalidad necesaria. La aplicación cliente se conecta al servicio, se autentica y envía la solicitud al servicio. El servicio puede ejecutar esta solicitud en la base de datos MySQL. La contraseña de MySQL permanece almacenada de forma segura en la máquina del servidor y nunca es accesible en la máquina de ningún usuario. El servidor puede imponer cualquier restricción o control de acceso que desee.

Esto requiere que su aplicación cliente pueda autenticarse en el servicio. Una forma de hacerlo es hacer que la aplicación cliente cree una nueva cuenta en el servicio en la primera ejecución, genere una credencial de autenticación aleatoria e inicie sesión automáticamente en el servicio cada vez que lo haga. Podría usar SSL con una contraseña aleatoria, o incluso mejor, usar algo como SSL con un certificado de cliente único para cada cliente.

La otra regla es: no se ingresan las credenciales de código en el programa. Si está almacenando credenciales en la máquina del usuario, guárdelas en alguna ubicación privada: tal vez un archivo de configuración o en un directorio, preferiblemente uno que solo sea legible por esta aplicación particular o este usuario particular (no un archivo legible en todo el mundo) / p>     

respondido por el D.W. 18.09.2012 - 07:10
fuente
4

Es un problema de seguridad clásico sin una solución perfecta, solo imperfecta, y se reduce al problema más general de proteger el software contra la manipulación y la ingeniería inversa.

  1. Use un método de autenticación externo que el usuario debe proporcionar activamente para alcanzar las credenciales: una contraseña ingresada manualmente (cuyo resumen de hash, por ejemplo, se utiliza para descifrar las credenciales), una llave de autenticación segura que contiene un certificado y clave privada coincidente que debe ingresarse en un puerto USB, un lector de huellas dactilares que proporcione la huella dactilar correcta, etc. Idealmente, el resultado de esto no será una simple respuesta de sí / no a su programa, ya que puede anularse / parcharse / falsificarse, pero un valor real (una clave criptográfica) requerido para descifrar sus credenciales (o cualquier otra cosa que esté tratando de proteger), se deriva directamente del autenticador. Un enfoque de múltiples fuentes en el que la clave de descifrado se calcula sobre la marcha a partir de varias fuentes (en cuanto a qué fuentes, esto realmente depende de su sistema) podría ser aún mejor.

  2. Obliga (automáticamente y masivamente) a tu programa para impedir la ingeniería inversa. Es cierto que las herramientas de análisis estático se han convertido en lo último en tecnología, pero existen herramientas de ofuscación [propietarias y caras] (ofuscando compiladores, empacadores, etc.) que hacen que la ingeniería inversa requiera mucho tiempo, sea desafiante y laboriosa. suficiente para enviar a los atacantes a buscar objetivos más fáciles. La adición de mecanismos de protección contra la depuración y los métodos de resistencia a la manipulación puede fortalecer aún más la seguridad de su programa. Es cierto que Java como lenguaje de bytecode es especialmente vulnerable a este respecto, ya que descompilarlo (en comparación con descompilar / desensamblar el código nativo) es bastante sencillo.

respondido por el Harel 17.09.2012 - 20:28
fuente

Lea otras preguntas en las etiquetas