sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo puedo proteger el nombre de usuario y la contraseña de MySQL de la descompilación?

Nunca codifique contraseñas en su código. Esto se mencionó recientemente en Los 25 errores de programación más peligrosos :

Codificar una cuenta secreta y una contraseña en su software es extremadamente conveniente, para ingenieros inversos expertos. Si la contraseña es la misma en todo su software, entonces todos los clientes se vuelven vulnerables cuando esa contraseña inevitablemente se conoce. Y debido a que está codificado, es un gran dolor de arreglar.

Debe almacenar la información de configuración, incluidas las contraseñas, en un archivo separado que la aplicación lee cuando se inicia. Esa es la única forma real de evitar que la contraseña se filtre como resultado de la descompilación (para empezar, nunca la compile en el binario).

Para obtener más información sobre este error común, puede leer el artículo CWE-259 . El artículo contiene una definición más detallada, ejemplos y mucha más información sobre el problema.

En Java, una de las formas más fáciles de hacer esto es usar la clase Preferencias. Está diseñado para almacenar todo tipo de configuraciones del programa, algunas de las cuales pueden incluir un nombre de usuario y una contraseña.

import java.util.prefs.Preferences;

public class DemoApplication {
  Preferences preferences = 
      Preferences.userNodeForPackage(DemoApplication.class);

  public void setCredentials(String username, String password) {
    preferences.put("db_username", username);
    preferences.put("db_password", password);
  }

  public String getUsername() {
    return preferences.get("db_username", null);
  }

  public String getPassword() {
    return preferences.get("db_password", null);
  }

  // your code here
}

En el código anterior, podría llamar a setCredentials después de mostrar un cuadro de diálogo que solicita el nombre de usuario y la contraseña. Cuando necesite conectarse a la base de datos, puede usar el getUsername y getPassword métodos para recuperar los valores almacenados. Las credenciales de inicio de sesión no estarán codificadas en sus archivos binarios, por lo que la descompilación no supondrá un riesgo para la seguridad.

Nota importante: Los archivos de preferencias son simplemente archivos XML de texto sin formato. Asegúrese de tomar las medidas adecuadas para evitar que usuarios no autorizados vean los archivos sin procesar (permisos de UNIX, permisos de Windows, etc.). En Linux, al menos, esto no es un problema, porque llamar a Preferences.userNodeForPackage creará el archivo XML en el directorio de inicio del usuario actual, que de todos modos no es legible para otros usuarios. En Windows, la situación podría ser diferente.

Más notas importantes: Ha habido mucha discusión en los comentarios de esta respuesta y otras sobre cuál es la arquitectura correcta para esta situación. La pregunta original en realidad no menciona el contexto en el que se usa la aplicación, así que hablaré sobre las dos situaciones que se me ocurren. El primero es el caso en que la persona que utiliza el programa ya conoce (y está autorizado a conocer) las credenciales de la base de datos. El segundo es el caso en el que usted, el desarrollador, intenta mantener en secreto las credenciales de la base de datos de la persona que usa el programa.

Primer caso:el usuario está autorizado a conocer las credenciales de inicio de sesión de la base de datos

En este caso, la solución que mencioné anteriormente funcionará. La Preference de Java class almacenará el nombre de usuario y la contraseña en texto sin formato, pero el archivo de preferencias solo podrá ser leído por el usuario autorizado. El usuario puede simplemente abrir el archivo XML de preferencias y leer las credenciales de inicio de sesión, pero eso no es un riesgo de seguridad porque, para empezar, el usuario conocía las credenciales.

Segundo caso:intentar ocultar las credenciales de inicio de sesión del usuario

Este es el caso más complicado:el usuario no debe conocer las credenciales de inicio de sesión pero aún necesita acceso a la base de datos. En este caso, el usuario que ejecuta la aplicación tiene acceso directo a la base de datos, lo que significa que el programa necesita conocer las credenciales de inicio de sesión con anticipación. La solución que mencioné anteriormente no es apropiada para este caso. Puede almacenar las credenciales de inicio de sesión de la base de datos en un archivo de preferencias, pero el usuario podrá leer ese archivo, ya que será el propietario. De hecho, realmente no hay una buena manera de usar este caso de forma segura.

Caso correcto:uso de una arquitectura de varios niveles

La forma correcta de hacerlo es tener una capa intermedia, entre su servidor de base de datos y su aplicación cliente, que autentica a los usuarios individuales y permite realizar un conjunto limitado de operaciones. Cada usuario tendría sus propias credenciales de inicio de sesión, pero no para el servidor de la base de datos. Las credenciales permitirían el acceso a la capa intermedia (el nivel de lógica empresarial) y serían diferentes para cada usuario.

Cada usuario tendría su propio nombre de usuario y contraseña, que podrían almacenarse localmente en un archivo de preferencias sin ningún riesgo de seguridad. Esto se denomina arquitectura de tres niveles (los niveles son su servidor de base de datos, servidor de lógica empresarial y aplicación cliente). Es más complejo, pero realmente es la forma más segura de hacer este tipo de cosas.

El orden básico de las operaciones es:

  1. El cliente se autentica con el nivel de lógica empresarial mediante el nombre de usuario y la contraseña personales del usuario. El nombre de usuario y la contraseña son conocidos por el usuario y no están relacionados con las credenciales de inicio de sesión de la base de datos de ninguna manera.
  2. Si la autenticación tiene éxito, el cliente realiza una solicitud al nivel de lógica de negocios solicitando información de la base de datos. Por ejemplo, un inventario de productos. Tenga en cuenta que la solicitud del cliente no es una consulta SQL; es una llamada a un procedimiento remoto como getInventoryList .
  3. El nivel de lógica empresarial se conecta a la base de datos y recupera la información solicitada. El nivel de lógica de negocios se encarga de formar una consulta SQL segura basada en la solicitud del usuario. Todos los parámetros de la consulta SQL deben desinfectarse para evitar ataques de inyección SQL.
  4. El nivel de lógica empresarial envía la lista de inventario a la aplicación cliente.
  5. El cliente muestra la lista de inventario al usuario.

Tenga en cuenta que en todo el proceso, la aplicación cliente nunca se conecta directamente a la base de datos . El nivel de lógica empresarial recibe una solicitud de un usuario autenticado, procesa la solicitud del cliente de una lista de inventario y solo entonces ejecuta una consulta SQL.