回答:
問題は、コンテンツ$xがサニタイズされておらず、シェルコードが特権エスカレーションコンテキストで使用される可能性がある場合に、攻撃者の制御下にある可能性のあるデータを含む場合です(たとえば、setuidによって呼び出されるスクリプトアプリケーション、sudoersスクリプト、またはネットワーク外のデータ(CGI、DHCPフック...)の処理に直接または間接的に使用されます)。
次の場合:
x='(PATH=2)'
次に:
x=$((1-$x)))
に設定PATHするという副作用があります2(攻撃者の制御下にある可能性が非常に高い相対パス)。あなたは置き換えることができPATHてLD_LIBRARY_PATHか、IFS同じことが起こると... x=$((1-x))(ダッシュものみが変数に数値定数を受け入れヤシュない)はbash、zshのまたはkshで。
ご了承ください:
x=$((1-$x))
$x(POSIXによるオプション)--(デクリメント)演算子を実装する一部のシェルの負の値に対しては正しく動作しません(と同様x=-1、これはシェルに1--1算術式を評価することを意味します)。算術評価の一部として(以前ではなく)拡張される"$((1-x))"ため、問題はありませんx。
ではbash、zshとksh(いないdashかyash)、あればx次のとおりです。
x='a[0$(uname>&2)]'
その後の拡張$((1-$x))または$((1-x))その原因uname(のためのコマンドを実行するzsh、a配列変数である必要があるが、一つは使用することができpsvar、そのため、例えば)。
要約すれば、一つは算術評価することによって行うことができる(シェルにメモを演算式で初期化されていないまたは非消毒外部データを使用してはならない$((...))(別名$[...]でbash又はzsh)も、シェルに応じてlet、[/ test、declare/typeset/export...、return、break、continue、exit、printf、print組み込み関数、配列インデックス、((..))および[[...]]構成体をいくつか挙げます)。
変数にリテラル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[0$(...)]問題に注意を向けた場所)。bashます。
x='P=3'; : $(($x + 5))設定されますP8に、しかしx='P=3'; : $((x + 5))設定されますPに3(でzsh、kshまたはbash)。「$((x + 1))...でも同じことが起こります」は正しくありません。古い時点でに設定さPATHれ2ます。