findを使用しようとしています echo 0へ 一部のファイルに追加されますが、これは sh -cでのみ機能するようです。 :
find /proc/sys/net/ipv6 -name accept_ra -exec sh -c 'echo 0 > {}' ;
ただし、 sh -cを使用する find -execを使用 引用の問題が疑われるので、とても不安になります。私はそれを少しいじりました、そして明らかに私の疑いは正当化されました:
-
私のテスト設定:
[email protected] ~ % cd findtest [email protected] ~/findtest % echo one > file with spaces [email protected] ~/findtest % echo two > file with 'single quotes' [email protected] ~/findtest % echo three > file with "double quotes" [email protected] ~/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 -execを使用するsh -cなし 問題なく動作しているようです–ここで引用する必要はありません:[email protected] ~ % find findtest -type f -exec cat {} ; one two three -
しかし、
sh -cを使用している場合{}ある種の引用が必要なようです:[email protected] ~ % 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 -
二重引用符は、ファイル名に二重引用符が含まれていない限り機能します:
[email protected] ~ % 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 -
一重引用符は、ファイル名に一重引用符が含まれていない限り機能します:
[email protected] ~ % 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で 本質的に安全ではありませんか?
承認された回答:
{}を埋め込まないでください シェルコードで!これにより、コマンドインジェクションの脆弱性が発生します。 cat "{}"の場合は注意してください 、それは"だけではありません 文字、 、 ` 、 $ これも問題です(たとえば、 ./ $(reboot)/ accept_raというファイルを考えてみてください。 )¹。
ここでは、ファイル名を個別の引数として shに渡します。 (コードにはありません 引数)、および sh インラインスクリプト(コード 引数)位置パラメータを使用してそれらを参照するには:
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} ;
または、1つの shを実行しないようにします ファイルごと:
find . -name accept_ra -exec sh -c 'for file do
echo 0 > "$file"; done' sh {} +
同じことがxargs-I {}にも当てはまります またはzsh のzargs-I {} 。書かないでください:
<ストライク>ストライク>
<list.txt xargs -I{} sh -c 'cmd > {}'
これは、 findと同じようにコマンドインジェクションの脆弱性になります 上記、ただし:
<list.txt xargs sh -c 'for file do cmd > "$file"; done' sh
これには、1つの shの実行を回避できるという利点もあります。 ファイルごと、および list.txtの場合のエラー ファイルが含まれていません。
zshを使用 のzargs 、 sh -c を呼び出すのではなく、関数を使用することをお勧めします。 :
do-it() cmd > $1
zargs ./*.txt -- do-it
上記のすべての例で、2番目の sh 上記はインラインスクリプトの$0に入ります 。そこで関連するもの( sh など)を使用する必要があります またはfind-sh )、 _のようなものではありません 、-コード> 、-コード> または、 $ 0の値としての空の文字列 シェルのエラーメッセージに使用されます:
$ find . -name accept_ra -exec sh -c 'echo 0 > "$1"' inline-sh {} ;
inline-sh: ./accept_ra: Permission denied
GNUパラレルコード> 動作が異なります。それを使用すると、しない sh -cを使用したい parallelとして すでにシェルを実行していて、 {}を置き換えようとします シェルの正しい構文で引用された引数を使用します。
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'