シェル算術評価における整理されていないデータ使用のセキュリティ影響

シェル算術評価における整理されていないデータ使用のセキュリティ影響

コメント最近の質問、Stéphane Chazelasは、二重角括弧演算には次のセキュリティリスクがあると述べました。

x=$((1-$x))

ほとんどの殻に。

私のGoogle技術が錆びて何も見つからないようです。二重括弧算術がセキュリティに与える影響は何ですか?

ベストアンサー1

問題は、アプリケーションのコンテンツが$x削除されておらず、攻撃者が制御できるデータが含まれている場合、シェルコードが最終的に特権昇格コンテキスト(setuidによって呼び出されるスクリプトなど)アプリケーションで使用できることです。 sudoersスクリプトまたは直接または間接的に使用されます。オフグリッドデータ(CGI、DHCPフック...)を処理します。

場合:

x='(PATH=2)'

それから:

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

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

気づく:

x=$((1-$x))

$x(POSIXによるオプション)(縮小)演算子を実装する一部のシェルでは、負の値に対して正しく機能しません--(と同様に、これはシェルで算術式をx=-1評価する必要があることを意味します)。拡張は算術評価の一部として行われるため、問題はありません(以前ではありません)。1--1"$((1-x))"x

bashzshおよびkshdashまたはそうでないyash)では、次のような場合x

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

$((1-$x))その後、 or の拡張により$((1-x))コマンドが実行されます( の場合は配列変数でなければなりませんが、たとえば使用できます)。unamezshapsvar

要約すると、初期化されていないか削除されていない外部データは、シェル算術式で使用しないでください。

$((...))$[...]算術評価は(inまたはとも呼ばれる)を介して実行できますが、組み込み関数bashzshシェル、配列のインデックス付け、構成などによって異なります。let[testdeclare/typeset/export...returnbreakcontinueexitprintfprint((..))[[...]]

ksh// の配列索引付けで機能するため、変数名を引数として使用するすべての組み込み関数 ( / with , , , // , / with , ... )zshでも機能します。bash[test-vreadunsetexporttypesetreadonlyprintprintf-vgetopts

数値テスト演算子のオペランドが組み込み関数[[...]]の有無にかかわらず、算術式として扱われるという事実は、ORで一般に後者が優先される理由の1つです。[testbashzsh

比較する:

$ a='x[1$(uname>&2)]' bash -c '[ "$a" -eq "$b" ]'
bash: line 0: [: x[1$(uname>&2)]: integer expression expected

(セキュリティ):

$ a='x[1$(uname>&2)]' bash -c '[[ "$a" -eq "$b" ]]'
Linux

uname実行されました)。

ksh、およびに問題[があります。)[[ ... ]]

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

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

一部のロケールでは、[0-9][[:digit:]]0123456789 以上が一致するため、あらゆる形式の入力検証/削除を避ける必要があります。

また、場合によっては、前にゼロの付いた数字が8進数(010時々10、時には8)で処理されることに注意してください。上記のチェックでは、システムよりも大きいシステムを許可することもできます(またはサポートされている最大の整数を使用します)。どんなアプリケーションでも)。対応する整数を使用してください。たとえば、bashは18446744073709551616を0として扱います。なぜなら2 64だからです。したがって、上記のケースの説明に追加のチェックを追加する必要があるかもしれません。たとえば、次のようになります。

(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
$ bash -c 'read "$x"' < /dev/null
Linux
$ env psvar= bash -c 'unset "$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

追加資料:

おすすめ記事