以下は、bash シェルで Shellshock バグを確認するために使用したコマンドです。
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
誰かコマンドを詳しく説明してもらえますか?
答え1
この答えは、Fedora Magazineのオリジナル記事マシュー・ミラー著、ライセンス:クリエイティブ・コモンズ 表示-継承 4.0ライセンス。
説明させてください:
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
関数のように見えるものを に設定しています。関数は 1 つの で:
、実際には何も実行しないと定義されている単純なコマンドです。ただし、semi-colon
関数定義の終了を示す の後に、コマンドがありますecho
。これは本来は存在しないはずですが、実行を妨げるものは何もありません。
次に、この新しい環境で実行するために指定されたコマンドは、新しい bash シェルであり、これも「echo this is a test
」または「何もしない:
」コマンドで、その後、完全に無害に終了します。
しかし、おっと!新しいシェルが起動して環境を読み取ると、変数に到達しx
、関数のように見えるため、それを評価します。関数定義は無害にロードされますが、その後、悪意のあるペイロードもトリガーされます。したがって、脆弱なシステムで上記を実行すると、結果が出力されます“OOPS”
。または、攻撃者は単に何かを出力するよりもさらに悪いことをする可能性があります。
答え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
、
env
- 変更された環境でプログラムを実行します。:
終了ステータスで終了する以外は何もしません0
。もっとパッチを当てていないbashの新しいインスタンスがとして起動されると
bash -c "echo this is a test"
、細工された環境変数は関数として扱われ、ロードされます。したがって、出力は次のようになります。
脆弱 これはテストです
注記:関数定義外の echo が bash の起動中に予期せず実行されました。関数定義は評価とエクスプロイトを実行するための単なるステップであり、関数定義自体と使用される環境変数は任意です。シェルは環境変数を調べ、関数定義がどのようなものであるかについての制約を満たしているように見える x を確認し、その行を評価して、意図せずに echo (悪意のあるコマンドかどうかに関係なく、任意のコマンドである可能性があります) も実行します。また、次も参照してください。これ