
La conservation des mots de passe a toujours été un casse-tête. Dans la version classique, vous avez un utilisateur qui s'efforce de ne pas oublier le "qwerty123" terriblement secret et le système d'information qui stocke le hachage de ce mot de passe. Un bon système doit également soigneusement saler les hachages afin d'empoisonner la vie de mauvaises personnes qui peuvent voler une base de données avec des mots de passe hachés. Tout est clair ici. Certains mots de passe sont stockés dans la tête et certains sont cryptés dans keepass.
Tout change lorsque nous retirons du schéma une personne qui entre soigneusement la clé d'un morceau de papier. Dans l'interaction de deux systèmes d'information, dans tous les cas, le mot de passe doit être stocké côté client sous une forme ouverte pour le système afin qu'il puisse être transmis et comparé au hachage de référence. Et à ce stade, les administrateurs ouvrent généralement la succursale locale d'une usine de fabrication de vélos et commencent à cacher, masquer et enterrer soigneusement la clé secrète du code de script. Beaucoup de ces options sont non seulement inutiles, mais aussi dangereuses. J'essaierai d'offrir une solution pratique et sûre à ce problème pour python. Et une petite touche sur PowerShell.
Comment ne pas faire
Tout le monde connaît le concept de «script temporaire». Ici, littéralement, seules les données peuvent être rapidement analysées de la base de données et supprimées. Et puis soudain, il s'avère que le script a déjà migré quelque part en production depuis la zone de développement. Et puis des surprises désagréables de la «jetabilité» initiale commencent à émerger.
L'option la plus courante est dans le style de:
db_login = 'john.doe' password = 'password!'
Le problème est qu'ici le mot de passe brille en clair et est assez facilement détecté parmi les dépôts d'anciens scripts par recherche automatique. Une version légèrement plus compliquée suit le chemin de la sécurité à travers l'obscurité, avec le mot de passe stocké sous une forme chiffrée directement dans le code. Dans ce cas, le déchiffrement doit être effectué immédiatement, sinon le client ne pourra pas présenter ce mot de passe côté serveur. Cette méthode permettra d'économiser le maximum d'un look décontracté, mais toute analyse sérieuse du code manuellement vous permettra d'extraire facilement la clé secrète. Le code ci-dessous ne sauvera que de ces "surfeurs d'épaule":
>>> import base64 >>> print base64.b64encode("password") cGFzc3dvcmQ= >>> print base64.b64decode("cGFzc3dvcmQ=") password
Le scénario le plus désagréable est l'utilisation de systèmes de contrôle de version, tels que git, pour ces fichiers contenant des informations sensibles. Même si l'auteur décide de supprimer tous les mots de passe, ils resteront dans l'historique du référentiel. En fait, si vous exécutez un fichier avec des données secrètes dans git, vous pouvez automatiquement les considérer comme compromis et commencer immédiatement la procédure de remplacement de toutes les informations d'identification affectées.
Utilisation du stockage système
Il y a une bibliothèque de
porte-clés sympa. Le principe de fonctionnement de base repose sur le fait que chaque utilisateur du système d'exploitation dispose de son propre stockage crypté, dont l'accès n'est possible qu'après la connexion de l'utilisateur au système. Il est multiplateforme et utilisera le backend pour stocker les mots de passe fournis par le système d'exploitation:
- KDE4 & KDE5 KWallet (dbus requis)
- Freedesktop Secret Service - de nombreux DE, y compris GNOME (nécessite un stockage secret)
- Casier d'identification Windows
- Porte-clés macOS
Vous pouvez également utiliser
des backends alternatifs ou écrire le vôtre, si quelque chose d'étrange est absolument nécessaire.
Comparez la difficulté d'attaque
Lorsque vous stockez le mot de passe directement dans le script, vous avez besoin de :
- Volez le code lui-même (facile)
- Désobfusquez si nécessaire (facile)
Lors de l'utilisation d'un trousseau de clés local, un attaquant doit:- Volez le code lui-même (facile)
- Désobfusquez si nécessaire (facile)
- Pour compromettre la machine locale en se connectant en tant qu'utilisateur attaqué (difficile)
Théoriquement, l'accès au stockage local peut être obtenu par tout programme local exécuté au nom de l'utilisateur actuel, s'il connaît les paramètres d'accès pour le mot de passe secret. Cependant, ce n'est pas un problème, car en cas de compte compromis, un attaquant pourra intercepter toutes les données sensibles. Les autres utilisateurs et leurs logiciels n'auront pas accès au magasin de clés local.
Exemple d'utilisation
import argparse import getpass import keyring def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument("-n", "--newpass", required=False, help="Set new password", action="store_true") arguments = parser.parse_args() return arguments def fake_db_connection():
Sécurité par mot de passe
Une autre fuite de mot de passe secrète courante est l'historique de la ligne de commande. L'utilisation de l'entrée standard n'est pas autorisée ici:
age = input("What is your age? ") print "Your age is: ", age type(age) >>output What is your age? 100 Your age is: 100 type 'int'>
Dans l'exemple ci-dessus, j'ai déjà mentionné la bibliothèque
getpass :
La saisie des données lors de leur utilisation est similaire à l'approche classique * nix lors de la connexion. Les données ne sont ni écrites ni affichées sur aucun écran des journaux système.
Un peu sur Powershell
Pour Powershell, la bonne option consiste à utiliser le casier Windows Credential Locker standard.
Ceci est implémenté par le module
CredentialManager .
Exemple d'utilisation:
Install-Module CredentialManager -force New-StoredCredential -Target $url -Username $ENV:Username -Pass .... Get-StoredCredential -Target ....