「find -exec sh -c」を安全に使用できますか?


29

私はいくつかのファイルに使用しようとfindecho 0ていますが、明らかにこれはsh -c

find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' \;

しかし、sh -cwith find -execを使用すると、引用の問題が疑われるため、非常に不安になります。私はそれを少しいじりましたが、明らかに私の疑念は正当化されました:

  • 私のテスト設定:

    martin@dogmeat ~ % cd findtest 
    martin@dogmeat ~/findtest % echo one > file\ with\ spaces
    martin@dogmeat ~/findtest % echo two > file\ with\ \'single\ quotes\'
    martin@dogmeat ~/findtest % echo three > file\ with\ \"double\ quotes\"
    martin@dogmeat ~/findtest % ll
    insgesamt 12K
    -rw-rw-r-- 1 martin martin 6 Sep 17 12:01 file with "double quotes"
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with 'single quotes'
    -rw-rw-r-- 1 martin martin 4 Sep 17 12:01 file with spaces
    
  • find -execwithout を使用してもsh -c問題なく動作するようです。ここでは引用符は不要です。

    martin@dogmeat ~ % find findtest -type f -exec cat {} \;
    one
    two
    three
    
  • しかし、私が使用してsh -c {}いるときは、ある種の引用が必要なようです:

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c 'cat {}' \;
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: spaces: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: single quotes: No such file or directory
    cat: findtest/file: No such file or directory
    cat: with: No such file or directory
    cat: double quotes: No such file or directory
    
  • ファイル名に二重引用符が含まれていない限り、二重引用符は機能します。

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c 'cat "{}"' \;
    one
    two
    cat: findtest/file with double: No such file or directory
    cat: quotes: No such file or directory
    
  • ファイル名に単一引用符が含まれていない限り、単一引用符は機能します。

    martin@dogmeat ~ % LANG=C find findtest -type f -exec sh -c "cat '{}'" \;
    one
    cat: findtest/file with single: No such file or directory
    cat: quotes: No such file or directory
    three
    

すべてのケースで機能するソリューションは見つかりませんでした。私が見落としているもの、または本質的に安全ではないものを使用sh -cしていfind -execますか?

回答:


41

{}シェルコードに埋め込まないでください!これにより、コマンドインジェクションの脆弱性が作成されます。以下のためにことに注意してくださいcat "{}"、それがないだけのことだ"文字、\`$また問題である(例えばと呼ばれるファイルを考えます./$(reboot)/accept_ra)。

(ちなみに、一部のfind実装ではそれができません。POSIX{}は、の引数にそれ自体がない場合、動作を指定しませんfind

ここでは、ファイル名をshコード引数ではなく)別の引数として渡し、shインラインスクリプト(コード引数)を使用して、位置パラメーターを使用してそれらを参照します。

find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} \;

または、shファイルごとに1 つ実行しないようにするには:

find . -name accept_ra -exec sh -c 'for file do
  echo 0 > "$file"; done' sh {} +

同じことが、にも適用されるxargs -I{}zshzargs -I{}。書かないでください:

<list.txt xargs -I {} sh -c 'cmd> {}'

find上記と同じ方法でコマンドインジェクションの脆弱性になりますが、次のようになります。

<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh

また、shファイルごとに1 つ実行するのを避ける利点もあり、list.txtファイルが含まれていない場合はエラーが発生します。

zshのはzargs、おそらく呼び出すのではなく、機能を使用したいと思いますsh -c

do-it() cmd > $1
zargs ./*.txt -- do-it

上記のすべての例で、上記の2番目shはインラインスクリプトのになり$0ます。あなたは(のようにそこに関連する何かを使用する必要がありますshfind-sh)、いないようなもの_---の値は以下のように、または空の文字列を$0シェルのエラーメッセージに使用されます。

$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} \;
inline-sh: ./accept_ra: Permission denied

GNUのparallel動作は異なります。これを使用すると、すでにシェルを実行しているように使用したくないため、シェルの正しい構文で引用された引数に置き換えようとしますsh -cparallel{}

<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'

thats second shはある種のプレースホルダーのよう_です。たとえば、bash internalsを呼び出したい場合に非常に便利ですfind /tmp -name 'fil*' -exec bash -c 'printf "%q\n" "$1"' _ {} \;。しかし、誰がこれが文書化されているか知っていますか?
フロリアンフィ

1
@FlorianFidaシェルへの最初の引数になる$0。(シェルの通常名をあなたはそれがあなたの通常の位置引数の1を食べていないので、このシナリオでは、それをスキップする必要があるのドキュメントが。-cこれに言及している。
ETANライスナー


1
@phk、それはargv[0]ここにはありません、それ$0はスクリプトのことです。Svenのページはここでは不正確です。rこれは、にzsh基づいてモードを変更できず、シェルが制限モードに入らないようにするため$0です。(exec -a rksh ksh -c 'cd /')制限付きkshで実行されますが、ではありませんksh -c 'cd /' rksh)。
ステファンシャゼル16年

1
気にしない場合、ステファンは「シェルコードに{}を埋め込まない理由」を説明する答えがありますか?私はあなたの答えをすべて見つけましたが、見つけられませんでしたが、見つけることができませんでしたが、このテーマについてあなたが書いたものを見たが、それが答えであったか、チャットやcomunixのような別のサイトであったか思い出せない場合は、時間があるとき... /、あなたは「埋め込むことはありません{}」の部分に拡大していただけませんか、私たちは、専用のQなどが必要だと思います「使用のセキュリティへの影響find-exec sh -cと埋め込み{}シェルコードでの」
don_crissti
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.