シェル算術評価で非サニタイズデータを使用することのセキュリティへの影響


17

最近の質問へのコメントで、StéphaneChazelasは、二重カッコ算術には次のようなセキュリティの影響があると述べています。

x=$((1-$x))

ほとんどのシェルで。

私のGoogleスキルは錆びているようで、何も見つかりません。二重括弧演算のセキュリティ上の意味は何ですか?

回答:


22

問題は、コンテンツ$xがサニタイズされておらず、シェルコードが特権エスカレーションコンテキストで使用される可能性がある場合に、攻撃者の制御下にある可能性のあるデータを含む場合です(たとえば、setuidによって呼び出されるスクリプトアプリケーション、sudoersスクリプト、またはネットワーク外のデータ(CGI、DHCPフック...)の処理に直接または間接的に使用されます)。

次の場合:

x='(PATH=2)'

次に:

x=$((1-$x)))

に設定PATHするという副作用があります2(攻撃者の制御下にある可能性が非常に高い相対パス)。あなたは置き換えることができPATHLD_LIBRARY_PATHか、IFS同じことが起こると... x=$((1-x))(ダッシュものみが変数に数値定数を受け入れヤシュない)はbash、zshのまたはkshで。

ご了承ください:

x=$((1-$x))

$x(POSIXによるオプション)--(デクリメント)演算子を実装する一部のシェルの負の値に対しては正しく動作しません(と同様x=-1、これはシェルに1--1算術式を評価することを意味します)。算術評価の一部として(以前ではなく)拡張される"$((1-x))"ため、問題はありませんx

ではbashzshksh(いないdashyash)、あればx次のとおりです。

x='a[0$(uname>&2)]'

その後の拡張$((1-$x))または$((1-x))その原因uname(のためのコマンドを実行するzsha配列変数である必要があるが、一つは使用することができpsvar、そのため、例えば)。

要約すれば、一つは算術評価することによって行うことができる(シェルにメモを演算式で初期化されていないまたは非消毒外部データを使用してはならない$((...))(別名$[...]bash又はzsh)も、シェルに応じてlet[/ testdeclare/typeset/export...returnbreakcontinueexitprintfprint組み込み関数、配列インデックス、((..))および[[...]]構成体をいくつか挙げます)。

変数にリテラル10進整数が含まれていることを確認するには、POSIXlyを使用できます。

case $var in
  ("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac

[0-9]一部のロケールでは0123456789以上に一致することに注意して[[:digit:]]ください。大丈夫ですが、私はそれには賭けません。

また、先頭にゼロの付いた数字は一部のコンテキスト(0108、10、時には8)で8 進数として扱われることを覚えておいてください。また、上記のチェックでは、システム(またはアプリケーションその整数を使用します;例えばbashは18446744073709551616を2 64として0として扱います)。したがって、上記のcaseステートメントに次のような追加のチェックを追加することができます。

(0?* | -0?*)
  echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
  echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;

例:

$ export 'x=psvar[0$(uname>&2)]'
$ ksh93 -c 'echo "$((x))"'
Linux
ksh93: psvar: parameter not set
$ ksh93 -c '[ x -lt 2 ]'
Linux
ksh93: [: psvar: parameter not set
$ bash -c 'echo "$((x))"'
Linux
0
$ bash -c '[[ $x -lt 2 ]]'
Linux
$ bash -c 'typeset -i a; export a="$x"'
Linux
$ bash -c 'typeset -a a=([x]=1)'
Linux
$ bash -c '[ -v "$x" ]'
Linux
$ mksh -c '[[ $x -lt 2 ]]'
Linux
$ zsh -c 'echo "$((x))"'
Linux
0
$ zsh -c 'printf %d $x'
Linux
0
$ zsh -c 'integer x'
Linux
$ zsh -c 'exit $x'
Linux

その他の資料:


x='P=3'; : $(($x + 5))設定されますP8に、しかしx='P=3'; : $((x + 5))設定されますP3(でzshkshまたはbash)。「$((x + 1))...でも同じことが起こります」は正しくありません。古い時点でに設定さPATH2ます。
mosvy

@mosvy、正しい感謝(および以前の編集)。今修正しました。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.