如何在bash脚本中过滤危险字符?

时间:2014-02-05 10:30:10

标签: performance bash security shell validation

我正在一个项目中使用大量的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组合安全地读取每个变量,但这对于性能问题是不可能的。

2 个答案:

答案 0 :(得分:5)

一个经常被引用的安全范例是你应该枚举允许的模式,而不是试图枚举所有可能的不允许的模式。

如果您将自己局限于分配了始终为单引号字符串的值的变量,则必须允许的唯一模式是

^[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避免繁琐的迂回。

答案 1 :(得分:2)

忘记过滤器。我对此问题的理解是,您不应该直接将配置文件的写/读权限授予某人。您应该只为一个组分配sudo权限,将相关用户添加到该组中。