【发布时间】: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