Pregunta

Los archivos

Java .class se pueden descompilar con bastante facilidad. ¿Cómo puedo proteger mi base de datos si tengo que usar los datos de inicio de sesión en el código?

¿Fue útil?

Solución

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

  

Codificar una cuenta secreta y   contraseña en su software es   extremadamente conveniente - para expertos   Ingenieros inversos. Si la contraseña es   lo mismo en todo su software,   entonces cada cliente se vuelve vulnerable   cuando esa contraseña inevitablemente se convierte   conocido. Y porque está codificado,   es un gran dolor arreglarlo.

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 completa, ejemplos y mucha otra 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 de programa, algunas de las cuales podrían incluir un nombre de usuario y 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, puede llamar al método setCredentials después de mostrar un diálogo pidiendo el nombre de usuario y la contraseña. Cuando necesite conectarse a la base de datos, puede usar los métodos getUsername y getPassword para recuperar los valores almacenados. Las credenciales de inicio de sesión no estarán codificadas en sus binarios, por lo que la descompilación no representará un riesgo de seguridad.

Nota importante: los archivos de preferencias son solo archivos XML de texto sin formato. Asegúrese de tomar las medidas adecuadas para evitar que usuarios no autorizados vean los archivos sin formato (permisos 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 otros usuarios no pueden leer de todos modos. En Windows, la situación puede ser diferente.

Notas más importantes: Se ha discutido mucho en los comentarios de esta respuesta y otras sobre cuál es la arquitectura correcta para esta situación. La pregunta original no menciona realmente el contexto en el que se está utilizando la aplicación, por lo que hablaré sobre las dos situaciones que se me ocurren. El primero es el caso en el que la persona que usa el programa ya conoce (y está autorizada a conocer) las credenciales de la base de datos. El segundo es el caso en el que usted, el desarrollador, está tratando de 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 clase Java Preference almacenará el nombre de usuario y la contraseña en texto plano, pero el archivo de preferencias solo podrá ser leído por el usuario autorizado. El usuario simplemente puede abrir el archivo XML de preferencias y leer las credenciales de inicio de sesión, pero eso no es un riesgo de seguridad porque el usuario conocía las credenciales para empezar.

Segundo caso: Intentando 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

Otros consejos

Coloque la contraseña en un archivo que leerá la aplicación. NUNCA incruste contraseñas en un archivo fuente. Período.

Ruby tiene un módulo poco conocido llamado DBI :: DBRC para dicho uso. No tengo dudas de que Java tiene un equivalente. De todos modos, no es difícil escribir uno.

¿Estás escribiendo una aplicación web? Si es así, use JNDI para configurarlo externamente a la aplicación. Hay disponible una descripción general aquí :

  

JNDI proporciona una manera uniforme para un   aplicación para buscar y acceder a control remoto   servicios a través de la red. El mando a distancia   el servicio puede ser cualquier servicio empresarial,   incluyendo un servicio de mensajería o un   servicio específico de la aplicación, pero, de   Por supuesto, una aplicación JDBC es   interesado principalmente en una base de datos   Servicio. Una vez que un objeto DataSource es   creado y registrado con un JNDI   servicio de nombres, una aplicación puede usar   la API JNDI para acceder a ese DataSource   objeto, que luego se puede utilizar para   conectarse a la fuente de datos que   representa.

No importa lo que haga, la información confidencial se almacenará en algún archivo en algún lugar. Su objetivo es hacer que sea lo más difícil de conseguir. Cuánto de esto puede lograr depende de su proyecto, necesidades y grosor de la billetera de su empresa.

La mejor manera es no almacenar contraseñas en ningún lado. Esto se logra mediante el uso de funciones hash para generar y almacenar hashes de contraseñas:

hash("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
hash("hbllo") = 58756879c05c68dfac9866712fad6a93f8146f337a69afe7dd238f3364946366
  

Los algoritmos hash son funciones unidireccionales. Convierten cualquier cantidad de datos   en una huella dactilar de longitud fija eso no se puede revertir. Ellos también   tener la propiedad de que si la entrada cambia aunque sea un poquito, el   el hash resultante es completamente diferente (ver el ejemplo anterior). Esta   es ideal para proteger contraseñas, porque queremos almacenar contraseñas   en una forma que los proteja incluso si el archivo de contraseña en sí es   comprometido, pero al mismo tiempo, debemos ser capaces de verificar que un   la contraseña del usuario es correcta.

Nota no relacionada: En los viejos tiempos de Internet, cuando hacía clic en el enlace 'Olvidé mi contraseña', los sitios web le enviaban su contraseña de texto sin formato. Probablemente estaban almacenando esos en una base de datos en alguna parte. Cuando los piratas informáticos obtuvieron acceso a su base de datos, obtendrían acceso a todas las contraseñas. Dado que muchos usuarios usarían la misma contraseña en varios sitios web, este era un gran problema de seguridad. Afortunadamente, hoy en día esta no es la práctica común.

Ahora viene la pregunta: ¿cuál es la mejor manera de almacenar contraseñas? Consideraría esta solución (autenticación y servicio de gestión de usuarios stormpath's) es una maldita solución ideal:

  1. Su usuario ingresa las credenciales, y esto se valida contra el hash de contraseña
  2. Los hashes de contraseña se generan y almacenan, no las contraseñas
  3. Los hashes se realizan varias veces
  4. Los hashes se generan usando una sal generada aleatoriamente
  5. Los hashes se cifran con una clave privada
  6. La clave privada se almacena en un lugar físicamente diferente al hash
  7. Las claves privadas están actualizadas de forma temporal
  8. Los hashes cifrados se dividen en trozos
  9. Estos fragmentos se almacenan en ubicaciones separadas físicamente

Obviamente no eres Google ni un banco, así que esta es una solución exagerada para ti. Pero luego viene la pregunta: ¿Cuánta seguridad requiere su proyecto, cuánto tiempo y dinero tiene?

Para muchas aplicaciones, aunque no se recomienda, almacenar una contraseña codificada en el código podría ser una solución lo suficientemente buena. Sin embargo, al agregar fácilmente un par de pasos adicionales de seguridad de la lista anterior, puede hacer que su aplicación sea mucho más segura.

Por ejemplo, supongamos que el paso 1 no es una solución aceptable para su proyecto. No desea que los usuarios ingresen la contraseña cada vez, o ni siquiera quiere / necesita que los usuarios sepan la contraseña. Aún tiene información confidencial en algún lugar y desea protegerla. Tiene una aplicación simple, no hay un servidor para almacenar sus archivos o esto es demasiado complicado para su proyecto. Su aplicación se ejecuta en entornos donde no es posible tener archivos almacenados de forma segura. Este es uno de los peores casos, pero aún con algunas medidas de seguridad adicionales, puede tener una solución mucho más segura. Por ejemplo, puede almacenar la información confidencial en un archivo y puede cifrar el archivo. Puede tener la clave privada de cifrado codificada en el código. Puede ofuscar el código, por lo que es un poco más difícil para alguien descifrarlo. Existen muchas bibliotecas para este propósito, consulte este enlace . (Quiero advertirle una vez más que esto no es 100% seguro. Un pirata informático inteligente con los conocimientos y herramientas adecuados puede hackear esto. Pero basado en

Esta pregunta muestra cómo almacenar contraseñas y otros datos en un archivo cifrado: Cifrado basado en contraseña AES Java de 256 bits

MD5 es un algoritmo hash, no un algoritmo de encriptación, en resumen, no puede recuperar el hash, solo puede comparar. Idealmente, debe usarse cuando se almacena la información de autenticación del usuario y no el nombre de usuario y la contraseña de db. db username y pwd deben encriptarse y mantenerse en un archivo de configuración, por lo menos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top