コマンドを表示してコードの挿入を防ぐ方法

コマンドを表示してコードの挿入を防ぐ方法

私は基本的wgetに遊んでページをダウンロードし、そのページのいくつかの情報を検索し、その情報にwget基づいて別のページを表示するスクリプトを作成しました。デフォルトでは、私のコードは次のようになります。

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

ただし、このソリューションにはいくつかの問題があります。最大の問題は、htmlファイルにいくつかの邪悪な値(たとえば、" google.com; <evil command>; ls "私のスクリプトはNetworkManagerスクリプトとしてrootとして実行される必要があるためです。 . これはエラーが発生したときにデバッグするのに非常に便利です。

コードの挿入を防ぐための良い方法はありますか?それとももっと良い方法がありますか?私の最初の考えは、すべての参照を次のように置き換えることでしたが、... | sed 's/"/\\/g"'コードを挿入するすべての可能な方法を見つけたかどうかはわかりません。

ありがとうございます!

答え1

コードをシェルにパイプすることはほとんど常にエラーです。ここではすでにシェルでコードを実行しているので、他のシェルを実行する理由はまったくありません。

また、その部分を文字列に入れてコマンドを作成しないでください。コマンドは文字列のリストです。これを文字列で埋めようとすると、引数を区切るスペースと引数内のスペースの間の区切りが失われます。そして 文字列を分割して実行しようとすると、他の問題が発生します。、その一部はセキュリティへの影響。しかし、とにかくここでは必要ありません。あなたは仕事をとても複雑にしています。

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

wget -vその部分を変更できるようにしたいのですがスクリプトの制御下で、その部分にスペースや何も含まれていないことがわかっている場合は、\[*?その部分を変数に入れることができます。

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

スクリプトがksh、bash、またはzshで実行されますが、通常のshでは実行されない場合は、コマンドを配列に入れることができます。

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

内容を反響するとき、制御文字に注意してください。これにより、端末がジョブを実行したり、実際に印刷された内容が歪むことがあります。

echo "$wget --post-data=$form_value" | tr -c '[:print:]' '?'

答え2

コマンドを記録するには、次の標準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[@]}"

これにより、任意のデータに対してシェルのインタプリタを呼び出さなくなります。

答え3

パラメータが「A5h4f121SDEfdsZPfkshf457dsFJqsd」と等しい場合は、sedを使用して英数字以外のすべてのエントリを削除できます。

このような:

#!/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"

この場合、英数字以外のすべての数字が削除され、コードは何の害もありません。

関連情報