Como exibir o comando e evitar a injeção de código

2

Estou jogando com wget , e basicamente faço um script que baixa uma página, preenho algumas informações nesta página e, em seguida, wget outra página, dependendo dessas informações. Então, basicamente, meu código parece

defautltCommand="wget -v"
formValue=$(cat myfileA.html | get_field_value )
command="${defaultCommand} --post-data=\"myfield=${formValue}\""
echo "Command 3: ${command}"
echo "${command}" | bash

No entanto, esta solução tem vários problemas, o principal é que se o arquivo html tiver alguns valores ruins (como " google.com; <evil command>; ls " ), ele poderá fazer a injeção de código. E porque meu script deve ser executado como root como um script do NetworkManager ... Gostaria de ter certeza de que não é possível injetar código. No entanto, eu gosto da idéia de escrever o comando que será usado, é bastante útil para depurar quando ocorre um erro.

Você tem uma boa maneira de ter certeza de que não posso receber nenhuma injeção de código? Ou talvez você tenha uma maneira ainda melhor de prosseguir? A primeira ideia que tive foi substituir todas as citações desta forma: ... | sed 's/"/\/g"' , mas não tenho certeza se capturaria todas as formas possíveis de injetar código.

Obrigado!

    
por tobiasBora 17.11.2017 / 18:14

3 respostas

3

Se você quiser registrar um comando, você pode usar o mecanismo padrão xtrace :

log_cmd() {
  local - # assuming ash-based shells or bash-4.4+
          # see set -o localoptions in zsh or use
          # function log_cmd { syntax in AT&T ksh
          # or replace {...;} with (...) POSIXly (but
          # spawns a subshell)

  typeset PS4="$1"; shift
  set -o xtrace

  "$@"
}

# here assuming a shell with arrays like ksh93, zsh, bash, yash
defautltCommand=(wget -v)
formValue=$(<myfileA.html get_field_value)
command=("${defaultCommand[@]}" "--post-data=myfield=$formValue")
log_cmd 'Command 3: ' "${command[@]}"

Dessa forma, você nunca está invocando o interpretador de um shell em dados arbitrários.

    
por 18.11.2017 / 10:00
5

O código de pipeline em um shell está quase sempre errado. Aqui, você já está executando código em um shell, não há absolutamente nenhuma razão para executar outro shell.

Além disso, não crie comandos colocando suas partes em uma string. Um comando é uma lista de cadeias de caracteres; se você tentar colocá-lo em uma string, perderá a distinção entre espaços que separam argumentos e espaços dentro de argumentos, e você encontrará problemas adicionais ao tentar dividir a string para executá-la , alguns dos quais têm implicações de segurança . Mas você não precisa disso aqui de qualquer maneira. Você está complicando demais as coisas.

form_value=$(cat myfileA.html | get_field_value )
wget -v --post-data="$form_value"

Se você quiser que a parte wget -v seja variável, mas sob o controle do seu script e saiba que as partes não conterão espaços em branco ou% de\[*?, você pode colocar essa parte em uma variável.

wget='wget'
if [ -n "$verbose" ]; then
  wget="$wget -v"
fi
form_value=$(cat myfileA.html | get_field_value )
$wget --post-data="$form_value"

Se o seu script for executado em ksh ou bash ou zsh, mas não se for executado em sh simples, você poderá colocar o comando em uma matriz.

#!/bin/ksh
…
download=(wget -v --post-data="$form_value")
…
"${download[@]}"

Ao exibir o conteúdo, Cuidado com os caracteres de controle que podem fazer com que seu terminal execute ações ou deturpe o que é realmente impresso .

echo "$wget --post-data=$form_value" | tr -c '[:print:]' '?'
    
por 17.11.2017 / 22:03
0

Se o seu argumento se parece com "A5h4f121SDEfdsZPfkshf457dsFJqsd" você pode remover todos os não alfanuméricos usando sed.

Algo parecido com isto:

#!/bin/bash

# sample function just not to think how to process your form
get_field_value () {
   echo "ls -la; ps -ef;\"find . -iname test.txt\";  \'date +%Y%m%d\'"
}

# out of the bad command will be:
get_field_value
# >> ls -la; ps -ef;"find . -iname test.txt";  'date +%Y%m%d'

# your script begins here

#sample url
url="www.google.com"

# suggesting you have your file near your script
formValue=$(cat myfileA.html | get_field_value )

# remove all non-alphanumerics using sed
# formValue=$(echo "$formValue" | sed -e "s/[^a-zA-Z0-9]//g")
formValue=$(echo "$formValue" | sed -e "s/[^[:alnum:]]//g")
echo "Command 3: wget -v --post-data=\"$formValue\""
# >> Command 3: wget -v --post-data="lslapseffindinametesttxtdateYmd"


# run your command
wget -v --post-data="myfield=${formValue}" "$url"

neste caso, todos os não alfanuméricos serão removidos e o código não poderá prejudicar

    
por 18.11.2017 / 00:50