Passwortübergabe auf der Kommandozeile möglichst sicher machen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Hallo Leute,

ich benötige für ein Programm, welches gerade entsteht, die Möglichkeit ein Kennwort beim Programmaufruf zu übergeben.
Ich bin mir bewusst das dieses ein paar Risiken mit sich bringt, komme jedoch aufgrund der externen Anforderungen nicht drum herum dieses genau so zu implementieren. Jedoch würde ich es gerne trotzdem möglichst sicher machen, das das Klartextkennwort nicht mit in der Prozessliste auftaucht, z.B.
Als Beispiel nehme ich hier mal den MySQL Client; auch hier kann man ja mit '-pKENNWORT' ein Kennwort auf der Kommandozeile übergeben; dennoch wird dieses in der Prozessliste nur verdeckt angezeigt:

Code: Alles auswählen

root     18625  0.0  0.1  45428  9328 pts/1    S+   11:21   0:00 mysql -uusername -px xxxxxxxxx
Ich verwende zur Abfrage der übrigen Parameter argparse; der Doku konnte ich solch eine Funktion jedoch nicht entnehmen.

(Wie) kriege ich so etwas ähnliches mit Python hin?

LG
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@Judge: sicherer und einfacher ist die Übergabe per Konfigurationsdatei oder Environmentvariable.
BlackJack

Von der Standardeingabe lesen und beim starten mit ``echo`` rein pipen wäre auch noch eine Möglichkeit.
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Sirius3 hat geschrieben:@Judge: sicherer und einfacher ist die Übergabe per Konfigurationsdatei oder Environmentvariable.
Hi Sirius3,
ja, aber wie gesagt: Ist nicht gewünscht. Es soll per Parameter übergebbar sein; genau wie beim mysql client.
BlackJack hat geschrieben:Von der Standardeingabe lesen und beim starten mit ``echo`` rein pipen wäre auch noch eine Möglichkeit.
Das würde ja zu einer Art interaktivem Passwort-Promt führen, oder? Oder man müsste da irgendwelchen Shell-Voodoo, wie "< echo "MeinKennwort" o.ä. anhängen ...
Wäre beides nicht gewünscht. Es soll ein Kommandozeilenparameter sein. Zudem soll das Script Batch-weise, also: Ohne Benutzerinteraktion, als Teil einer Scriptkette ausführbar sein. Das schließt eine interaktive Abfrage ja leider aus.

Ich habe auch schon überlegt, ob man da irgendeinen uneleganten Move macht, das sich das Script unmittelbar selbst nochmal aufruft, nur das es das Klartextpasswort in eine Temp-Datei schreibt, die es anschließend wieder löscht und halt mit '-p xxxxxx' oder so, in der Prozessliste auftaucht. Aber wie gesagt: Ziemlich aufwändig und wenig elegant ...
Ich hoffe auf eine bessere Idee.
Sirius3
User
Beiträge: 18335
Registriert: Sonntag 21. Oktober 2012, 17:20

@Judge: das mit echo ist kein Shell-Voodoo sondern ein ganz normaler Weg, den viele Tools benutzen.

Was Du erreichen willst, ist Voodoo, da die üblichen Methoden aus irgendwelchen Gründen nicht zu gehen scheinen. Da wäre abzufragen, warum es so eine Anforderung gibt.

Als nicht empfehlenswerten Workaround wandelt dieses Bash-Skript die Parameter in eine Environment-Variable um:

Code: Alles auswählen

#!/bin/bash
script_dir=$(dirname "$0")
PARAMS=$(printf '%q ' "$@") exec "${script_dir}"/your_script.py
Hat den Nachteil, wie auch alle anderen "Lösungen" mit Parametern, dass das Passwort kurzzeitig in der Prozessliste auftaucht.
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Für Dich und mich nicht - Für den Enduser, die sich mit der Shell nicht sonderlich auskennen, ist sowas aber Voodoo. Die Anforderung ist, das Kennwort als Kommandozeilenoption übergeben zu können. Scheinbar soll das dadurch auch für Shell-Legastheniker bedienbar bleiben oder sich leichter in bestehende Scripte einbinden lassen.

Das das Kennwort für die kurze Zeit, in der die "Umwandlung" passiert, in der Prozessliste auftaucht ist klar; aber wie Du schon sagst: Das geht halt nicht anders und wird bei jeder Lösung so sein. Aber das ist ja schon eine deutliche Verbesserung, im Vergleich zur Anzeige über die komplette Laufzeit des Programmes hinweg.

Auf die Anforderung habe ich keinen Einfluss; die ist nunmal so, wie sie ist. Ich habe meine Kritik zu diesem Punkt dem Kunden gegenüber geäußert und er wünscht es trotzdem so. Ich gehe dann nicht gerne auf den Kunden zu und diskutiere ihm meine Ansicht schön, wenn seine irgendwie vertretbar umzusetzen ist. Einzige Möglichkeit das zu ändern wäre, wenn ich ihm sage "das geht mit Python nicht". Es wäre nun aber extrem peinlich, wenn jemand anderes, jetzt oder später, eine entsprechende Lösung präsentieren könnte. Daher versuche ich hier erstmal mein Glück. Unabhängig davon was "üblich" oder "vernünftig" ist; was und wie mit Python möglich ist, ist die Frage.

Wenn das also mit Python nicht möglich sein sollte, würde ich mir die Frage stellen "wie funktioniert es denn beim mysql client" / "was macht der anders"? Klar - das ist ein Binärprogramm; vermutlich in C o.ä. geschrieben. Aber letzten Endes können diese doch auch nur Funktionen des Systems nutzen, die diese auch anbieten. Python müsste sich in dem Punkt doch derselben Methoden bedienen können, oder nicht?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

nezzcarth
User
Beiträge: 1790
Registriert: Samstag 16. April 2011, 12:47

Als Variante von BlackJacks Vorschlag mit der Echo Pipe:
Man könnte die Passwortübergabe auch per here-string realisieren (./skript.py <<< passwort). Ist natürlich kein Parameter, aber von der Schreibweise ja noch halbwegs ähnlich...
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

MySQL macht vermutlich eine normale Parameterübergabe und ändert anschließend die Prozessbezeichnung so, dass das Passwort nicht angezeigt wird. Das kannst du faken, indem du `sys.argv` kopierst und den Wert hinter deiner Option für das Passwort unkenntlich machst. Anschließend ein ``' '.join(args)`` (wenn `args` die Kopie ist) und dies als neuen Prozessnamen verwenden.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Judge:
Und wie siehts mit der Angabe einer Passwortdatei als Parameter aus? (`command --passwordfile=/secret_dont_read`) Ist das auch "verboten"? Die Datei selbst kannst Du mit Permissions absichern.
Benutzeravatar
Judge
User
Beiträge: 129
Registriert: Mittwoch 13. Juni 2012, 22:27
Wohnort: Ratingen
Kontaktdaten:

Moin, sorry das ich jetzt erst wieder auf dieses Thema zurückkomme.
'setproctitle' tut zu 100% perfekt was ich wollte; klappt wunderbar. Vor allem verlangt diese Lösung 0 mitdenken vom Anwender und ist ohne irgendwas zu beachten einfach "da".

Vielen Dank aber auch an alle anderen für die anderen Lösungen.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Judge:
Die Warnhinweise beim mysql-client bzgl. dieses Vorgehens hast Du hoffentlich verstanden und auch dem Kunden gespiegelt:
Use a -pyour_pass or --password=your_pass option on the command line. For example:

shell> mysql -u francis -pfrank db_name

This is convenient but insecure. On some systems, your password becomes visible to system status programs such as ps that may be invoked by other users to display command lines. MySQL clients typically overwrite the command-line password argument with zeros during their initialization sequence. However, there is still a brief interval during which the value is visible. Also, on some systems this overwriting strategy is ineffective and the password remains visible to ps. (SystemV Unix systems and perhaps others are subject to this problem.)

If your operating environment is set up to display your current command in the title bar of your terminal window, the password remains visible as long as the command is running, even if the command has scrolled out of view in the window content area.
Übrigens ist `echo` bei fast allen modernen Shells ein Builtin, d.h. die Form der Passwortübergabe über STDIN würde nicht das Passwort in den Prozessnamen leaken:[codebox=bash file=Unbenannt.bsh]echo "TopSecret" | yourscript.py[/code]

Hier mal ein simples Skript, welches sich wahlweise interaktiv oder über STDIN-piping (z.B. mit echo, siehe oben) das Passwort holt (`getpass` kommt aus der Pythondoku):

Code: Alles auswählen

#!/usr/bin/env python

import termios, sys

def getpass(prompt="Password: "):
    fd = sys.stdin.fileno()
    old = termios.tcgetattr(fd)
    new = termios.tcgetattr(fd)
    new[3] = new[3] & ~termios.ECHO          # lflags
    try:
        termios.tcsetattr(fd, termios.TCSADRAIN, new)
        passwd = raw_input(prompt)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old)
    return passwd


if sys.stdin.isatty():
    pw = getpass()
    print
else:
    pw = raw_input()

print 'pw:', pw
Das sollte sicherer sein, als was Du mit Ändern des Prozessnamen gebaut hast.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

jerch hat geschrieben:Übrigens ist `echo` bei fast allen modernen Shells ein Builtin, d.h. die Form der Passwortübergabe über STDIN würde nicht das Passwort in den Prozessnamen lecken:[codebox=bash file=Unbenannt.bsh]echo "TopSecret" | yourscript.py[/code]
Das Passwort ist dann aber trotzdem noch in der History der Shell. Ein Angreifer der Prozessnamen auslesen kann, sollte die History auch lesen können.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@DasIch:
Das geht aber nur als der gleiche Benutzer oder mit entsprechend höheren Rechten, während die Prozessnamesliste vom Kernel in die Welt posaunt wird.
Antworten