이 코드 삽입이 작동하지 않는 이유는 무엇입니까?

이 코드 삽입이 작동하지 않는 이유는 무엇입니까?
$ 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

모든 취약한 경우에는 명령을 주입하는 데 사용할 수 있는 단일 파일 이름이 없으며 명령 구성 방법에 따라 다릅니다.

관련 정보