【问题标题】:Safe way to set computed environment variables设置计算环境变量的安全方法
【发布时间】:2010-03-22 22:23:35
【问题描述】:

我有一个 bash 脚本,我正在修改它以接受来自标准输入的 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(全局设置)或正则表达式(仅在 bash >= 3 中)。它的工作原理是丢弃不在允许字符白名单中的任何内容,然后将结果与原始结果进行比较。如果没有抛出任何内容,则整个密钥必须仅包含列入白名单的字符。

【问题讨论】:

    标签: bash shell environment-variables security


    【解决方案1】:

    safer 使用 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
    

    另外,请参阅this。

    【讨论】:

    • 回复:为什么我要重新设置 IFS。在某些情况下,我收到错误“CMK_TEST:找不到命令”,因为它在 = 符号上分裂。我仍然对这是什么时候发生的感到有些困惑,因为在简单的测试中它不会。
    • 我不知道声明。这是一个有用的位。避免 eval 总是好的。但是我最终使用了一些避免使用 extglob 或正则表达式的东西(从而满足了我的秘密议程,即保持在完全由我的任意经验和舒适度描述的 bash 的可移植子集中。)我将用我的内容更新我的主要帖子最终使用。
    【解决方案2】:

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

    function import ()
    {
        local IFS="="
        while read key val; do
            case "$key" in CMK_*)
                # you can use case/esac here if you like
                if [[ $val =~ "some bad stuff" ]] ;then
                     echo "bad stuff found" 
                     echo "decide to exit or not here"
                else
                     eval "$key=$val";;
                fi
    
            esac
        done
     }
    

    【讨论】:

    • 这让我很紧张。我需要预测所有可能形式的讨厌的东西。我宁愿依靠白名单而不是黑名单。
    猜你喜欢
    • 2017-12-31
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 2018-08-02
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多