Passwort in Shell-Skripten verbergen

23

Wie kann ich ein Passwort in Shell-Skripten verbergen? Es gibt eine Reihe von Skripten, die auf die Datenbank zugreifen. Wenn wir das Skript öffnen, kennen auch andere den Benutzernamen und das Passwort. Also, wenn jemand weiß, wie man sich versteckt, lass es mich wissen.

Ich habe eine Möglichkeit: Platzieren Sie das Kennwort in einer Datei und machen Sie die Datei als versteckt und niemand wird auf die Datei zugreifen (ändern Sie die Berechtigungen und verwenden Sie die Datei im Skript, während Sie auf die Datenbank zugreifen).

Arun
quelle

Antworten:

35

Erstens ist es , wie bereits von mehreren Personen erwähnt, unerlässlich, die Anmeldeinformationen vom Skript zu trennen. (Zusätzlich zur erhöhten Sicherheit bedeutet dies auch, dass Sie dasselbe Skript für mehrere Systeme mit unterschiedlichen Anmeldeinformationen wiederverwenden können.)

Zweitens sollten Sie nicht nur die Sicherheit der Anmeldeinformationen berücksichtigen, sondern auch die Auswirkungen, wenn diese Anmeldeinformationen kompromittiert werden. Sie sollten nicht nur ein Kennwort für den gesamten Zugriff auf die Datenbank haben, sondern unterschiedliche Anmeldeinformationen mit unterschiedlichen Zugriffsebenen. Sie könnten zum Beispiel einen DB-Benutzer haben, der die Möglichkeit hat, eine Suche in der Datenbank durchzuführen - dieser Benutzer sollte nur Lesezugriff haben. Ein anderer Benutzer hat möglicherweise die Berechtigung, neue Datensätze einzufügen, diese jedoch nicht zu löschen. Ein dritter kann berechtigt sein, Datensätze zu löschen.

Zusätzlich zur Einschränkung der Berechtigungen für jedes Konto sollten Sie auch die Verwendungsmöglichkeiten der einzelnen Konten einschränken. Beispielsweise darf das von Ihrem Webserver verwendete Konto keine Verbindung von einer anderen IP-Adresse als der des Webservers herstellen. Ein Konto mit vollständigen Root-Berechtigungen für die Datenbank sollte in der Tat in Bezug auf den Verbindungsaufbau stark eingeschränkt sein und nur interaktiv verwendet werden. Ziehen Sie auch in Betracht, gespeicherte Prozeduren in der Datenbank zu verwenden, um genau einzuschränken, was von jedem Konto ausgeführt werden kann.

Diese Einschränkungen müssen auf der DB-Server-Seite des Systems implementiert werden, damit die Einschränkungen auch bei einer Beeinträchtigung der Client-Seite nicht geändert werden können. (Und natürlich muss der DB-Server zusätzlich zur DB-Konfiguration mit Firewalls usw. geschützt werden ...)

Bei einem DB-Konto, das nur über eingeschränkten Lesezugriff und nur über eine bestimmte IP-Adresse verfügt, sind möglicherweise keine weiteren Anmeldeinformationen erforderlich, abhängig von der Vertraulichkeit der Daten und der Sicherheit des Hosts, auf dem das Skript ausgeführt wird läuft ab. Ein Beispiel kann ein Suchformular auf Ihrer Website sein, das mit einem Benutzer ausgeführt werden kann, der nur eine gespeicherte Prozedur verwenden darf, die nur die Informationen extrahiert, die auf der Webseite angezeigt werden. In diesem Fall bietet das Hinzufügen eines Kennworts keine zusätzliche Sicherheit, da diese Informationen bereits öffentlich sind und der Benutzer nicht auf andere Daten zugreifen kann, die vertraulicher sind.

Stellen Sie außerdem sicher, dass die Verbindung zur Datenbank über TLS hergestellt wird. Andernfalls kann jeder, der im Netzwerk empfangsbereit ist, Ihre Anmeldeinformationen abrufen.

Drittens überlegen Sie, welche Art von Anmeldeinformationen verwendet werden sollen. Passwörter sind nur eine Form und nicht die sicherste. Sie könnten stattdessen eine Form eines öffentlichen / privaten Schlüsselpaars oder AD / PAM oder dergleichen verwenden.

Viertens betrachten Sie die Bedingungen, unter denen das Skript ausgeführt wird:

Wenn es interaktiv ausgeführt wird, sollten Sie das Kennwort oder das Kennwort für den privaten Schlüssel oder den privaten Schlüssel eingeben oder mit einem gültigen Kerberos-Ticket angemeldet sein, wenn Sie es ausführen. Mit anderen Worten, das Skript sollte sein Kennwort erhalten Anmeldeinformationen direkt von Ihnen zum Zeitpunkt der Ausführung, anstatt sie aus einer Datei zu lesen.

Wenn es von einem Webserver ausgeführt wird, sollten Sie die Anmeldeinformationen zum Zeitpunkt des Starts des Webservers einrichten. Ein gutes Beispiel hierfür sind SSL-Zertifikate - sie haben ein öffentliches Zertifikat und einen privaten Schlüssel, und der private Schlüssel hat ein Passwort. Sie können den privaten Schlüssel auf dem Webserver speichern, müssen jedoch das Kennwort eingeben, wenn Sie Apache starten. Sie können auch die Anmeldeinformationen für eine bestimmte Hardware, z. B. eine physische Karte oder ein HSM, haben, die nach dem Start des Servers entfernt oder gesperrt werden können. (Der Nachteil dieser Methode ist natürlich, dass der Server nicht von selbst neu gestartet werden kann, wenn etwas passiert. Ich würde dies dem Risiko vorziehen, dass mein System kompromittiert wird, aber Ihre Laufleistung kann variieren ...)

Wenn das Skript von Cron ausgeführt wird, ist dies der schwierige Teil. Sie möchten nicht, dass die Anmeldeinformationen irgendwo auf Ihrem System herumliegen, wo jemand darauf zugreifen kann - aber Sie möchten, dass sie herumliegen, damit Ihr Skript darauf zugreifen kann, oder? Na ja, nicht ganz richtig. Überlegen Sie genau, was das Skript tut. Welche Berechtigungen benötigt es für die Datenbank? Kann es eingeschränkt werden, damit es egal ist, ob die falsche Person eine Verbindung zu diesen Berechtigungen herstellt? Können Sie das Skript stattdessen direkt auf dem DB-Server ausführen, auf den kein anderer Zugriff hat, anstatt von dem Server, der andere Benutzer hat? Wenn aus irgendeinem Grund , dass ich nicht denken kann, absolut Sie müssen das Skript läuft auf einem unsicheren Server haben , und es muss in der Lage sein, etwas Gefährliches / Zerstörerisches zu tun ... Jetzt ist ein guter Zeitpunkt, Ihre Architektur zu überdenken.

Fünftens sollten Sie, wenn Sie die Sicherheit Ihrer Datenbank schätzen, diese Skripts nicht auf Servern ausführen, auf die andere Personen Zugriff haben. Wenn jemand auf dem System angemeldet, dann sie werden die Möglichkeit an , Ihre Anmeldeinformationen erhalten haben. Beispielsweise besteht bei einem Webserver mit einem SSL-Zertifikat zumindest eine theoretische Möglichkeit, dass sich jemand als Root anmelden und auf den Speicherbereich des httpd-Prozesses zugreifen und die Anmeldeinformationen extrahieren kann. In letzter Zeit gab es mindestens einen Exploit, bei dem dies über SSL möglich war, ohne dass der Angreifer angemeldet sein musste.

Erwägen Sie auch die Verwendung von SELinux oder Apparmor oder was auch immer für Ihr System verfügbar ist, um einzuschränken, welche Benutzer was tun können. Sie ermöglichen es Ihnen, Benutzern nicht einmal zu erlauben, eine Verbindung zur Datenbank herzustellen, selbst wenn sie Zugriff auf die Anmeldeinformationen erhalten.

Wenn Ihnen das alles übertrieben vorkommt und Sie es sich nicht leisten können oder keine Zeit dafür haben - dann sollten Sie meiner (arroganten und elitären) Meinung nach nichts Wichtiges oder Sensibles in Ihrer Datenbank speichern. Und wenn Sie nichts Wichtiges oder Sensibles speichern, ist es auch nicht wichtig, wo Sie Ihre Anmeldeinformationen speichern - in welchem ​​Fall sollten Sie überhaupt ein Passwort verwenden?

Schließlich , wenn Sie absolut nicht irgendeine Art von Anmeldeinformationen vermeiden speichern, können Sie die Anmeldeinformationen schreibgeschützt und von Wurzel und Stamm im Besitz Eigentum auf einen sehr vorübergehend gewähren könnte , wenn dies durch ein Skript dazu aufgefordert wird (weil Ihr Skript sollte nicht sein Als root ausführen, es sei denn, dies ist unbedingt erforderlich, und eine Verbindung zu einer Datenbank ist nicht erforderlich. Aber es ist immer noch keine gute Idee.

Jenny D
quelle
9
Überhaupt nicht arrogant und elitär. Oder ich auch. "Wie kann ich meinen Schmuck für den Fall schützen, dass ein Einbrecher einbricht?" "Legen Sie es in einen Safe, der an Ort und Stelle verschraubt / verschweißt ist." "Das ist zu viel Mühe, ich hole einfach einen tragbaren Safe und hänge den Schlüssel an einen Haken." "Dann brauchst du keinen Safe." Überaus vernünftiger Rat.
Wildcard
12

Erstens sollten Sie alle Anstrengungen unternehmen, um zu verhindern, dass Sie in einem Skript oder neben einem Skript ein Kennwort speichern müssen, wenn Sie auf irgendeine Weise Änderungen vornehmen können. Die Antwort von Jenny D enthält viele gute Ratschläge in dieser Hinsicht.

Ansonsten ist Ihre Idee, das Kennwort in einer separaten Datei mit eingeschränkten Berechtigungen abzulegen, so ziemlich das Gegenteil. Sie können diese Datei beispielsweise über das Hauptskript beziehen:

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

Sie können auch die Berechtigungen des Hauptskripts einschränken, sodass nur autorisierte Personen es ausführen können. Es ist jedoch wahrscheinlich besser, das vorgeschlagene Kennwort einzuhalten und nur das Kennwort selbst in einer eingeschränkten Datei zu speichern. Auf diese Weise können Sie den Code selbst überprüfen (ohne vertrauliche Geheimnisse), die Versionskontrolle und das Kopieren des Skripts vereinfachen.

Celada
quelle
@BasileStarynkevitch ah aber ich sehe, dass es auch heißt " /usr/local/etckann ein symbolischer Link zu sein /etc/local". Das habe ich vermisst. Also hast du auch Recht, aber es ist ein Mai, also ist es optional. Aber ja, es macht nicht viel aus, und persönliche Vorlieben.
Celada
1
Abgesehen davon, dass ich ein Backup mache, /etc/ aber nicht /usr/local/ (von dem ich annehme , dass es nach einem Festplattencrash wiederhergestellt werden kann)
Basile Starynkevitch
fair point about backups
Celada
3

Andere Antworten haben das Wie angesprochen , aber ich werde überlegen, ob . Abhängig von der Art der Datenbank, mit der Ihre Benutzer eine Verbindung herstellen, verfügen Sie möglicherweise bereits über einen geeigneten Mechanismus, der von diesen Client-Programmen bereits verwendet wird. In diesem Fall sollten Sie sie unbedingt verwenden (ich denke an ~/.mysqlrcoder ~/.pgpass).

Wenn Sie mehreren Benutzern den Zugriff auf die Datenbank ermöglichen, um bestimmte Abfragen mit einem gemeinsam genutzten Konto durchzuführen, sollten Sie dies wahrscheinlich nicht tun. Stellen Sie stattdessen sicher, dass sie Konten in der Datenbank haben und dass diese Konten nicht mehr Berechtigungen haben, als sie benötigen (lesen Sie wahrscheinlich viel davon und haben Sie nur sehr geringen Schreibzugriff). Wenn sie bestimmte Abfragen für bestimmte Tabellen durchführen müssen, auf die sie sonst nicht zugreifen können, stellen Sie gespeicherte Prozeduren bereit SECURTY DEFINER, damit sie darauf zugreifen können .

Falls keine der oben vermeidet Sie speichern Anmeldeinformationen benötigen, dann lesen Sie die anderen Antworten hier.

Toby Speight
quelle
1

Ihre Idee, das Passwort an einem unzugänglichen Ort zu verstecken, ist unter Umständen in Ordnung.

Wenn die Informationen getrennt sind, bedeutet dies, dass eine einfache Bearbeitung der Datei, z. B. während einer Codeüberprüfung mit einem Kollegen, diese nicht anzeigen wird. Beachten Sie jedoch, dass jeder, der Zugriff auf Ihr Konto hat, eine solche Datei leicht finden kann. Ich habe ~/.sshfür solche Zwecke ein Unterverzeichnis von verwendet, aus dem einfachen Grund, der sich sshbeschwert, wenn die Zugriffsrechte für ~/.sshnicht ausreichend eingeschränkt sind.

Sie können jedoch auch andere Maßnahmen ergreifen, um ein derartiges Erkennen von Benutzernamen und / oder Passwörtern zu verhindern.

Verschleiern : Wenn Sie den Benutzernamen oder das Passwort nicht lesen jemand wollen , während Sie ein Skript bearbeiten Sie es im Text setzen können , aber nicht im Klartext, sondern verschleiert. Wenn die verschleierte Version lang genug ist, um zu verhindern, dass jemand sie auswendig kann, kann sie nicht erkannt werden, auch wenn die Entschlüsselungsmethode und der Schlüssel in Sichtweite sind. Dies würde natürlich immer noch trivial umgangen, wenn jemand Zugriff auf Ihr Konto hat.

GPG verwenden :

Etwas besser, aber immer noch nicht vollständig gegen Angriffe des Root-Benutzers auf Ihr System geschützt, ist die Verschlüsselung von Benutzernamen / Passwort-Paaren in einer gpgöffentlich zugänglichen Datei, und das Skript ruft den Inhalt der Datei ab (möglicherweise werden Sie zur Eingabe eines Passworts aufgefordert, wenn nicht zwischengespeichert / abgelaufen). Ich verwende eine ggp-Karte, damit kein Zugriff möglich ist, wenn ich meinen Laptop herumlasse, aber die Karte heraus ziehe, auch wenn die PIN noch im Cache wäre. Zumindest wenn ich das Ding 20 mal in ein paar Minuten laufen lasse muss ich den Pin nur einmal bereitstellen.

Sicherheit scheint immer umgekehrt mit Bequemlichkeit (Einrichten und Verwenden) verbunden zu sein.

Anthon
quelle
0

Es gibt eine Möglichkeit, Kennwörter in einem Bash-Skript zu speichern, aber Sie müssen das Skript verschlüsseln und verschleiern, damit niemand es lesen oder einen Debugger ausführen kann, um genau zu sehen, was es tut. Um ein Bash / Shell-Skript zu verschlüsseln und zu verschleiern und tatsächlich ausführbar zu machen, kopieren Sie es und fügen es hier ein:

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

Auf der obigen Seite müssen Sie lediglich Ihr Skript einreichen (Sie können zur Beruhigung zuerst ein Beispielskript einreichen). Eine zip-Datei wird für Sie generiert. Klicken Sie mit der rechten Maustaste auf den Download-Link und kopieren Sie die angegebene URL. Gehen Sie dann zu Ihrer UNIX-Box und führen Sie die folgenden Schritte aus.

Installation:

  1. wget link-to-the-zip-datei

  2. Entpacken Sie die neu heruntergeladene Zip-Datei

  3. cd / tmp / KingLazySHIELD

  4. ./install.sh / var / tmp / KINGLAZY / SHIELDX- (Ihr-Skriptname) / home / (Ihr-Benutzername) -force

Mit dem obigen Installationsbefehl können Sie Folgendes ausführen:

  1. Es installiert die verschlüsselte Version Ihres Skripts im Verzeichnis / var / tmp / KINGLAZY / SHIELDX- (Ihr-Skript-Name).

  2. Dadurch wird ein Link zu diesem verschlüsselten Skript in das Verzeichnis eingefügt, das Sie anstelle von / home / (Ihr-Benutzername) angegeben haben. Auf diese Weise können Sie problemlos auf das Skript zugreifen, ohne den absoluten Pfad eingeben zu müssen.

  3. Stellt sicher, dass NIEMAND das Skript ändern kann - Jeder Versuch, das verschlüsselte Skript zu ändern, macht es funktionsunfähig ... bis diese Versuche gestoppt oder entfernt werden. Es kann sogar so konfiguriert werden, dass Sie benachrichtigt werden, wenn jemand versucht, etwas anderes mit dem Skript zu tun, als es auszuführen ... z. B. Hacking- oder Änderungsversuche.

  4. Stellt sicher, dass NIEMAND Kopien davon anfertigen kann. Niemand kann Ihr Skript an einen abgelegenen Ort kopieren und versuchen, damit herumzudrehen, um zu sehen, wie es funktioniert. Alle Kopien des Skripts müssen mit dem ursprünglichen Speicherort verknüpft sein, den Sie bei der Installation angegeben haben (Schritt 4).

HINWEIS:

Ich glaube nicht, dass dies für interaktive Skripte funktioniert, die den Benutzer zu einer Antwort auffordern. Die Werte sollten fest im Skript codiert sein. Die Verschlüsselung stellt sicher, dass niemand diese Werte tatsächlich sehen kann, sodass Sie sich darüber keine Gedanken machen müssen.

AncientMinds
quelle
0

Eine andere Lösung, ohne Rücksicht auf die Sicherheit (ich halte es auch für besser, die Anmeldeinformationen in einer anderen Datei oder in einer Datenbank zu speichern), besteht darin, das Kennwort mit gpg zu verschlüsseln und es in das Skript einzufügen.

Ich verwende ein passwortloses GPG-Schlüsselpaar, das ich in einem USB verwahre. (Hinweis: Wenn Sie dieses Schlüsselpaar exportieren, verwenden Sie --armor nicht, exportieren Sie sie im Binärformat.)

Zuerst verschlüsseln Sie Ihr Passwort:

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

Das gpg-verschlüsselte Passwort wird dann in der Standardausgabe ausgedruckt. Kopieren Sie die gesamte Nachricht und fügen Sie Folgendes zum Skript hinzu:

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)

Auf diese weise kann das passwort nur entschlüsselt werden, wenn der usb im system eingebunden ist. Natürlich können Sie auch die Schlüssel in das System importieren (weniger sicher oder überhaupt keine Sicherheit) oder Sie können den privaten Schlüssel mit einem Passwort schützen (so dass er nicht automatisiert werden kann).

Juanu
quelle
-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
quelle
3
Ich habe Ihren Code eingerückt, vielleicht können Sie erklären, was Sie versuchen zu tun?
Archemar
-6

Ich glaube nicht, dass Sie das Passwort jemals speichern sollten. Ich kann mir keinen guten Grund dafür vorstellen. Stattdessen sollten Sie einen gesalzenen Hash dieses Kennworts speichern - eine Zeichenfolge, die von einer Funktion zuverlässig erzeugt wird, wenn das ursprüngliche Kennwort als Eingabe übergeben wird, jedoch niemals das Kennwort .

mikeserv
quelle
5
Ich bin unklar, wie dies das Problem lösen wird, dass a) eine Verbindung zu einem Dienst hergestellt werden kann, für den ein Kennwort erforderlich ist, und b) Benutzer das Skript anzeigen und somit die Authentifizierungsdetails ermitteln können, ob es sich um Kennwörter handelt oder nicht
Jenny D
1
Sie behaupten, meine Antwort zu kennen, bevor ich sie geschrieben habe.
Jenny D
1
Ich habe jetzt meine Antwort geschrieben. Was ich versucht habe, von Ihnen zu erfahren, war zum Teil mein fünfter Punkt: Sobald die Anmeldeinformationen im Speicher gespeichert sind, sind sie für einen Angreifer mit Zugriff auf den Server nicht mehr vollständig sicher. Auch, dass Ihre knappe Antwort nicht sehr hilfreich war, obwohl nicht falsch. Ich denke darüber nach, das nächste Mal darauf hinzuweisen, wenn sich jemand beschwert, dass wir bei ServerFault nicht so nett sind wie die Leute bei Unix / Linux :-)
Jenny D
2
@JennyD - sobald das Guthaben gespeichert ist, muss es auf keinen Fall dort bleiben - und das ist ein sehr guter Grund, stattdessen ohnehin mit Hashes umzugehen. Trotzdem werde ich die Höflichkeitsstandards der Community gerne als allgemeines Vorbild darstellen - ich bin in der Tat sehr bekannt für diese Eigenschaft.
mikeserv
4
Nach Ihrer großen Diskussion möchte ich nur erwähnen, falls es ein Missverständnis gibt, dass nicht Jenny, sondern ich selbst abstimmte. Und der Grund war nicht eine Meinung darüber, ob es eine gute Idee ist, ein Zertifikat und einen privaten Schlüssel oder ein interaktiv eingegebenes Passwort zu verwenden oder das zu tun, was das OP wollte oder was auch immer. Das lag daran, dass die Antwort in der jetzigen Form falsch ist: Das Speichern eines gesalzenen Hashes des Passworts als Client-Berechtigungsnachweis ist keine Sache: Gesalzener Hashes ist eine Sache, die Sie am Ende der Verbindung behalten, die die Authentifizierung überprüft, nicht auf der Seite, die es einreicht.
Celada