why the beginning and ending double quotes in the filename not paired with the beginning and ending double quotes in
"$@"
Como a expansão de variáveis não é uma substituição de texto direto. As aspas dentro de uma variável não são processadas como aspas, são apenas caracteres comuns nesse ponto.
Isso é semelhante a qualquer variável que contenha citações.
$ foo='"foo bar"'
As aspas em foo
não terminam as aspas na linha de comando, não há divisão de palavras:
$ printf "%s\n" "$foo"
"foo bar"
E aqui, há divisão de palavras (porque a expansão não é citada), e as citações em foo
não fazem nada para evitar:
$ printf "%s\n" $foo
"foo
bar"
O último é semelhante ao motivo pelo qual a maneira ingênua de armazenar um comando em uma variável não funciona.
Quanto ao eval
, não entendo por que você o adicionou, mas como envolve outra rodada de expansões, você pode simplesmente colocar uma substituição de comando lá:
$ touch '$(uname -m)'
$ find . -exec sh -c 'eval ls "$@"' sh {} \;
$(uname -m)
ls: cannot access './x86_64': No such file or directory
ou um ponto e vírgula:
$ touch ';uname -m'
$ find . -exec sh -c 'eval ls "$@"' sh {} \;
;uname -m
;uname -m
x86_64
(Não sei por que isso executa o ls
duas vezes.)
Com um arquivo chamado "; echo world "
, as aspas se expandem como parte do "$@"
, onde eval
as vê e, como ele executa todo o processamento do shell novamente, você tem um ponto-e-vírgula entre aspas.
Não há um nome de arquivo único que funcione para injetar um comando em todos os casos vulneráveis, isso depende da maneira como o comando é construído.