
Das Speichern von Passwörtern war schon immer ein Problem. In der klassischen Version haben Sie einen Benutzer, der sich bemüht, das schrecklich geheime „qwerty123“ und das Informationssystem, das den Hash aus diesem Passwort speichert, nicht zu vergessen. Ein gutes System löst auch Hashes sorgfältig, um das Leben von schlechten Menschen zu vergiften, die eine Datenbank mit gehashten Passwörtern stehlen können. Hier ist alles klar. Einige Passwörter werden im Kopf gespeichert, andere in keepass verschlüsselt.
Alles ändert sich, wenn wir eine Person aus dem Schema entfernen, die den Schlüssel vorsichtig von einem Stück Papier eingibt. In der Interaktion zweier Informationssysteme sollte das Passwort in jedem Fall auf der Client-Seite in offener Form für das System gespeichert werden, damit es übertragen und mit dem Referenz-Hash verglichen werden kann. In diesem Stadium öffnen Administratoren normalerweise die lokale Filiale der Fahrradfabrik und beginnen, den geheimen Schlüssel im Skriptcode sorgfältig zu verstecken, zu verschleiern und zu begraben. Viele dieser Optionen sind nicht nur nutzlos, sondern auch gefährlich. Ich werde versuchen, eine bequeme und sichere Lösung für dieses Problem für Python anzubieten. Und ein kleiner Hauch von Powershell.
Wie man es nicht macht
Jeder kennt das Konzept des "temporären Scripting". Hier können buchstäblich nur Daten schnell aus der Datenbank analysiert und gelöscht werden. Und dann stellt sich plötzlich heraus, dass das Skript bereits irgendwo in der Produktion aus der Entwicklungszone migriert ist. Und dann tauchen unangenehme Überraschungen aus der anfänglichen „Verfügbarkeit“ auf.
Die häufigste Option ist im Stil von:
db_login = 'john.doe' password = 'password!'
Das Problem ist, dass hier das Passwort klar leuchtet und durch die automatische Suche leicht unter den Einlagen alter Skripte erkannt werden kann. Eine etwas kompliziertere Version folgt dem Weg der Sicherheit durch Dunkelheit, wobei das Passwort in verschlüsselter Form direkt im Code gespeichert wird. In diesem Fall sollte die Rückentschlüsselung sofort durchgeführt werden, da der Client dieses Kennwort sonst nicht auf der Serverseite anzeigen kann. Diese Methode spart das Maximum eines ungezwungenen Aussehens, aber bei jeder ernsthaften manuellen Analyse des Codes können Sie den geheimen Schlüssel einfach extrahieren. Der folgende Code speichert nur von solchen "Schulter-Surfern":
>>> import base64 >>> print base64.b64encode("password") cGFzc3dvcmQ= >>> print base64.b64decode("cGFzc3dvcmQ=") password
Das unangenehmste Szenario ist die Verwendung von Versionskontrollsystemen wie git für solche Dateien mit vertraulichen Informationen. Selbst wenn der Autor beschließt, alle Passwörter zu löschen, bleiben sie im Verlauf des Repositorys. Wenn Sie eine Datei mit geheimen Daten in git ausführen, können Sie diese automatisch als gefährdet betrachten und sofort mit dem Verfahren zum Ersetzen aller betroffenen Anmeldeinformationen beginnen.
Verwenden des Systemspeichers
Es gibt eine coole
Schlüsselbundbibliothek . Das Grundprinzip des Betriebs basiert auf der Tatsache, dass jeder Benutzer des Betriebssystems über einen eigenen verschlüsselten Speicher verfügt, auf den erst zugegriffen werden kann, nachdem sich der Benutzer beim System angemeldet hat. Es ist plattformübergreifend und verwendet das vom Betriebssystem bereitgestellte Backend zum Speichern von Kennwörtern:
- KDE4 & KDE5 KWallet (dbus erforderlich)
- Freedesktop Secret Service - viele DEs, einschließlich GNOME (erfordert Secretstorage)
- Windows-Anmeldeinformationsschließfach
- macOS Schlüsselbund
Sie können auch
alternative Backends verwenden oder eigene schreiben, wenn absolut etwas Seltsames erforderlich ist.
Vergleichen Sie die Angriffsschwierigkeiten
Wenn Sie das Passwort direkt im Skript speichern, benötigen Sie :
- Stehlen Sie den Code selbst (einfach)
- Bei Bedarf deobfuscieren (einfach)
Bei Verwendung eines lokalen Schlüsselbunds muss ein Angreifer:- Stehlen Sie den Code selbst (einfach)
- Bei Bedarf deobfuscieren (einfach)
- So gefährden Sie den lokalen Computer, indem Sie sich als angegriffener Benutzer anmelden (schwierig)
Theoretisch kann jedes lokale Programm, das im Auftrag des aktuellen Benutzers ausgeführt wird, auf den lokalen Speicher zugreifen, wenn er die Zugriffseinstellungen für das geheime Kennwort kennt. Dies ist jedoch kein Problem, da ein Angreifer im Falle eines kompromittierten Kontos alle vertraulichen Daten abfangen kann. Andere Benutzer und ihre Software haben keinen Zugriff auf den lokalen Keystore.
Anwendungsbeispiel
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():
Passwortsicherheit
Ein weiteres häufiges geheimes Kennwortleck ist der Befehlszeilenverlauf. Die Verwendung von Standardeingaben ist hier nicht zulässig:
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'>
Im obigen Beispiel habe ich bereits die
getpass- Bibliothek erwähnt:
Die Eingabe von Daten bei deren Verwendung ähnelt dem klassischen * nix-Ansatz bei der Anmeldung. Daten werden in keinem System in Systemprotokollen geschrieben oder auf einem Bildschirm angezeigt.
Ein bisschen über Powershell
Für Powershell ist die richtige Option die Verwendung des standardmäßigen Windows Credential Locker.
Dies wird vom
CredentialManager- Modul implementiert.
Anwendungsbeispiel:
Install-Module CredentialManager -force New-StoredCredential -Target $url -Username $ENV:Username -Pass .... Get-StoredCredential -Target ....