How to avoid possible argument injection?
Descubra de que tipo de entradas você deseja passar e certifique-se de que os argumentos apenas os contenham.
No mínimo, certifique-se de que eles não contenham caracteres especiais para o shell remoto.
$1
não é um grande problema, uma vez que você compara com valores conhecidos. Embora você precise citar duas vezes, caso contrário, ele pode se expandir para várias palavras na comparação, e isso pode permitir passar valores engraçados por meio dele (algo como 1 -o x
passaria a comparação).
Use if [ "$1" = "s3" ] ; then ...
em vez disso.
Quanto a $2
e $3
, passá-las por ssh
é basicamente o mesmo que passar para eval
ou sh -c
. Quaisquer substituições dentro deles serão expandidas no controle remoto.
Digamos que executaremos ssh somehost "echo $var"
. Agora, se var
contiver $(ls -ld /tmp)
, a linha de comando remota será echo $(ls -ld /tmp)
e o ls
será executado no remoto. Duplicar a variável não ajudará na expansão do comando, mas aspas simples o farão. Com o comando escrito como
ssh somehost "echo '$var'"
, a expansão do comando não acontece.
As aspas simples dentro da variável ainda são um problema, pois elas terminarão as aspas simples, então, no mínimo, precisaremos verificar isso:
case "$var" in *"'"*) echo var has a single-quote; exit 1 ;; esac
Apesar de podermos procurar por quaisquer caracteres especiais que não queremos passar. Os sinais de dólar iniciam a maioria das expansões, os backticks iniciam a expansão de comandos e as citações também não confiam:
case "$var" in *[\'\"\$\']*) echo var has something funny; exit 1 ;; esac
Mas não tenho certeza se isso é tudo, então é melhor apenas colocar na lista de permissões os personagens que queremos passar. Se letras, dígitos, traços e sublinhados são suficientes:
case "$var" in *[!-_a-zA-Z0-9]*) echo var has something funny; exit 1 ;; esac
Então, isso pode ser um começo:
function runMyScript {
case "$2" in *[!-_a-zA-Z0-9]*) exit 1 ;; esac
case "$3" in *[!-_a-zA-Z0-9]*) exit 1 ;; esac
if [ "$1" = "s3" ] ; then
ssh somehost "script.sh '$1' '$2' '$3'"
elif [ "$1" = "ec2" ] ; then
ssh somehost "script.sh '$1' '$2'"
else
echo "** Run with s3 or ec2 options"
fi
}
Se você usou function runMyScript
em vez de runMyScript()
, não está executando um shell POSIX simples. Se for Bash, você pode reescrever as correspondências de padrões com [[...]]
test, que suporta correspondências de expressões regulares .
Novas versões do Bash também têm a expansão ${var@Q}
, que deve produzir o conteúdo de var
cotado em um formato que pode ser reutilizado como entrada. Também pode ser útil, mas eu não tenho um novo bash o suficiente para testá-lo.
Além disso, não confie cegamente em mim para lembrar de todas as peculiaridades possíveis da linguagem shell.