내가 사용하려고 해요 find로 echo 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 -exec없이 사용하면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있습니까?
답변
{}쉘 코드에 포함시키지 마십시오 ! 명령 주입 취약점이 발생합니다. 주를 위해 것을 cat "{}"그것의의에 대해서뿐만 아니라 "문자, \, `, $또한 문제가 있습니다 (예를 들어라는 파일을 고려 ./$(reboot)/accept_ra).
(그런데, 일부 find구현에서는 그렇게 할 수 없으며 POSIX{} 는에 대한 인수에서 자체가 아닌 경우 동작을 지정 하지 않은 채로 둡니다find )
여기에서 파일 이름을 별도의 인수로 sh( 코드 인수가 아닌 ) 및 sh인라인 스크립트 ( 코드 인수)로 전달하여 위치 매개 변수를 사용하여 파일 이름 을 참조하려고합니다.
find . -name accept_ra -exec sh -c 'echo 0 > "$1"' sh {} \;
또는 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
또한 sh파일 당 하나를 실행 list.txt하지 않고 파일이 포함되지 않은 경우 오류 를 피할 수 있다는 이점이 있습니다.
함께 zshS ‘ zargs, 당신은 아마 호출보다는 기능을 사용하고자하는 것입니다 sh -c:
do-it() cmd > $1
zargs ./*.txt -- do-it
위의 모든 예제에서 위의 두 번째 예제 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 parallel는 다르게 작동합니다. 그것으로, 당신은 이미 쉘을 실행하는 것처럼 사용하고 싶지 않으며 쉘 에 대한 올바른 구문에서 인용 된 인수 로 대체하려고합니다 .sh -cparallel{}
<list.txt PARALLEL_SHELL=sh parallel 'cmd > {}'