findutilsマニュアルから:
たとえば、これら2つのコマンドの構造は次のとおりです。
# risky find -exec sh -c "something {}" \; find -execdir sh -c "something {}" \;
非常に危険です。その理由は、「{}」がセミコロンやその他のシェル関連文字を含むことができるファイル名に拡張されるためです。たとえば、
/tmp/foo; rm -rf $HOME
上記の2つのコマンドは、誰かがファイルを作成した場合に誰かのホームディレクトリを削除できます。そのため、信頼できないデータ(ファイル名など)をさらに解釈するために、引数を解釈するコマンドに渡すコマンド(例: "sh")を実行しないでください。
シェルの場合、この問題に対するきちんとした解決策があります。
# safer find -exec sh -c 'something "$@"' sh {} \; find -execdir sh -c 'something "$@"' sh {} \;
このアプローチはすべての問題を防ぐことを保証することはできませんが、攻撃者が選択したデータをシェルコマンドテキストに置き換えるよりもはるかに安全です。
find -exec sh -c "something {}" \;
代替項目が{}
引用されず、単一の文字列として扱われないのが問題の原因ですか?ソリューション
find -exec sh -c 'something "$@"' sh {} \;
ではが最初に
{}
置き換えられた{}
が引用されていないので、"$@"
元のコマンドと同じ問題がありますか?たとえば、これは、および?"$@"
に拡張されます。"/tmp/foo;"
"rm"
"-rf"
"$HOME"
なぜ
{}
脱出または引用しないのですか?
- 同じ種類の問題と解決策(
sh -c
該当する場合は含めるかどうか、find
必要ではない可能性があります)に適用され、最小限の例である他の例を提供できますか?注意を気を散らすことはできるだけ少ないのですか?バラより"bash -c"で実行されるコマンドに引数を与える方法
ありがとうございます。
ベストアンサー1
これは実際には参照には関係なく、パラメータ処理に関連しています。
危険な例を考えてみましょう。
find -exec sh -c "something {}" \;
これはシェルによって解析され、6つの単語に分けられます:、、、、、(
find
もはや引用符なし)、拡張する内容はありません。シェルは、この6つの単語を引数として使用して実行されます。-exec
sh
-c
something {}
;
find
find
たとえば、処理する項目を見つけると、引数に置き換えられ、foo; rm -rf $HOME
実行されます。{}
foo; rm -rf $HOME
sh
sh
-c
something foo; rm -rf $HOME
sh
-c
これで結果が解析されたことがわかりますsomething foo; rm -rf $HOME
(オプションではない最初のパラメータ)結果を実行します。
今、より安全なバリエーションを考えてみましょう。
find -exec sh -c 'something "$@"' sh {} \;
シェルは、、、、、、、、パラメータ
find
で実行されます。find
-exec
sh
-c
something "$@"
sh
{}
;
これ
find
が見つかったら、foo; rm -rf $HOME
再び置き換えられ、{}
パラメータ、、、で実行されます。sh
sh
-c
something "$@"
sh
foo; rm -rf $HOME
sh
-c
、およびsomething "$@"
を実行するコマンドで処理し、sh
およびをfoo; rm -rf $HOME
位置引数として処理します(から始まる$0
)、"$@"
次に拡張foo; rm -rf $HOME
単一値として、something
単一の引数で実行しますfoo; rm -rf $HOME
。
を使用してこれを表示できますprintf
。新しいディレクトリを作成し、入力して実行します。
touch "hello; echo pwned"
次のように最初のバリアントを実行します。
find -exec sh -c "printf \"Argument: %s\n\" {}" \;
生産する
Argument: .
Argument: ./hello
pwned
2番目のバリアントは次のように実行されます。
find -exec sh -c 'printf "Argument: %s\n" "$@"' sh {} \;
生産する
Argument: .
Argument: ./hello; echo pwned