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_root
Benutzer 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 sudo
mit dem targetpw
Flag, was bedeutet, dass das von sudo abgefragte Passwort das Passwort des Zielbenutzers ist, nicht meines. Ich verwende den pass
Passwort-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/password
wird 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_password
um 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
0a
ist NL
gemäß 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 sudo
die 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 --shell
Befehl 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 -Q
Ausgabe):
- 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_password
die Umgebungsvariable aufruft und SUDO_ASKPASS
auf den Pass dieses Skripts in meiner .zshrc
Datei 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-sudo
das aufruftpass root_password
- Setzen Sie die
SUDO_ASKPASS
Umgebungsvariable in my.zprofile
auf den Pfad dieses Skripts - Habe die Zeile
alias sudo='sudo -A'
zu meinem hinzugefügt.zshrc
Und voilà! Beim Aufruf sudo command
wird nun wie gewünscht meine GnuPG-Schlüsselpassphrase abgefragt, um das Root-Passwort zu entschlüsseln und sudo --shell
ich erhalte ordnungsgemäß eine Root-Shell.
Antwort1
pass root_password | sudo --stdin --shell
erfolgreich. pass
Das Passwort wurde gedruckt und sudo
gelesen und eine Shell gestartet; die Ausgabe wurde beendet, was bedeutet, dass der für die Ausgabe und Eingabe der Shell pass
verwendete Stream geschlossen wurde; die Shell wurde erfolgreich bei EOF beendet.pass
Nachfolgende Hinrichtungen innerhalb dersudo
Timeout-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 true
wenn 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, pass
wennfragtedafür von sudo
.