sudo --stdinと任意の文字を含むパスワードを使用したzshの奇妙な動作

sudo --stdinと任意の文字を含むパスワードを使用したzshの奇妙な動作

この投稿は、あなたが期待したり毎日見ることができるように始まりません。ここに私のルートパスワードがあります。: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
覚えにくいですか?まあ、それは問題ではありません。あなたが私に叫ぶ前に、うん、私は変えた。これで、dummy_rootテストに対応するパスワードを持つユーザーがいます。

長い話を短く

このパスワードをstdinのsudoに渡すためにzshを壊しました。

(非常に)長いバージョン

したがって、これは間違っています。私はsudowithtargetpwフラグを使用しています。これは、sudoが要求するパスワードが私のパスワードではなく、ターゲットユーザーのパスワードであることを意味します。私はpassパスワードマネージャ(場所)、私はすべてのコンピュータ/サーバーのルートパスワードを含みます。確実なセキュリティ上の理由から、パスワードは128文字のパスでランダムに生成されます(そうでないため)。私は怠惰な人なので(そしてあなたもそうだと確信しています)、次のエイリアスを使用したいと思います。

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

passに慣れていない人のために説明すると、デフォルトでGnuPGを使用してディレクトリツリーのパスワードを暗号化し、パスワードの復号化を呼び出してpass directory/subdirectory/passwordstdoutに印刷します(もちろん、ディレクトリはオプションであり、ルートディレクトリに保存されているすべてを混在させることができます)ですが、これはお勧めできません。)エイリアスの目的は、1日に数十回実行されるのを防ぐことです。

$ 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)

しかし、aliasコマンドをテストするとどうなりますか?

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

ここで%ロゴは色が反転しています。私の端末には、黒の背景に白いテキスト、白い背景%に黒のテキストがあり、いくつかの白い強調表示があり、パスワードが復号化された後に印刷されます。これを印刷し[sudo] password for root:てこれを印刷する間、%GPGは私に秘密鍵のパスワードを要求しました。場合によっては、反転されたパーセント記号が見つかり、どこでいつ見たかが印刷されていると思います。EOF(ここでは注意してください。全くわかりません。方法については投稿の最後を参照してください。これを印刷するには%)。この奇妙なフラグの後はルートではなくecho $?復帰することに注意してください0

pass root_passwordだから私はキャラクターに関するより多くの情報を得ることができることを確認するために出力の16進ダンプを得ました。結果は次のとおりです。

$ 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はい。記号はありませんが、NLsudoに必要な改行(参照)はここにあります。man ascii%man sudo

しかし、ちょっと待って、今は楽しさが始まります。新しく起動したターミネータウィンドウまたはttyでコマンドを2回実行すると、次のことが起こります。

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

それ以来、zshが破損しているようです。最初のコマンドの出力を実行したいようですが、sudo2番目のコマンドのみを実行します。以下は、「壊れた」シェルのいくつかの例です。

$ 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

ここで何が起こっているのでしょうか?示されているように、zshインスタンスを別のインスタンス(evec)に置き換えてもexec zsh問題は解決しません。ここで実際に壊れたものは何ですか?ビア、zshまたはsudo?

それでは、もう少しテストしてみましょう。新しいターミナルウィンドウで別の16進ダンプを実行してみましょう(明らかにzshを「通常の」状態に復元する方法がわからないからです)。

$ 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
$

パーセント記号はどこに行きましたか?全く知らない。これにはありませんが、まだルートではありませんが、シェルは現在破損しています(この「破損した状態」という名前を適切に指定する方法がわかりません)。後でコマンドを実行すると、pass root_password | sudo --stdin --shell前と同じエラーメッセージが表示されます。 ttyやターミネーター、さらには邪悪な%キャラクターでもすべてが同じだという点は注目に値する。

これが私が助けを必要とするかもしれないと考えることができるすべての情報です。私はArch Linuxを使用しており、記載されているすべてのパッケージは今日(地球上の場所に応じて2017年4月16日または15日、現在フランスの午前4時)現在の最新バージョンです。つまり(pacman -Q出力):

  • カーネル: 4.10.9-1
  • zsh:5.3.1-2
  • 数度:1.8.19.p2-1
  • 合格:1.7.1-1
  • gnupg:2.1.20-1
  • ターミネーター:1.91-5

ここに一つあります。協会私の.zshrcの場合も役に立ちます。

%約束したように、この悪意のあるフラグを取得するいくつかのステップは次のとおりですpass。文字を印刷するために後ろに新しい行を追加せずに複数行のパスワードを作成し、Ctrl+を押すとパスワードが完成します。テキスト行の末尾にある+をDクリックするだけでは不十分で、ダブルクリックする必要があることがわかりました。ただし、複数行のパスワードに末尾の行を追加する場合は、そのパスワードを一度クリックすると、この内容を表示せずにパスワードの入力が終了します。CtrlD

$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barCtrl+DCtrl+D%
そこに!

ただし、末尾の行がある場合は表示されず、Ctrl+をD1回押すだけでプロンプトが表示されます。

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

したがって、基本的な質問は次のとおりです。エイリアスをどのように機能させることができますか?気になる方のために、私はカスタムスクリプトディレクトリにpass root_password環境変数を呼び出し、私のファイルの対応するスクリプト渡しSUDO_ASKPASSに設定するスクリプト行を作成しました。.zshrcもう一つの質問は次のとおりです。ここでzshとsudoは正確に何ですか?


2017-04-16 編集:ソリューション

ありがとうマイケル・ホーマー私の問題については、次の解決策を選択しました。

  • askpass-sudo次を呼び出す1行のスクリプトを作成します。pass root_password
  • SUDO_ASKPASS私の環境変数を.zprofileスクリプトパスに設定します。
  • alias sudo='sudo -A'私の行にこの行を追加してください。.zshrc

望むより!次に、ルートシェルを適切に取得できるsudo commandように、ルートパスワードを復号化するために必要なGnuPGキーパスワードを要求します。sudo --shell

ベストアンサー1

pass root_password | sudo --stdin --shell効果がありました。passパスワードを印刷し、sudoそれを読み、シェルを起動します。最終出力は、シェルpassの出力と入力ストリームがpassEOFで正常に終了したことを意味します。

その後の実行sudoタイムアウトウィンドウ認証は不要なため、シェルがパスワード自体を受け取り、それをコマンドとして実行しようとするとエラーが発生します。


シェルが必要な場合やstdinから読み取られるコマンドの一部を実行すると、エイリアスは機能しない可能性があります(ただし、エイリアスを必要としないコマンドの場合は機能します)。必要に応じて実行エイリアスを設定し、タイムアウトを利用してpass root_password | sudo --stdin trueパスワードなしでコマンドを実行できます。

必要な動作を提供するために、AskPassアシスタントの種類を構築することもできます。pass以下を使用してパスワードを入力してください。尋ねるで構成されているからですsudo

おすすめ記事