J'ai une application Java) qui se connecte à une base de données.
Le nom d'utilisateur et le mot de passe de la base de données sont stockés dans un fichier de propriétés.
Quelle est la pratique courante pour éviter de stocker le mot de passe en texte clair dans le fichier de propriétés tout en conservant l’option permettant à l’utilisateur de le modifier?
La principale motivation ici est d'empêcher quelqu'un de regarder par-dessus l'épaule de l'administrateur et de voir le mot de passe lorsque l'administrateur modifie le fichier de propriétés.
J'ai lu ici qu'il existe une méthode intégrée pour le faire en C #.
Connaissant Java, je ne m'attends pas à trouver une solution intégrée, mais j'aimerais entendre ce que font les autres.
Si je ne trouve pas le bon choix, je vais probablement le chiffrer avec un mot de passe constant qui sera conservé dans le code. Mais je détesterais le faire de cette façon parce que ça fait mal.
Edit 12 décembre 2012 On dirait qu'il n'y a pas de magie et je dois stocker le mot de passe dans le code ou quelque chose de similaire. À la fin, nous avons mis en œuvre quelque chose de très similaire à ce que fait Jasypt, mentionné dans l'une des réponses. J'accepte donc la réponse de Jasypt car c'est ce qui se rapproche le plus d'une réponse définitive.
Jasypt fournit la classe org.jasypt.properties.EncryptableProperties pour charger, gérer et décrypter de manière transparente les valeurs chiffrées dans les fichiers .properties, permettant ainsi le mélange des données chiffrées et non chiffrées. valeurs chiffrées dans le même fichier.
http://www.jasypt.org/encrypting-configuration.html
En utilisant un objet org.jasypt.properties.EncryptableProperties, une application serait capable de lire et d'utiliser correctement un fichier .properties comme celui-ci:
datasource.driver=com.mysql.jdbc.Driver
datasource.url=jdbc:mysql://localhost/reportsdb
datasource.username=reportsUser
datasource.password=ENC(G6N718UuyPE5bHyWKyuLQSm02auQPUtm)
Notez que le mot de passe de la base de données est crypté (en fait, toute autre propriété peut également être cryptée, qu'elle soit liée à la configuration de la base de données ou non).
Comment lisons-nous cette valeur? comme ça:
/*
* First, create (or ask some other component for) the adequate encryptor for
* decrypting the values in our .properties file.
*/
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("jasypt"); // could be got from web, env variable...
/*
* Create our EncryptableProperties object and load it the usual way.
*/
Properties props = new EncryptableProperties(encryptor);
props.load(new FileInputStream("/path/to/my/configuration.properties"));
/*
* To get a non-encrypted value, we just get it with getProperty...
*/
String datasourceUsername = props.getProperty("datasource.username");
/*
* ...and to get an encrypted value, we do exactly the same. Decryption will
* be transparently performed behind the scenes.
*/
String datasourcePassword = props.getProperty("datasource.password");
// From now on, datasourcePassword equals "reports_passwd"...
La solution de compromis de l'homme pauvre consiste à utiliser une approche simpliste à signatures multiples.
Par exemple, l'administrateur de base de données définit le mot de passe de la base de données des applications sur une chaîne aléatoire de 50 caractères. TAKqWskc4ncvKaJTyDcgAHq82X7tX6GfK2fc386bmNw3muknj
Il ou elle donne la moitié du mot de passe au développeur de l’application qui le code ensuite dans le fichier binaire Java.
private String pass1 = "TAKqWskc4ncvKaJTyDcgAHq82"
L'autre moitié du mot de passe est passé en tant qu'argument de ligne de commande. l'administrateur de la base de données transmet pass2 à l'assistance technique du système ou à la personne administrative qui y entre l'heure de début de l'application ou l'inscrit dans le script de démarrage automatisé de l'application.
Java -jar /myapplication.jar -pass2 X7tX6GfK2fc386bmNw3muknjU
Lorsque l'application démarre, elle utilise pass1 + pass2 et se connecte à la base de données.
Cette solution présente de nombreux avantages sans les inconvénients mentionnés.
Vous pouvez mettre en toute sécurité la moitié du mot de passe dans un argument de ligne de commande, car sa lecture ne vous aidera pas beaucoup, sauf si vous êtes le développeur qui possède l'autre moitié du mot de passe.
L'administrateur de base de données peut également modifier la seconde moitié du mot de passe et le développeur n'a pas besoin de redéployer l'application.
Le code source peut également être semi-public, car le lire et le mot de passe ne vous donnera pas accès à l'application.
Vous pouvez améliorer encore la situation en ajoutant des restrictions sur les plages d'adresses IP à partir desquelles la base de données acceptera les connexions.
Qu'en est-il de fournir un mécanisme d'authentification personnalisé N-Factor?
Avant de combiner les méthodes disponibles, supposons que nous puissions effectuer les opérations suivantes:
1) Code dur à l’intérieur du programme Java
2) Stocker dans un fichier .properties
3) Demander à l'utilisateur de taper le mot de passe en ligne de commande
4) Demander à l'utilisateur de taper le mot de passe à partir d'un formulaire
5) Demander à l'utilisateur de charger un fichier de mots de passe à partir d'une ligne de commande ou d'un formulaire
6) Fournir le mot de passe via le réseau
7) de nombreuses alternatives (par exemple Draw A Secret, Fingerprint, IP-spécifique, bla bla bla)
1ère option: Nous pourrions rendre les choses plus compliquées pour un attaquant en utilisant l'obscurcissement, mais ceci n'est pas considéré comme une bonne contre-mesure. Un bon codeur peut facilement comprendre son fonctionnement s’il peut accéder au fichier. Nous pourrions même exporter un fichier binaire par utilisateur (ou simplement la partie ou la partie clé de l'obfuscation), de sorte qu'un attaquant doit avoir accès à ce fichier spécifique à l'utilisateur, pas à une autre distribution. Encore une fois, nous devrions trouver un moyen de changer les mots de passe, par exemple en recompilant ou en utilisant la réflexion pour un comportement de classe de changement à la volée.
2ème option: Nous pouvons stocker le mot de passe dans le fichier .properties dans un format chiffré, afin qu'il ne soit pas directement visible de l'attaquant (comme jasypt fait). Si nous avons besoin d'un gestionnaire de mots de passe, nous aurons également besoin d'un mot de passe principal, qui devrait à nouveau être stocké quelque part - dans un fichier .class, le magasin de clés, le noyau, un autre fichier ou même en mémoire - ont tous des avantages et des inconvénients.
Mais, maintenant, les utilisateurs ne feront que modifier le fichier .properties pour le changement de mot de passe.
3ème option: saisissez le mot de passe lors de l'exécution à partir de la ligne de commande, par exemple. Java -jar /myprogram.jar -p sdflhjkiweHIUHIU8976hyd
.
Cela n'exige pas que le mot de passe soit stocké et restera en mémoire. Cependant, les commandes history
et les journaux du système d'exploitation peuvent être votre pire ennemi ici. Pour changer les mots de passe à la volée, vous devrez implémenter certaines méthodes (par exemple, écouter les entrées de la console, RMI, les sockets, REST bla bla bla), mais le mot de passe restera toujours en mémoire .
Vous pouvez même le déchiffrer temporairement uniquement lorsque cela est nécessaire -> puis supprimez le déchiffré, mais conservez toujours le mot de passe chiffré en mémoire. Malheureusement, la méthode susmentionnée n'augmente pas la sécurité contre les accès non autorisés en mémoire, car la personne qui y parviendra aura probablement accès à l'algorithme, au sel et à tout autre secret utilisé.
4ème option: fournissez le mot de passe à partir d'un formulaire personnalisé plutôt que de la ligne de commande. Cela contournera le problème de la journalisation de l'exposition.
5ème option: fournissez un fichier en tant que mot de passe stocké précédemment sur un autre support -> puis supprimez le fichier. Cela permettra à nouveau de contourner le problème de l'exposition lors de la journalisation, sans qu'aucune dactylographie ne soit volée. Lorsqu'un changement est requis, fournissez un autre fichier, puis supprimez-le à nouveau.
6ème option: pour éviter à nouveau la navigation en bandoulière, on peut implémenter un appel de méthode RMI, pour fournir le mot de passe (via un canal crypté) à partir d'un autre périphérique, par exemple via un téléphone mobile. Cependant, vous devez maintenant protéger votre canal réseau et accéder à l'autre périphérique.
Je choisirais une combinaison des méthodes ci-dessus pour obtenir une sécurité maximale et accéder ainsi aux fichiers .class, au fichier de propriétés, aux journaux, au canal réseau, au surf sur l'épaule, à l'homme au milieu, à d'autres fichiers bla bla bla. Ceci peut être facilement implémenté en utilisant une opération XOR) entre tous les sous-mots de passe pour produire le mot de passe actuel.
Nous ne pouvons pas être protégés contre les accès non autorisés en mémoire, cependant, cela ne peut être réalisé qu'en utilisant du matériel à accès restreint (cartes à puce, HSM, SGX, par exemple), où tout est calculé en eux, sans que quiconque, même le propriétaire légitime capable d'accéder à des clés de décryptage ou des algorithmes. Encore une fois, on peut aussi voler ce matériel, signalent attaques par canaux secondaires qui peuvent aider les attaquants lors de l'extraction de clé et dans certains cas, vous devez faire confiance à une autre partie (par exemple, avec SGX, vous faites confiance à Intel). Bien sûr, la situation risque d'empirer lorsque le clonage sécurisé-enclave (désassemblage) sera possible, mais je suppose que cela prendra plusieurs années pour être pratique.
En outre, on peut envisager une solution de partage de clé où la clé complète est partagée entre différents serveurs. Cependant, lors de la reconstruction, la clé complète peut être volée. Le seul moyen d’atténuer le problème susmentionné consiste à utiliser calcul multipartite sécurisé .
Nous devons toujours garder à l'esprit que, quelle que soit la méthode de saisie, nous devons nous assurer que nous ne sommes pas vulnérables au sniffing de réseau (attaques MITM) et/ou aux enregistreurs de frappe.
En réalité, il s’agit d’un doublon de Crypter le mot de passe dans les fichiers de configuration? .
La meilleure solution que j'ai trouvée jusqu'à présent est dans cette réponse: https://stackoverflow.com/a/1133815/1549977
Avantages: le mot de passe est enregistré dans un tableau de caractères et non sous forme de chaîne. Ce n'est toujours pas bon, mais mieux que toute autre chose.