shellshockを確認するコマンドの説明


32

Shellshockのバグについてbashシェルをチェックするために使用したコマンドは次のとおりです。

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

誰でもコマンドを詳細に説明できますか?


4
unix.stackexchange.com/q/157329/70524も参照してください-Fixeeの答えが役に立つかもしれません。
ムル14

回答:


45

この回答は、Creative Commons Attribution-Share Alike 4.0ライセンスの下でライセンスされているMatthew MillerによるFedora Magazineのオリジナル記事の派生物です。

説明させてください:

env x='() { :;}; echo OOPS' bash -c :

これにより、脆弱なシステムでは「OOPS」が出力されますが、bashにパッチが適用されている場合はサイレントに終了します。

env x='() { :;}; echo OOPS' bash -c "echo this is a test"

これにより、脆弱なシステムでは「OOPS」“this is a test”が出力されますが、bashにパッチが適用されている場合は出力されます。

そして、おそらく環境変数と関係があると聞いたことがあるでしょう。しかし、なぜ環境変数のコードが実行されるのですか?まあ、それは想定されていません—しかし、私は自分の利益のためにちょっと賢すぎると呼びたがっている機能のために、いくつかの欠陥の余地があります。Bashは端末プロンプトとして表示されますが、スクリプト言語でもあり、関数を定義する機能があります。あなたはこのようにします:

$ Ubuntu()  { echo "Ubuntu is awesome."; }

そして、新しいコマンドがあります。echoここは実際にはまだ実行されていないことに注意してください。新しいコマンドを実行すると何が起こるかとして保存されています。これはすぐに重要になります!

$ Ubuntu
 Ubuntu is awesome.

有用!しかし、何らかの理由で、サブプロセスとしてbashの新しいインスタンスを実行し、その下で素晴らしい新しいコマンドを実行する必要があるとしましょう。このステートメントbash -c somecommandはまさにこれを行います。新しいシェルで指定されたコマンドを実行します。

$ bash -c Ubuntu
  bash: Ubuntu: command not found

ああ 悲しい。子は関数定義を継承しませんでした。しかし、それは環境に固有のものです-シェルからエクスポートされたキーと値のペアのコレクション。(これは完全な「概念」です。これに慣れていない場合は、今のところ私を信頼してください。)そして、bashは関数をエクスポートすることもできます。そう:

$ export -f Ubuntu
$ bash -c Ubuntu
  Ubuntu is awesome.

これはすべて順調です。ただし、これを実現するメカニズムはかなり危険です。基本的に、環境変数で関数を実行するためのLinux / Unixマジックはないため、エクスポート関数は実際には関数定義を含む通常の環境変数を作成するだけです。次に、2番目のシェルが「着信」環境を読み取り、関数のように見えるコンテンツを持つ変数に遭遇すると、それを評価します。

理論的には、関数を定義しても実際には実行されないため、これは完全に安全です。ただし、これが私たちがここにいる理由です。関数定義の最後に達したときに評価が停止しないというバグがコードにありました。ただ動き続けた。

環境変数に保存された関数がで合法的に作成された場合、それは決して起こりませんexport -f。しかし、なぜ合法ですか?攻撃者は古い環境変数を作成することができ、関数のように見える場合、新しいbashシェルはそれを考えます!

したがって、最初の例では:

env x='() { :;}; echo OOPS' bash -c "echo this is a test"

envコマンドは、指定された変数セットを使用してコマンドを実行します。この場合、x関数のように見えるものに設定しています。この関数は単一で:、実際には何もしないと定義されている単純なコマンドです。しかし、その後、semi-colon関数定義の終わりを示すwhichの後に、echoコマンドがあります。それはそこにあるはずではありませんが、私たちがそれをするのを止めるものは何もありません。

次に、この新しい環境で実行するために指定されたコマンドは、新しい「bash」シェルであり、再び「echo this is a test」または「do nothing :」コマンドを使用します。その後、完全に無害に終了します。

しかし—おっと!その新しいシェルが起動して環境を読み取ると、x変数に到達し、関数のように見えるため、それを評価します。関数定義は無害にロードされます-そして、悪意のあるペイロードもトリガーされます。したがって、脆弱なシステムで上記を実行すると、“OOPS”印刷されます。または、攻撃者は単に物事を印刷するよりもはるかに悪いことをする可能性があります。


1
Muchas graciasが、これがなぜ機能するかについての優れた説明について。
ダグR.

2
env必要ではないことに注意してください。次のコマンドを使用せずに、同じ結果(Bashが更新されたかどうかに応じて合格/不合格)を取得できますx='() { :;}; echo OOPS' bash -c "echo this is a test"。これは、コマンドの前に変数を割り当てると、その変数とその値がコマンドのbash -c "..."環境(この場合)に渡されるためです。
追って通知があるまで一時停止します。

1
...しかし、最近のパッチのいくつかでは必要になるかもしれません。物事は流動的です。
追って通知があるまで一時停止します。

4
@DennisWilliamson env必要かどうかは、テスト対象のシェルではなく、テストを実行するシェルによって決まります。(これらは同じかもしれません。それでも、bashが独自の環境を処理する方法をテストしてます。)BourneスタイルのシェルはNAME=value command構文を受け入れます。Cスタイルのシェル(例えば、cshtcsh)しないでください。そのため、テストの移植性は少し高くenvなります(ただし、その動作方法について混乱を招く場合があります)。
エリアケイガン14年

2

パッチが適用されていないバージョンbashも店舗は環境変数として関数定義をエクスポートします。

関数を次のxように保存します。

$ x() { bar; }
$ export -f x

そして、その定義を確認してください、

$ env | grep -A1 x
x=() {  bar
}

したがって、独自の環境変数を定義し、それらを関数定義として解釈することにより、これを悪用できます。たとえば、次のenv x='() { :;}'ように扱われます

x() { :;
}

shellshockをチェックするコマンドは何をしますか、

env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

からman env

  1. env -変更された環境でプログラムを実行します。

  2. :終了ステータスで終了するだけ0です。もっと見る

  3. パッチを当てていないbashの新しいインスタンスがとして起動するbash -c "echo this is a test"と、細工された環境変数が関数として扱われ、ロードされます。したがって、出力が得られます

    傷つきやすい
    これはテストです

注:関数定義外のエコーは、bashの起動中に予期せず実行されました。関数定義は、評価とエクスプロイトを実現するための単なるステップであり、関数定義自体と使用される環境変数は任意です。シェルは環境変数を調べ、xを見て、関数定義がどのようなものであるかを知っている制約を満たしているように見え、行を評価します。 。また、参照してください。これを


パッチを適用したバージョンのbashの子シェルで評価してエクスポートすると、定義済みのbash関数がまだあることがわかりました。これを参照してください:chayan @ chayan:〜/ testr $ test(){echo "anything"; }; export -f test; bash -c test出力:何でもあなたの答えはやや適切に指示されていません。kasiyAの定義を超えて変数を展開するというバグの説明は正しいと思います。
heemayl

@heemaylこの動作は自然です。しかし、試してenv test='() { echo "anything"; }' bash -c "echo otherthing"みると出力に表示されますotherthing。これはパッチで修正されています。まだわからない場合はお気軽に。
souravc 14

もう一度明確にしてください。最後のコメントでは、基本的に関数を定義し、bashにエコーを実行するように指示しています。この例では、bashで関数を呼び出していません。パッチを適用したbashとパッチを適用していないbashの両方で同じ出力が得られないでしょうか?バグは基本的にbashが関数定義の後に置かれたコマンドを実行していたので、たとえばenv test = '(){echo "anything"; }; echo "foo" 'bash -c "echo otherthing"。この文脈で私を明確にしてください。
heemayl 14

@heemayl私は私の答えを編集しましたが、今ではそれが明確であることを願っています。私の最後のコメントの例では、関数を呼び出していません。しかし、違いは、unpatched bash定義されているとおりに関数を呼び出すことができますが、パッチを適用した場合bashは定義自体が存在しないことです。
souravc 14

@heemayl:いいえ、それは間違っています。パッチを適用したBashは、引き続き関数定義を子の環境に渡します。このパッチの違いは、関数定義(echo vulnerable)に続くコードが実行されないことです。最新のパッチでは、渡される関数には特定のプレフィックス(env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test")が必要であることに注意してください。いくつかのより新しいパッチが%%最初のパッチの代わりに使用するかもしれません()
追って通知があるまで一時停止します。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.