Masquage du mot de passe dans les scripts shell

23

Comment masquer un mot de passe dans des scripts shell? Il existe un certain nombre de scripts qui accèdent à la base de données. Si nous ouvrons le script, d'autres connaissent également le nom d'utilisateur et le mot de passe. Donc, si quelqu'un sait comment se cacher, faites-le moi savoir.

J'ai un moyen: placer le mot de passe dans un fichier et le rendre caché et personne ne va accéder au fichier (changer les autorisations et utiliser le fichier dans le script tout en accédant à la base de données).

arun
la source

Réponses:

35

Tout d'abord , comme plusieurs personnes l'ont déjà dit, il est essentiel de conserver les informations d'identification distinctes du script. (En plus d'une sécurité accrue, cela signifie également que vous pouvez réutiliser le même script pour plusieurs systèmes avec des informations d'identification différentes.)

Deuxièmement , vous devez prendre en compte non seulement la sécurité des informations d'identification, mais également l'impact si / quand ces informations d'identification sont compromises. Vous ne devez pas avoir un seul mot de passe pour tous les accès à la base de données, vous devez avoir des informations d'identification différentes avec différents niveaux d'accès. Vous pouvez, par exemple, avoir un utilisateur de base de données qui a la possibilité d'effectuer une recherche dans la base de données - cet utilisateur doit avoir un accès en lecture seule. Un autre utilisateur peut être autorisé à insérer de nouveaux enregistrements, mais pas à les supprimer. Un troisième peut être autorisé à supprimer des enregistrements.

En plus de restreindre les autorisations pour chaque compte, vous devez également restreindre la provenance de chaque compte. Par exemple, le compte utilisé par votre serveur Web ne doit pas être autorisé à se connecter à partir d'une autre adresse IP que celle du serveur Web. Un compte avec des autorisations root complètes sur la base de données doit être très limité en termes de provenance et ne doit jamais être utilisé autrement qu'interactivement. Pensez également à utiliser des procédures stockées dans la base de données pour restreindre exactement ce qui peut être fait par chaque compte.

Ces restrictions doivent être implémentées du côté serveur de base de données du système, de sorte que même si le côté client est compromis, les restrictions ne peuvent pas en être modifiées. (Et, évidemment, le serveur DB doit être protégé avec des pare-feu, etc. en plus de la configuration DB ...)

Dans le cas d'un compte DB qui n'est autorisé qu'à un accès limité en lecture seule, et uniquement à partir d'une adresse IP particulière, vous n'aurez peut-être pas besoin d'autres informations d'identification que cela, selon la sensibilité des données et la sécurité de l'hôte du script est en cours d'exécution. Un exemple peut être un formulaire de recherche sur votre site Web, qui peut être exécuté avec un utilisateur qui est uniquement autorisé à utiliser une procédure stockée qui extrait uniquement les informations qui seront présentées sur la page Web. Dans ce cas, l'ajout d'un mot de passe ne confère pas vraiment de sécurité supplémentaire, car ces informations sont déjà censées être publiques, et l'utilisateur ne peut accéder à aucune autre donnée qui serait plus sensible.

Assurez-vous également que la connexion à la base de données est établie à l'aide de TLS, ou que quiconque écoute sur le réseau peut obtenir vos informations d'identification.

Troisièmement , réfléchissez au type d'informations d'identification à utiliser. Les mots de passe ne sont qu'une forme et ne sont pas les plus sécurisés. Vous pouvez à la place utiliser une certaine forme de paire de clés publique / privée, ou AD / PAM ou similaire.

Quatrièmement , considérez les conditions dans lesquelles le script sera exécuté:

S'il est exécuté de manière interactive, vous devez entrer le mot de passe ou le mot de passe de la clé privée ou de la clé privée, ou être connecté avec un ticket Kerberos valide, lorsque vous l'exécutez - en d'autres termes, le script doit obtenir son informations d'identification directement auprès de vous au moment où vous l'exécutez, au lieu de les lire à partir d'un fichier.

S'il est exécuté à partir d'un serveur Web, envisagez de configurer les informations d'identification au moment où vous démarrez le serveur Web. Un bon exemple ici est les certificats SSL - ils ont un certificat public et une clé privée, et la clé privée a un mot de passe. Vous pouvez stocker la clé privée sur le serveur Web, mais vous devez toujours y saisir le mot de passe lorsque vous démarrez Apache. Vous pouvez également disposer des informations d'identification sur un type de matériel, tel qu'une carte physique ou un HSM, qui peut être supprimé ou verrouillé une fois le serveur démarré. (Bien sûr, l'inconvénient de cette méthode est que le serveur ne peut pas redémarrer seul si quelque chose se produit. Je préférerais cela au risque de compromettre mon système, mais votre kilométrage peut varier ...)

Si le script est exécuté à partir de cron, c'est la partie difficile. Vous ne voulez pas que les informations d'identification se trouvent n'importe où sur votre système où quelqu'un puisse y accéder - mais vous voulez les faire traîner afin que votre script puisse y accéder, non? Eh bien, pas tout à fait raison. Considérez exactement ce que fait le script. De quelles autorisations a-t-il besoin sur la base de données? Peut-il être restreint de manière à ce que la mauvaise personne se connecte avec ces autorisations? Pouvez-vous plutôt exécuter le script directement sur le serveur de base de données auquel personne d'autre n'a accès, au lieu du serveur qui a d'autres utilisateurs? Si, pour une raison à laquelle je ne peux pas penser, vous devez absolument exécuter le script sur un serveur non sécurisé et il doit être capable de faire quelque chose de dangereux / destructeur ... c'est le bon moment pour repenser votre architecture.

Cinquièmement , si vous appréciez la sécurité de votre base de données, vous ne devez pas exécuter ces scripts sur des serveurs auxquels d'autres personnes ont accès. Si quelqu'un est connecté sur votre système, il aura alors la possibilité d'obtenir vos informations d'identification. Par exemple, dans le cas d'un serveur Web avec un certificat SSL, il existe au moins une possibilité théorique que quelqu'un puisse accéder à la racine et accéder à la zone de mémoire du processus httpd et extraire les informations d'identification. Il y a eu au moins un exploit ces derniers temps où cela pourrait être fait via SSL, sans même exiger que l'attaquant soit connecté.

Pensez également à utiliser SELinux ou apparmor ou tout ce qui est disponible pour votre système pour restreindre les utilisateurs qui peuvent faire quoi. Ils vous permettront d'interdire aux utilisateurs d'essayer même de se connecter à la base de données, même s'ils parviennent à accéder aux informations d'identification.

Si tout cela vous semble exagéré , et que vous ne pouvez pas vous le permettre ou que vous n'avez pas le temps de le faire - alors, à mon avis (arrogant et élitiste), vous ne devriez pas stocker quoi que ce soit d'important ou de sensible dans votre base de données. Et si vous ne stockez rien d'important ou de sensible, alors où vous stockez vos informations d'identification n'est pas important non plus - dans ce cas, pourquoi utiliser un mot de passe?

Enfin , si vous ne pouvez absolument pas éviter de stocker une sorte d'informations d'identification, vous pourriez avoir les informations d'identification en lecture seule et détenues par root et root pourrait accorder la propriété de manière extrêmement temporaire lorsque le script le demande (car votre script ne devrait pas être exécuter en tant que root, sauf si absolument nécessaire, et la connexion à une base de données ne le rend pas nécessaire). Mais ce n'est toujours pas une bonne idée.

Jenny D
la source
9
Pas du tout arrogant et élitiste. Ou bien je le suis aussi. "Comment puis-je protéger mes bijoux en cas d'effraction?" "Mettez-le dans un coffre-fort qui est boulonné / soudé en place." "C'est trop de problèmes, je vais juste prendre un coffre-fort portable et accrocher la clé à un crochet." "Alors ne t'embête pas à utiliser un coffre-fort." Conseils éminemment sensés.
Wildcard
12

Tout d'abord, s'il existe un moyen de changer les choses pour éviter d'avoir à stocker un mot de passe à l'intérieur ou à côté d'un script, vous devriez faire tous les efforts pour le faire. La réponse de Jenny D contient beaucoup de bons conseils à cet effet.

Sinon, votre idée de placer le mot de passe dans un fichier séparé avec des autorisations restreintes est à peu près tout. Vous pouvez par exemple source ce fichier à partir du script principal:

. /usr/local/etc/secret-password-here

Vous pouvez également restreindre les autorisations du script principal afin que seules les personnes autorisées puissent l'exécuter, mais il est probablement préférable de faire comme vous le suggérez et de stocker uniquement le mot de passe lui-même dans un fichier restreint. De cette façon, vous pouvez permettre l'inspection du code lui-même (sans secrets sensibles), le contrôle de version et la copie autour du script plus facilement, etc ...

Celada
la source
@BasileStarynkevitch ah mais je vois qu'il dit aussi " /usr/local/etcpeut être un lien symbolique vers /etc/local". J'ai manqué ça. Vous avez donc également raison, mais c'est un MAI, donc c'est facultatif. Mais oui, ça n'a pas beaucoup d'importance, et de préférence personnelle.
Celada
1
Sauf que je sauvegarde /etc/ mais pas /usr/local/ (ce qui, je suppose, peut être reconstruit après un crash de disque)
Basile Starynkevitch
juste point sur les sauvegardes
Celada
3

D'autres réponses ont porté sur le comment , mais je considérerai le si . Selon le type de base de données auquel vos utilisateurs se connectent, vous pouvez déjà avoir un mécanisme approprié qui est déjà utilisé par ces programmes clients, auquel cas assurez-vous de les utiliser (je pense à ~/.mysqlrcou ~/.pgpass).

Si vous donnez à plusieurs utilisateurs la possibilité d'accéder à la base de données pour effectuer des requêtes spécifiques à l'aide d'un compte partagé, vous ne devriez probablement pas. Au lieu de cela, assurez-vous qu'ils ont des comptes sur la base de données et que ces comptes n'ont pas plus d'autorisations que nécessaire (probablement lire une grande partie de celui-ci et très peu d'accès en écriture). S'ils doivent effectuer des requêtes spécifiques sur certaines tables auxquelles ils ne pourraient pas accéder autrement, fournissez des procédures stockées SECURTY DEFINERpour leur permettre de le faire.

Si aucun des ci - dessus évite que vous ayez à des informations d' identification de magasin, puis lire les autres réponses ici.

Toby Speight
la source
1

Votre idée de cacher le mot de passe dans un endroit inaccessible pourrait être OK selon les circonstances.

Si les informations sont séparées, cela signifie une simple modification du fichier, par exemple lors d'une révision de code avec un collègue ne va pas le montrer. Mais sachez que toute personne ayant accès à votre compte peut facilement trouver un tel fichier. J'ai utilisé un sous-répertoire de ~/.sshà de telles fins, pour la simple raison que l'on se sshplaint si les droits d'accès ~/.sshne sont pas suffisamment restreints.

Il y a cependant d'autres choses que vous pouvez faire pour empêcher un tel coup d'œil du nom d'utilisateur et / ou des mots de passe.

Obscurcissement : Si vous ne voulez pas que quelqu'un lise le nom d'utilisateur ou le mot de passe pendant que vous modifiez un script, vous pouvez le mettre dans le texte, mais pas en texte brut, mais obscurci. Si la version obscurcie est suffisamment longue pour empêcher sa mémorisation par quelqu'un qui la regarde, elle ne peut pas être connue même si la méthode et la clé de déchiffrement sont bien en vue. Bien sûr, cela serait encore contourné par une personne ayant accès à votre compte.

Utilisation de GPG :

Un peu mieux, mais toujours pas une preuve complète contre les attaques de l'utilisateur root sur votre système, consiste à chiffrer les paires nom d'utilisateur / mot de passe dans un fichier gpgpublic et à ce que le script récupère le contenu du fichier (possible de vous demander un mot de passe, sinon mis en cache / expiré). J'utilise ggp-card pour que lorsque je laisse mon ordinateur portable autour mais que je retire la carte, aucun accès ne soit possible même si la broche serait toujours mise en cache. Au moins, si je lance quelque chose 20 fois en quelques minutes, je ne dois fournir la broche qu'une seule fois.

La sécurité semble toujours inversement liée à la commodité (configuration et utilisation).

Anthon
la source
0

Il existe un moyen de stocker les mots de passe dans un script bash mais vous devez crypter et obscurcir le script afin que personne ne puisse le lire ou exécuter n'importe quel type de débogueur dessus pour voir exactement ce qu'il fait. Pour chiffrer et obscurcir un script bash / shell et qu'il soit réellement exécutable, essayez de le copier et de le coller ici:

http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm

Sur la page ci-dessus, tout ce que vous avez à faire est de soumettre votre script (vous pouvez d'abord soumettre un exemple de script pour votre tranquillité d'esprit). Un fichier zip sera généré pour vous. Faites un clic droit sur le lien de téléchargement et copiez l'URL qui vous est fournie. Ensuite, accédez à votre boîte UNIX et effectuez les étapes suivantes.

Installation:

  1. wget lien vers le fichier zip

  2. décompressez le fichier zip nouvellement téléchargé

  3. cd / tmp / KingLazySHIELD

  4. ./install.sh / var / tmp / KINGLAZY / SHIELDX- (votre-nom-de-script) / home / (votre-nom-d'utilisateur) -force

Ce que la commande d'installation ci-dessus fera pour vous:

  1. Il installera la version chiffrée de votre script dans le répertoire / var / tmp / KINGLAZY / SHIELDX- (votre-nom-script).

  2. Il placera un lien vers ce script crypté dans le répertoire que vous spécifiez en remplacement de / home / (votre-nom d'utilisateur) - de cette façon, il vous permet d'accéder facilement au script sans avoir à taper le chemin absolu.

  3. Garantit que PERSONNE ne peut modifier le script - Toute tentative de modification du script crypté le rendra inutilisable ... jusqu'à ce que ces tentatives soient arrêtées ou supprimées. Il peut même être configuré pour vous avertir chaque fois que quelqu'un essaie de faire autre chose avec le script que de l'exécuter ... c'est-à-dire des tentatives de piratage ou de modification.

  4. Garantit que personne ne peut en faire de copie. Personne ne peut copier votre script dans un endroit isolé et essayer de le contourner pour voir comment cela fonctionne. Toutes les copies du script doivent être des liens vers l'emplacement d'origine que vous avez spécifié lors de l'installation (étape 4).

REMARQUE:

Je ne pense pas que cela fonctionne pour les scripts interactifs qui invitent l'utilisateur à répondre. Les valeurs doivent être codées en dur dans le script. Le cryptage garantit que personne ne peut réellement voir ces valeurs, vous n'avez donc pas à vous en soucier.

AncientMinds
la source
0

Une autre solution, sans égard à la sécurité (je pense aussi qu'il vaut mieux conserver les informations d'identification dans un autre fichier ou dans une base de données) est de crypter le mot de passe avec gpg et de l'insérer dans le script.

J'utilise une paire de clés gpg sans mot de passe que je garde dans une clé USB. (Remarque: lorsque vous exportez cette paire de clés, n'utilisez pas --armor, exportez-les au format binaire).

Cryptez d'abord votre mot de passe:

echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient someone@mail.com --encrypt

Ce sera imprimé le mot de passe crypté gpg dans la sortie standard. Copiez l'intégralité du message et ajoutez-le au script:

password=$(gpg --batch --quiet --no-default-keyring --secret-keyring /media/usb/key.priv --decrypt <<EOF 
-----BEGIN PGP MESSAGE-----

hQEMA0CjbyauRLJ8AQgAkZT5gK8TrdH6cZEy+Ufl0PObGZJ1YEbshacZb88RlRB9
h2z+s/Bso5HQxNd5tzkwulvhmoGu6K6hpMXM3mbYl07jHF4qr+oWijDkdjHBVcn5
0mkpYO1riUf0HXIYnvCZq/4k/ajGZRm8EdDy2JIWuwiidQ18irp07UUNO+AB9mq8
5VXUjUN3tLTexg4sLZDKFYGRi4fyVrYKGsi0i5AEHKwn5SmTb3f1pa5yXbv68eYE
lCVfy51rBbG87UTycZ3gFQjf1UkNVbp0WV+RPEM9JR7dgR+9I8bKCuKLFLnGaqvc
beA3A6eMpzXQqsAg6GGo3PW6fMHqe1ZCvidi6e4a/dJDAbHq0XWp93qcwygnWeQW
Ozr1hr5mCa+QkUSymxiUrRncRhyqSP0ok5j4rjwSJu9vmHTEUapiyQMQaEIF2e2S
/NIWGg==
=uriR
-----END PGP MESSAGE-----
EOF)

De cette façon, uniquement si l'USB est monté dans le système, le mot de passe peut être déchiffré. Bien sûr, vous pouvez également importer les clés dans le système (moins sécurisées, ou pas de sécurité du tout) ou vous pouvez protéger la clé privée avec un mot de passe (donc elle ne peut pas être automatisée).

Juanu
la source
-2
#!/bin/bash
unset username
unset password
unset dbname
echo -n "username:"
read username
echo -n "dbname:"
read dbname
prompt="password:"

    while IFS= read -p "$prompt" -r -s -n 1 char
            do
                    if [[ $char == $'\0' ]]
                            then
                                    break
                    fi
                    prompt='*'
                    password+="$char"
            #       read -s -p "Enter Password: "  pswd
            #       echo -e "\nYour password is: " $pswd
            done
arun
la source
3
J'ai mis en retrait votre code, peut-être pourriez-vous expliquer ce que vous essayez de faire?
Archemar
-6

Je ne pense pas que vous devriez jamais enregistrer le mot de passe. Je ne peux pas penser à une seule bonne raison à cela. Au lieu de cela, vous devez stocker un hachage salé de ce mot de passe - une chaîne qui est produite de manière fiable par une fonction lorsque le mot de passe d'origine est passé en entrée, mais jamais le mot de passe .

mikeserv
la source
5
Je ne sais pas comment cela résoudra le problème: a) de pouvoir se connecter à un service nécessitant un mot de passe, et b) que les utilisateurs puissent voir le script et ainsi être en mesure de comprendre les détails d'authentification, qu'il s'agisse de mots de passe ou pas
Jenny D
1
Vous prétendez connaître ma réponse avant de l'avoir écrite.
Jenny D
1
J'ai écrit ma réponse maintenant. Ce que j'essayais d'obtenir de vous était en partie mon cinquième point - une fois que les informations d'identification sont stockées en mémoire, elles ne sont pas entièrement sécurisées contre un attaquant ayant accès au serveur. De plus, votre réponse concise n'était pas très utile, même si elle n'était pas incorrecte. Je pense à le signaler la prochaine fois que quelqu'un se plaindra que nous, chez ServerFault, ne sommes pas aussi gentils que les gens d'Unix / Linux :-)
Jenny D
2
@JennyD - une fois que le crédit est en mémoire - il n'a certainement pas besoin de rester là - et c'est une très bonne raison de traiter avec des hachages à la place de toute façon. Pourtant, je serai heureux de représenter les normes de courtoisie de la communauté comme son exemple en général - je suis très bien connu pour ce trait, en fait.
mikeserv
4
Après votre grande discussion, je voudrais juste mentionner au cas où il y aurait un malentendu que c'est moi qui ai rétrogradé, pas Jenny. Et la raison n'était pas une opinion sur l'opportunité ou non d'utiliser un certificat et une clé privée ou un mot de passe entré de manière interactive ou de faire ce que l'OP voulait ou autre chose. C'est parce que la réponse actuelle est fausse: stocker un hachage salé du mot de passe en tant qu'identifiant client n'est pas une chose: les hachages salés sont une chose que vous gardez à la fin de la connexion qui vérifie l'auth, pas sur le côté qui le soumet.
Celada