Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 设置计算环境变量的安全方法_Bash_Shell_Environment Variables_Security - Fatal编程技术网

Bash 设置计算环境变量的安全方法

Bash 设置计算环境变量的安全方法,bash,shell,environment-variables,security,Bash,Shell,Environment Variables,Security,我有一个bash脚本,我正在修改它以接受来自stdin的key=value对。(它是由xinetd产生的。)如何安全地将这些key=value对转换为子流程的环境变量 我计划只允许以预定义前缀“CMK_”开头的键,以避免设置IFS或任何其他“危险”变量。但这种简单化的方法 function import () { local IFS="=" while read key val; do case "$key" in CMK_*) eval

我有一个bash脚本,我正在修改它以接受来自stdin的key=value对。(它是由xinetd产生的。)如何安全地将这些key=value对转换为子流程的环境变量

我计划只允许以预定义前缀“CMK_”开头的键,以避免设置IFS或任何其他“危险”变量。但这种简单化的方法

function import ()
{
    local IFS="="
    while read key val; do
        case "$key" in CMK_*)
            eval "$key=$val";;
        esac
    done
 }
是非常不安全的,因为$val可能包含各种讨厌的东西。这似乎是可行的:

shopt -s extglob
function import ()
{
    NORMAL_IFS="$IFS"
    local IFS="="
    while read key val; do
        case "$key" in CMK_*([a-zA-Z_]) )
            IFS="$NORMAL_IFS"
            eval $key='$val'
            export $key
            IFS="="
            ;;
        esac
    done
 }
但是(1)它使用了我以前从未使用过的时髦的extglob,并且(2)它非常复杂,以至于我不能放心它的安全性

具体来说,我的目标是允许key=value设置通过bash脚本传递到被调用进程的环境中。由子流程来处理设置的潜在恶意值

我正在修改其他人的脚本,所以我不想只是将其转换为Perl并使用它。我也不希望改变它,以不同的方式调用子流程,比如

#!/bin/sh
...start of script...
perl -nle '($k,$v)=split(/=/,$_,2); $ENV{$k}=$v if $k =~ /^CMK_/; END { exec("subprocess") }'
...end of script...
更新:我最终用于密钥检查的是:

if [ "$key" = "${key%[^a-zA-Z_0-9]*}" ]; then

它不需要extglob(全局设置)或regex(仅在bash>=3中)。它的工作原理是抛出任何不在允许字符白名单中的内容,然后将结果与原始结果进行比较。如果没有抛出任何内容,那么整个密钥必须只包含白名单中的字符。

一种方法是知道你将得到什么样的讨厌的东西。然后在函数从stdin读取时清理该值。例如(bash>3.2)


一种方法是知道你会得到什么样的下流东西。然后在函数从stdin读取时清理该值。例如(bash>3.2)

使用
declare
比使用
eval
更重要:

shopt -s extglob
function import ()
{
    NORMAL_IFS="$IFS"
    local IFS="="
    while read key val; do
        case "$key" in 
            CMK_*([a-zA-Z_]) )
                IFS="$NORMAL_IFS"
                declare $key="$val"  2>/dev/null || echo "Bad key"
                IFS="="   # why set this here?
                ;;
            *)
                echo "Bad key"
                ;;
        esac
    done
}
如果不想使用
extglob
,可以使用正则表达式匹配测试:

while ...
if [[ $key =~ CMK_ ]]    # or something like: [[ $key =~ CMK_[[:alpha:]] ]]
then
    declare ...
else
    echo "Bad key"
fi
另外,请参见。

使用
声明比使用
评估更重要:

shopt -s extglob
function import ()
{
    NORMAL_IFS="$IFS"
    local IFS="="
    while read key val; do
        case "$key" in 
            CMK_*([a-zA-Z_]) )
                IFS="$NORMAL_IFS"
                declare $key="$val"  2>/dev/null || echo "Bad key"
                IFS="="   # why set this here?
                ;;
            *)
                echo "Bad key"
                ;;
        esac
    done
}
如果不想使用
extglob
,可以使用正则表达式匹配测试:

while ...
if [[ $key =~ CMK_ ]]    # or something like: [[ $key =~ CMK_[[:alpha:]] ]]
then
    declare ...
else
    echo "Bad key"
fi

另外,请参见。

re:我为什么要重新设置IFS。在某些情况下,我会得到一个错误“CMK_TEST:command not found”,因为它在=符号上分裂。我仍然有点困惑,这是什么时候发生的,因为在简单的测试中并没有。我不知道declare。这是有用的一点。避免评估总是好的。但我最终使用了一些避免使用extglob或regex的东西(从而满足了我的秘密议程,即完全由我的任意体验和舒适度来描述bash的可移植子集)。我将用我最终使用的东西更新我的主要帖子。re:我为什么要重新设置IFS。在某些情况下,我会得到一个错误“CMK_TEST:command not found”,因为它在=符号上分裂。我仍然有点困惑,这是什么时候发生的,因为在简单的测试中并没有。我不知道declare。这是有用的一点。避免评估总是好的。但我最终使用了一些避免使用extglob或regexes的东西(这样就满足了我的秘密议程,即呆在完全由我的随意体验和舒适度描述的bash的可移植子集中)。我将用我最终使用的东西更新我的主要帖子。这让我很紧张。我需要预测所有可能的下流东西。我宁愿依赖白名单也不愿依赖黑名单,这让我很紧张。我需要预测所有可能的下流东西。我宁愿依赖白名单也不愿依赖黑名单。