Java .class
fichiers peuvent être décompilé assez facilement. Comment puis-je protéger ma base de données si je dois utiliser les données de connexion dans le code?
Réponses
Trop de publicités?Jamais coder en dur les mots de passe dans votre code. Cette question a été soulevée récemment dans le Top 25 des Plus Dangereuses Erreurs de Programmation:
Le codage en dur un compte secret et le mot de passe dans votre logiciel est extrêmement pratique-qualifiés inverse ingénieurs. Si le mot de passe est le même à travers tous vos logiciels, ensuite, chaque client devient vulnérable lorsque le mot de passe devient inévitablement connu. Et parce que c'est codé en dur, c'est une immense douleur à corriger.
Vous devez stocker les informations de configuration, y compris les mots de passe dans un fichier séparé que l'application lit quand il commence. C'est la seule véritable façon de prévenir le mot de passe de fuite comme un résultat de la décompilation (jamais compiler dans le binaire pour commencer).
Pour plus d'informations sur cette erreur commune, vous pouvez lire la CWE-259 article. L'article contient une plus approfondie de la définition, des exemples, et beaucoup d'autres informations sur le problème.
En Java, l'un des moyens les plus faciles de le faire est d'utiliser les Préférences de la classe. Il est conçu pour stocker toutes sortes de paramètres de programme, qui pourraient inclure un nom d'utilisateur et mot de passe.
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
}
Dans le code ci-dessus, vous pouvez appeler l' setCredentials
méthode après montrant une boîte de dialogue askign pour le nom d'utilisateur et mot de passe. Lorsque vous devez vous connecter à la base de données, vous pouvez simplement utiliser l' getUsername
et getPassword
méthodes pour récupérer les valeurs stockées. Les identifiants de connexion ne sera pas codées en dur dans vos fichiers binaires, de sorte que la décompilation ne va pas poser un risque de sécurité.
Remarque importante: Les fichiers de préférences sont tout simplement le texte des fichiers XML. Assurez-vous de prendre des mesures appropriées pour empêcher les utilisateurs non autorisés de visualiser les fichiers raw (UNIX autorisations, les autorisations de Windows, et cetera). Dans Linux, au moins, ce n'est pas un problème, parce que l'appelant Preferences.userNodeForPackage
va créer le fichier XML dans le courant répertoire home de l'utilisateur, qui est non lisible par les autres utilisateurs de toute façon. Dans Windows, la situation pourrait être différente.
Plus Important: Il y a eu beaucoup de discussion dans les commentaires de cette réponse et d'autres au sujet de la bonne architecture est pour cette situation. La question d'origine n'a pas vraiment parler du contexte dans lequel l'application est utilisée, donc je vais vous parler des deux situations que je pense. Le premier est le cas où la personne qui utilise le programme connaît déjà (et est autorisé à connaître) la base de données d'informations d'identification. La seconde est le cas dans lequel vous, le développeur, tentent de conserver la base de données d'informations d'identification secret de la personne qui utilise le programme.
Premier Cas: l'Utilisateur est autorisé à connaître la base de données d'informations de connexion
Dans ce cas, la solution que j'ai mentionné ci-dessus va travailler. La Java Preference
classe sera stocké le nom d'utilisateur et le mot de passe en texte brut, mais le fichier de préférences ne seront lisibles par l'utilisateur autorisé. L'utilisateur peut simplement ouvrir les préférences de fichier XML et de lire les informations d'identification de connexion, mais ce n'est pas un risque pour la sécurité, car l'utilisateur savais que les informations d'identification pour commencer.
Deuxième Cas: en Essayant de masquer les informations d'identification de connexion de l'utilisateur
C'est le cas plus compliqué: l'utilisateur ne doit pas connaître les identifiants de connexion mais a encore besoin de l'accès à la base de données. Dans ce cas, l'utilisateur qui exécute l'application dispose d'un accès direct à la base de données, ce qui signifie que le programme a besoin de connaître les identifiants de connexion à l'avance. La solution que j'ai mentionné ci-dessus n'est pas approprié pour ce cas. Vous pouvez stocker la base de données d'informations de connexion dans un fichier de préférences, mais il l'utilisateur sera capable de lire ce fichier, car ils seront le propriétaire. En fait, il n'y a vraiment pas de bonne façon d'utiliser ce cas de manière sécurisée.
Casse: à l'Aide d'une architecture multi-niveaux
La bonne façon de le faire est d'avoir une couche intermédiaire entre votre serveur de base de données et l'application client, qui permet d'authentifier les utilisateurs individuels et permet à un ensemble limité d'opérations à effectuer. Chaque utilisateur a leurs propres informations d'identification de connexion, mais pas pour le serveur de base de données. Les informations d'identification permettrait l'accès à la couche du milieu (la couche de logique métier) et serait différente pour chaque utilisateur.
Chaque utilisateur aura son propre nom d'utilisateur et le mot de passe, ce qui pourrait être stockée localement dans un fichier de préférences, sans aucun risque pour la sécurité. Cela s'appelle une architecture à trois niveaux (les niveaux en cours de votre serveur de base de données, la logique métier de serveur, et le client de l'application). Il est plus complexe, mais c'est vraiment le plus sûr moyen de faire ce genre de chose.
L'ordre de base des opérations:
- Le Client s'authentifie auprès de couche de logique métier à l'aide de personnel de l'utilisateur nom d'utilisateur/mot de passe. Le nom d'utilisateur et mot de passe sont connus à l'utilisateur et ne sont pas liés à la connexion de base de données d'informations d'identification d'une quelconque façon.
- Si l'authentification réussit, le client fait une demande à la couche logique métier demandant certains renseignements provenant de la base de données. Par exemple, un inventaire de produits. Notez que la demande du client n'est pas une requête SQL, c'est un appel de procédure distante comme
getInventoryList
. - La couche de logique métier se connecte à la base de données et récupère les informations demandées. La couche de logique métier est en charge de la formation d'une sécurité de requête SQL basé sur la demande de l'utilisateur. Tous les paramètres de la requête SQL doivent être désinfectés pour prévenir les attaques par injection SQL.
- La couche de logique métier envoie la liste d'inventaire de retour à l'application cliente.
- Le client affiche la liste de l'inventaire à l'utilisateur.
Notez que dans l'ensemble du processus, le client demande de ne jamais se connecte directement à la base de données. La couche de logique métier reçoit une demande d'un utilisateur authentifié, le processus de la demande du client pour une liste d'inventaire, et seulement ensuite, exécute une requête SQL.
Mettre le mot de passe dans un fichier que l'application va lire. Ne JAMAIS incorporer des mots de passe dans un fichier source. Période.
Ruby a un peu connu module DBI::DBRC pour une telle utilisation. Je ne doute pas que Java a un équivalent. De toute façon, il n'est pas difficile d'en écrire un.
Êtes-vous l'écriture d'une application web? Si oui, utiliser JNDI pour le configurer de manière externe à l'application. Un aperçu est disponible ici:
JNDI fournit une manière uniforme pour une application pour rechercher et accéder à distance à des services sur le réseau. La distance le service peut être de n'importe quelle entreprise de service, y compris un service de messagerie ou un demande-service spécifique, mais, de bien sûr, une application JDBC est intéressés principalement dans une base de données service. Une fois un objet DataSource est créé et enregistré avec un JNDI service de nommage, une application peut utiliser l'API JNDI pour accéder à cette source de données objet, qui peut ensuite être utilisé pour se connecter à la source de données, il représente.
MD5 est un algorithme de hachage, pas un algorithme de chiffrement, en bref u ne peut pas revenir wat u haché, u ne peut comparer. Idéalement, il devrait être utilisé lors de stocker les informations d'authentification utilisateur et de ne pas db nom d'utilisateur et mot de passe. db nom d'utilisateur et le pwd doivent être cryptées et traitées dans un fichier de config, pour le moins.