我正在一个项目中使用大量的shellcript用于各种目的,性能和可移植性很重要.其中一些脚本使用的配置文件具有以下格式:
VARIABLE1="value" VARIABLE2="several words, several values" VARIABLE3="a,list,of,words"
然后,要使用这些变量,我们只需要输入以下内容:
#!/bin/sh . /path/to/the/configuration.file echo "Var 1 is: $VARIABLE1" echo "Var 2 is: $VARIABLE2" echo "Var 3 is: $VARIABLE3"
简单吧?
没那么多.事实是,虽然我们可以通过简单的方式保护脚本免受修改chown root file.sh; chmod 0711 file.sh
,但配置文件必须是可写的,然后我们发现像这样的讨厌的事情可能发生:
VARIABLE1="value"; rm requiredfile.data VARIABLE2="you dont want to see this: `rm anotherimportantfile.data` rm thelastrequiredfile.bin
因此,当调用配置文件时,插入其中的指令将使用实际调用它的任何用户的权限执行.
我知道我的要求是棘手的,但我希望能够过滤所有可能导致未经授权的代码执行的危险语法.
到目前为止我做了什么:
FILTER=' /^$/d # Delete empty lines /^#/d # Delete comments /^[A-Z0-9_]\+=.\+$/{ # Select assignments /`/p # alert with ` /\$/p # alert with $ /\\/p # alert with \ /;/p # alert with ; d # Accept the rest } ' C=`sed -e "$FILTER" $1 | wc -l` 2>/dev/null if test $C -gt 0; then echo "#ERR Suspicious strings in configuration file" fi
我错过了什么?有什么改进?
PS:我知道可以用grep
/ cut
组合安全地读取每个变量,但是对于性能问题是不可能的.
一个经常被引用的安全范例是你应该枚举允许的模式,而不是试图枚举所有可能的不允许的模式.
如果您将自己限制为分配的值始终是单引号字符串的变量,则必须允许的唯一模式是
^[A-Za-z_][A-Za-z0-9_]*='[^']*'[\t ]*$
尾部空格并不是绝对必要的(如果你想要很好,你也可以允许引导空格).
单引号禁止所有shell元字符; 单引号中的任何字符串都是逐字记录的.
允许双引号或不带引号的字符串只会引起麻烦.过渡到单引号可能有点麻烦,但如果你来这里寻求安全建议,那就是你会得到的.
顺便提一下,您可以简单地grep
用来查找违规行为:
if grep -v "^[A-Za-z_][A-Za-z0-9_]*='[^']*'[\t ]*$" configfile /dev/null >&2; then echo "$0: Invalid lines in configfile -- aborting" >&2 exit 2 fi . configfile : :
作为用户,我将非常感谢包含违规的诊断消息.这也避免了繁琐的绕行通道wc -l
.