在Shell算术评估中使用未经消毒的数据的安全隐患


17

在对最近一个问题评论中,StéphaneChazelas提到双括号算法有安全隐患,例如:

x=$((1-$x))

在大多数贝壳上。

我的Google技能似乎很生疏,找不到任何东西。双括号算法的安全含义是什么?

Answers:


22

问题在于,如果$x外壳代码可能最终在特权提升上下文中使用(例如,setuid调用的脚本),则其中的内容尚未经过清理并包含可能受到攻击者控制的数据应用程序,sudoers脚本或用于直接或间接处理网络外数据(CGI,DHCP钩子...)。

如果:

x='(PATH=2)'

然后:

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

具有设置PATH2(相对路径很可能在攻击者的控制之下)的副作用。您可以替换PATH使用LD_LIBRARY_PATHIFS...这同样与发生x=$((1-x))在bash,zsh中或ksh(不是冲也不佳日只接受变量有数字常量)。

注意:

x=$((1-$x))

对于$x实现了(按POSIX可选)--(减量)运算符的某些shell中的负值,它将不能正常工作(与一样x=-1,这意味着要求shell评估1--1算术表达式)。"$((1-x))"没有这个问题,因为x算术评估的一部分(不早于此)已经扩展了。

bashzshksh(不dashyash)中,如果x是:

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

然后扩展$((1-$x))$((1-x))导致uname执行该命令(对于zsha需要是一个数组变量,但是可以使用该变量psvar)。

总之,我们不应该使用未初始化或不消毒的炮弹在算术表达式中的外部数据(注意,算术评估可以这样做$((...))(又名$[...]bashzsh),而且还取决于在壳let[/ testdeclare/typeset/export...returnbreakcontinueexitprintfprint内建函数,数组索引((..))[[...]]结构等)。

要检查变量是否包含文字十进制整数,可以使用POSIXly:

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

请注意,[0-9]在某些语言环境中,匹配项超过0123456789。[[:digit:]]应该可以,但我不会打赌。

还请记住,在某些情况下,带有前导零的数字被视为八进制(010有时为10,有时为8),并且请注意,上面的检查将使可能大于系统(或您将要使用的任何应用程序)支持的最大整数的数字通过在其中使用该整数;例如bash将18446744073709551616视为0,即2 64)。因此,您可能想要在上述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))将设置P为8,但x='P=3'; : $((x + 5))将设置P3(在zshkshbash)。“ $((x + 1))…… 也发生同样的情况”现在不正确;它将设置PATH2,与旧版本相同。
mosvy

@mosvy,对,谢谢(以及您先前的编辑)。现在已更正。
斯特凡·查泽拉斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.