Shellshockの脆弱性をチェックしているときに、これを取得しました。
host1:~$ env x='(){ :;}; echo vulnerable' bash -c "echo hello"
hello
host1:~$ env x='() { :;}; echo vulnerable' bash -c "echo hello"
vulnerable
hello
host1:~$
変でしょ?
Shellshockの脆弱性をチェックしているときに、これを取得しました。
host1:~$ env x='(){ :;}; echo vulnerable' bash -c "echo hello"
hello
host1:~$ env x='() { :;}; echo vulnerable' bash -c "echo hello"
vulnerable
hello
host1:~$
変でしょ?
() {
Bash は、スペースを含む正確に 4 文字で始まる環境変数を関数として認識します。だからenv x='(){ :;}; echo vulnerable'
数えない。
これは、 で関数を定義するために使用する構文に完全には準拠していませんbash
。内部bash
的には、関数の文字列表現を正規化された形式で保存します。関数が ( でexport -f function_name
) エクスポートされると、正規化された形式が環境に追加され、子bash
プロセスはそれを関数定義として認識します。
「シェルショック」バグは、bash
認識された関数を処理する方法に起因します。のバグのあるバージョンbash
(かなり前にさかのぼる) は、環境からの文字列を関数定義として評価するだけであり (関数名として変数の名前を先頭に追加することにより)、脆弱性テストで示されているように、インジェクション攻撃の対象となります。 .
子プロセスでbash
関数を定義するために、関数定義のように見える文字列を手動で作成することは、既知の手法です。bash
関数のエクスポートと再インポートは非常に一般的であり、多くの場合、ユーザーは気付かないことさえあります。(たとえば、この手法は、 および によって開始されたサブシェルに bash 関数を渡すために使用されxargs bash -c
ますfind ... -exec bash -c
。)
bash
環境内の埋め込み関数定義と見なされるものについては、少しうるさいです。最初に
env x='(){ :;}; echo vulnerable' bash -c "echo hello"}
()
と の間にスペースがないと、{
これbash
がエクスポートされた関数として認識されなくなります。そのため、単純なシェル変数のままです。見て、走ってみて
env x='(){ :;}; echo vulnerable' bash -c 'echo $x'
2 番目の例では、エクスポートされた関数を模倣するために、スペースを含む の値がx
正しく作成されているため、子bash
は の値全体を評価しx
て関数を「インポート」しますが、関数定義に続くコードも実行します。