Estou escrevendo um script de shell que muda seu comportamento com base no número de parâmetros posicionais passados
script.sh
if [ $# -eq 1 ]; then
if [ -f "$1" ]; then
validate='validate <"$1"'
else
validate='validate <<<"$1"'
fi
else
IFS=$'\n'
validate="validate <<<'${*}'"
fi
eval "$validate" | pull_data
Ambas validate
e pull_data
são funções Bash que leem do stdin e escrevem no stdout
Se for o primeiro caso [ $# -eq 1 ]
, acredito que o código esteja seguro contra injeção. Como a string é entre aspas simples, a expansão de parâmetros só acontece depois que eval é chamado. Não consigo pensar em uma string que possa resultar em injeção de código aqui.
Emitir
O problema surge com a else
condição. Aqui, cada parâmetro posicional é expandido em uma nova linha. Por exemplo
./script.sh "string_with_'_in_its_name" "code injected'"
A citação dentro de um dos primeiros parâmetros faz com que os novos parâmetros subsequentes sejam interpretados como comandos. Similarmente, isso também resulta em uma vulnerabilidade de injeção:
./script.sh valid_input \''$(code injected)'\'
Contexto
Estou usando eval para evitar repetir a validate ... | pull_data
construção em cada condição if. O script real tem muito mais condições, e usar eval o torna mais legível.
Qualquer conselho sobre como refatorar este script para evitar o problema de injeção e, ao mesmo tempo, manter a legibilidade seria muito apreciado!