zsh seltsames Verhalten mit sudo --stdin und Passwort mit zufälligen Zeichen

zsh seltsames Verhalten mit sudo --stdin und Passwort mit zufälligen Zeichen

Dies ist ein Beitrag, der nicht so beginnt, wie man es erwarten oder jeden Tag sehen würde. Hier ist mein Root-Passwort: :4\g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
Schwer zu merken, oder? Nun, das ist nicht das Problem. Und bevor Sie mich anschreien: ja, ich habe es geändert. Ich habe jetzt einen dummy_rootBenutzer mit diesem Passwort für Tests.

Kurz zusammengefasst

Ich habe zsh kaputt gemacht, indem ich dieses Passwort an sudo auf stdin übergeben habe

(Sehr) lange Version

Hier ist also, was falsch ist: Ich verwende sudomit dem targetpwFlag, was bedeutet, dass das von sudo abgefragte Passwort das Passwort des Zielbenutzers ist, nicht meines. Ich verwende den passPasswort-Manager (Website) für alles, einschließlich des Root-Passworts aller meiner Computer/Server. Aus offensichtlichen Sicherheitsgründen wird dieses Passwort zufällig von pass mit 128 Zeichen generiert (warum auch nicht). Da ich ein fauler Mensch bin (ich bin sicher, Sie sind das auch), möchte ich den folgenden Alias ​​verwenden:

alias sudo='pass mydomain.tld/hostname/users/root/password | sudo --stdin'

Für diejenigen unter Ihnen, die mit pass nicht vertraut sind: Es verschlüsselt im Grunde Passwörter in einem Verzeichnisbaum mit GnuPG, und beim Aufruf pass directory/subdirectory/passwordwird das Passwort entschlüsselt und auf stdout ausgegeben (Verzeichnisse sind natürlich optional, Sie können alles ungeordnet im Stammverzeichnis speichern, das wird jedoch nicht empfohlen). Das Ziel des Alias ​​ist es, dies nicht zigmal am Tag tun zu müssen:

$ pass --clip root_password #Copy root password to clipboard 
$ sudo command
[sudo] password for root: paste
#command output (if the password is right of course)

Beim Testen des Alias-Befehls passiert Folgendes:

$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$

Hier %ist das Zeichen farblich invertiert: Mein Terminal ist weißer Text auf schwarzem Hintergrund, das %ist schwarz auf weißem Hintergrund, irgendwie weiß hervorgehoben, und wird nach der Passwortentschlüsselung durch pass gedruckt. Zwischen dem Drucken von [sudo] password for root:und dem Drucken von diesem %fragt GPG nach meiner privaten Schlüsselpassphrase. Das invertierte Prozentzeichen ist mir schon einmal aufgefallen, und da und wann ich es gesehen habe, glaube ich, dass es gedruckt werden soll EOF(Vorsicht, ich bin mir da überhaupt nicht sicher, eine Methode zum Drucken von diesem finden Sie am Ende des Beitrags %). Beachten Sie, dass ich nach diesem seltsamen Zeichen nicht root bin, sondern echo $?zurückgibt 0...

Also habe ich die Ausgabe per Hexdump verarbeitet, pass root_passwordum zu sehen, ob ich mehr Informationen über diesen Charakter bekommen kann. Hier ist das Ergebnis:

$ pass root_password
:4\?g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
$ pass root_password | hexdump -C
00000000  3a 34 5c 3f 67 26 38 6e  3a 36 5f 46 5b 60 39 54  |:4\?g&8n:6_F[`9T|
00000010  6f 75 63 38 4c 73 2b 4c  27 38 29 3e 36 21 33 2c  |ouc8Ls+L'8)>6!3,|
00000020  6e 4e 6d 55 7a 52 26 55  62 7e 77 37 4e 54 64 27  |nNmUzR&Ub~w7NTd'|
00000030  5e 4c 62 30 5d 60 30 60  2e 22 75 3e 74 50 5c 3e  |^Lb0]`0`."u>tP\>|
00000040  58 41 73 70 4d 4c 54 74  21 40 7d 3d 46 36 43 50  |XAspMLTt!@}=F6CP|
00000050  29 4e 73 53 4d 59 59 37  2a 78 6d 27 41 21 37 60  |)NsSMYY7*xm'A!7`|
00000060  21 6e 27 74 6d 41 61 47  57 6f 42 68 53 7c 75 34  |!n'tmAaGWoBhS|u4|
00000070  7b 6b 24 2a 76 2f 6f 7c  27 25 29 6d 62 58 4d 77  |{k$*v/o|'%)mbXMw|
00000080  0a                                                |.|
00000081

0aist NLgemäß man ascii. Sie können hier feststellen, dass das %Zeichen hier nicht steht und dass das von sudo benötigte Zeilenumbruchzeichen (siehe man sudo) hier steht.

Aber warten Sie, jetzt beginnt der Spaß: Wenn ich den Befehl in einem frisch gestarteten Terminator-Fenster oder TTY zweimal ausführe, passiert Folgendes:

$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$

Und ab da scheint zsh kaputt zu sein. Es scheint, als wolle es die Ausgabe des ersten Befehls ausführen, aber nur sudodie des zweiten Befehls. Hier sind einige Beispiele mit dieser „kaputten“ Shell:

$ echo testpw | sudo --stdin --shell
zsh: command not found: testpw
$ echo testpw | cat
testpw
$ echo testpw | wc --bytes
11
$ echo anothertestpw | sudo --stdin --shell
zsh: command not found: anothertestpw
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$ exec zsh
$ echo testpw | sudo --stdin --shell
zsh: command not found:testpw

Was ist hier los? Wie gezeigt behebt sogar das Ersetzen der Zsh-Instanz durch eine andere ( exec zsh) das Problem nicht. Was ist hier wirklich kaputt? Pass, Zsh oder Sudo?

Machen wir also weiter, testen wir weiter, führen wir einen weiteren Hexdump in einem neuen Terminalfenster durch (weil ich offensichtlich nicht weiß, wie ich zsh wieder in seinen „normalen“ Zustand versetze):

$ pass root_password | sudo --stdin --shell 2>&1 | hexdump -C
00000000  5b 73 75 64 6f 5d 20 70  61 73 73 77 6f 72 64 20  |[sudo] password |
00000010  66 6f 72 20 72 6f 6f 74  3a 20                    |for root: |
0000001a
$

Wo ist dieses Prozentzeichen hin? Keine Ahnung. Es ist einfach nicht hier und ich bin immer noch kein Root, aber die Shell ist jetzt in ihrem defekten Zustand (ich weiß definitiv nicht, wie ich diesen „defekten Zustand“ richtig benennen soll). Wenn ich den pass root_password | sudo --stdin --shellBefehl nach diesem ausführe, wird dieselbe Fehlermeldung wie zuvor ausgegeben. Es ist zu beachten, dass auf einem TTY und am Terminator alles gleich ist, sogar dieses böse %Zeichen.

Hier sind alle Informationen, die mir einfallen und die jemand brauchen könnte, um mir zu helfen. Ich verwende Arch Linux und alle erwähnten Pakete sind auf dem aktuellen Stand (16. oder 15.04.2017, je nachdem, wo auf der Welt Sie sich befinden, derzeit 4 Uhr morgens in Frankreich), was bedeutet ( pacman -QAusgabe):

  • Kernel: 4.10.9-1
  • zsh: 5.3.1-2
  • sudo: 1.8.19.p2-1
  • bestanden: 1.7.1-1
  • gnupg: 2.1.20-1
  • Terminator: 1,91-5

Hier ist einVerknüpfungzu meiner .zshrc, das könnte auch helfen.

Und wie versprochen, hier sind einige Schritte, um dieses bösartige %Zeichen mit zu erhalten pass. Erstellen Sie einfach ein mehrzeiliges Passwort und drücken Sie Ctrl+ D, um das Passwort abzuschließen, ohne eine neue Zeile hinzuzufügen, um dieses Zeichen auszugeben. Ich stelle hier fest, dass das Drücken von Ctrl+ Dam Ende einer Textzeile nicht ausreicht, Sie müssen es zweimal tun. Wenn Sie diesem mehrzeiligen Passwort jedoch eine neue Zeile hinzufügen, wird die Passworteingabe durch einmaliges Drücken beendet, ohne dass dies angezeigt wird.

$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barCtrl+DCtrl+D%
Da ist es !

Aber bei einer abschließenden Zeile wird es nicht angezeigt und wir erhalten unsere Eingabeaufforderung zurück, wenn wir nur einmal Ctrl+ drücken D.

$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barReturn
Ctrl+D
$

Die grundlegende Frage ist also: Wie bekomme ich meinen Alias ​​zum Laufen? Für alle, die sich das fragen: Ich habe einfach ein einzeiliges Skript in meinem benutzerdefinierten Skriptverzeichnis geschrieben, das pass root_passworddie Umgebungsvariable aufruft und SUDO_ASKPASSauf den Pass dieses Skripts in meiner .zshrcDatei setzt. Eine andere Frage könnte sein: Was zum Teufel ist hier mit zsh und sudo los?


Edit 2017-04-16: Lösung

Dank anMichael HomerIch habe für mein Problem folgende Lösung gewählt:

  • Schreiben Sie ein einzeiliges Skript mit dem Namen, askpass-sudodas aufruftpass root_password
  • Setzen Sie die SUDO_ASKPASSUmgebungsvariable in my .zprofileauf den Pfad dieses Skripts
  • Habe die Zeile alias sudo='sudo -A'zu meinem hinzugefügt.zshrc

Und voilà! Beim Aufruf sudo commandwird nun wie gewünscht meine GnuPG-Schlüsselpassphrase abgefragt, um das Root-Passwort zu entschlüsseln und sudo --shellich erhalte ordnungsgemäß eine Root-Shell.

Antwort1

pass root_password | sudo --stdin --shellerfolgreich. passDas Passwort wurde gedruckt und sudogelesen und eine Shell gestartet; die Ausgabe wurde beendet, was bedeutet, dass der für die Ausgabe und Eingabe der Shell passverwendete Stream geschlossen wurde; die Shell wurde erfolgreich bei EOF beendet.pass

Nachfolgende Hinrichtungen innerhalb dersudoTimeout-Fenstererforderte keine Authentifizierung, sodass die Shell das Kennwort selbst erhielt und versuchte, es als Befehl auszuführen, wobei dieser Fehler auftrat.


Ihr Alias ​​kann unmöglich funktionieren, wenn Sie eine Shell möchten oder einen Befehl ausführen möchten, der von der Standardeingabe gelesen wird (bei Befehlen, die dies nicht tun, funktioniert er jedoch). Sie könnten einen Alias ​​einrichten, der ausgeführt wird, pass root_password | sudo --stdin truewenn Sie möchten, und sich dann auf das Timeout verlassen, um Befehle ohne Kennwort auszuführen.

Sie könnten auch eine Art Askpass-Helfer erstellen, der das gewünschte Verhalten liefert. Er würde das Passwort bereitstellen, passwennfragtedafür von sudo.

verwandte Informationen