$ touch '"; echo world "'
$ find . -exec sh -c 'ls -l "$@"' sh {} \;
total 0
-rw-rw-r-- 1 t t 0 Jun 8 23:13 '"; echo world "'
-rw-rw-r-- 1 t t 0 Jun 8 23:13 './"; echo world "'
파일 이름이 실행될 수 "$@"
있도록 파일 이름의 열기 및 닫기 큰따옴표가 파일 이름의 열기 및 닫기 큰따옴표와 쌍을 이루지 않는 이유가 궁금합니다.echo world
sh
인용하려면 쉘 명령의 어휘 분석 중에 인용 부호를 인식해야 하기 때문입니까 ? 여기서 파일 이름의 따옴표는 매개 변수 확장 후 쉘 명령에만 나타납니다. 이는 이미 어휘 분석을 통과했으며 파일 이름의 따옴표를 인식할 시간이 없습니까? 비슷하다https://unix.stackexchange.com/a/448643/674?
차이점은 추가해도 eval
주입이 작동하지 않는다는 것입니다. 왜냐하면 eval
쉘이 파일 이름에서 및 를 인식 하더라도 "
파일 이름도 쉘에 의해 삭제되기 때문입니다.;
"
$ find . -exec sh -c 'eval ls -l "$@"' sh {} \;
total 0
-rw-rw-r-- 1 t t 0 Jun 8 23:13 '"; echo world "'
ls: cannot access './; echo world ': No such file or directory
eval
실제로 실행되는 내용을 확인하기 위한 디버깅 :
$ find . -exec sh -c 'echo ls -l "$@"' sh {} \;
ls -l .
ls -l ./"; echo world "
$ ls -l ./"; echo world "
ls: cannot access './; echo world ': No such file or directory
감사해요.
참고로 명령 출력에 동일한 파일의 두 항목이 있는 이유는 무엇입니까 find
? 부터. 현재 디렉토리에 대한 하드 링크입니다. find 자체가 출력되지 않고 그 아래의 파일이 출력되는 이유는 무엇입니까?
답변1
파일 이름의 여는 큰따옴표와 닫는 큰따옴표가 파일 이름의 여는 큰따옴표와 닫는 큰따옴표와 쌍을 이루지 않는 이유는 무엇입니까?
"$@"
변수 확장은 직접적인 텍스트 대체가 아니기 때문입니다. 변수 안의 따옴표는 따옴표로 처리되지 않으며 현재로서는 단지 일반 문자일 뿐입니다.
이는 따옴표가 포함된 모든 변수와 유사합니다.
$ foo='"foo bar"'
따옴표는 foo
명령줄의 따옴표를 끝내지 않으며 단어 분리가 없습니다.
$ printf "%s\n" "$foo"
"foo bar"
그리고 여기 저기예토큰화(확장이 인용되지 않았기 때문에), 인용문은 foo
이를 방지하기 위해 아무 역할도 하지 않습니다.
$ printf "%s\n" $foo
"foo
bar"
후자는 명령을 변수에 저장하는 간단한 접근 방식이 작동하지 않는 이유와 유사합니다.
의 경우 eval
왜 추가했는지 이해할 수 없지만 또 다른 확장이 필요하므로 거기에 명령 대체를 넣을 수 있습니다.
$ touch '$(uname -m)'
$ find . -exec sh -c 'eval ls "$@"' sh {} \;
$(uname -m)
ls: cannot access './x86_64': No such file or directory
또는 세미콜론:
$ touch ';uname -m'
$ find . -exec sh -c 'eval ls "$@"' sh {} \;
;uname -m
;uname -m
x86_64
(왜 두 번 실행되는지 잘 모르겠습니다 ls
.)
라는 파일의 경우 "; echo world "
따옴표가 보이는 "$@"
위치의 일부로 확장되고 전체 쉘 처리가 다시 실행되므로 따옴표로 묶인 세미콜론이 표시됩니다.eval
모든 취약한 경우에는 명령을 주입하는 데 사용할 수 있는 단일 파일 이름이 없으며 명령 구성 방법에 따라 다릅니다.