Por que essa injeção de código não está funcionando?

0
$ 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 "'

Eu estava me perguntando por que as aspas duplas inicial e final no nome do arquivo não são emparelhadas com as aspas iniciais e finais em "$@" , para que echo world no nome do arquivo possa ser executado?

É porque uma citação deve ser reconhecida por sh durante a análise léxica do comando shell, a fim de citar? Aqui, as aspas no nome do arquivo aparecem no comando shell somente após a expansão do parâmetro, que já passou pela análise lexical e é muito tarde para que as aspas no nome do arquivo sejam reconhecidas? Similarmente ao link ?

Diferentemente, adicionar eval também não faz a injeção funcionar, porque embora eval torne " e ; no nome do arquivo reconhecível pelo shell, " no nome do arquivo também será removido por o shell:

$ 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

Depure para ver o que eval realmente executa:

$ 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

Obrigado.

Em uma nota lateral, por que existem dois itens para o mesmo arquivo na saída do comando find ? Desde a . é um link rígido para o diretório atual, por que não encontrar a saída sobre o próprio diretamente, mas o arquivo sob ele?

    
por Tim 09.06.2018 / 04:48

1 resposta

2

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, 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.

    
por 10.06.2018 / 10:46

Tags