eval

时间:2017-02-20 12:06:54

标签: bash shell eval code-injection

在开发(安全地)从配置文件加载分配的过程中,我试图想出一个shell函数:

  • 接收任意字符串作为第一个参数,应用安全扩展(即变量扩展,${}扩展...)但阻止任何不安全扩展(包括嵌套在其他构造中)。
  • 将结果分配给作为第二个参数接收的变量名称(对于此问题,可以假定变量名称是安全的)
  • 最好是纯shell(特定于Bash对我来说是好的),但是如果提供更好的结果,使用外部命令的提议就可以了,不会过多地降低性能并依赖于通常在基本安装上提供的实用程序类UNIX操作系统。
  • 在删除“第一级”引号的同时执行扩展,就像shell一样。

下面是一个示例(假设函数safeval符合上述要求,并已在当前上下文中加载):

export A=1
safeval '$A$(ls /)' B
echo "$B"      # Echoes 1$(ls /)
safeval '"a""b"' C
echo "$C"      # Echoes ab

1 个答案:

答案 0 :(得分:0)

按照上一个问题我问( Reading assignments from configuration files)以及mklement0的评论回答让我想到了这个问题的答案:Bash Templating: How to build configuration files from templates with Bash?,我想出了一个潜在的解决方案,我正在寻找反馈,特别是我可能错过了它的安全和潜在的失败模式。

#
# Argument 1 : string to safely expand
# Argument 2 : name of the variable to which expanded value will be assigned
#
safeval()
{
local _v=$1
_v=${_v//\$\(/\$$'\1'}
_v=${_v//\$\[/\$$'\2'}
_v=${_v//'`'/$'\3'}
_v=${_v//\\ /$'\4'}
_v=${_v// /$'\5'}
eval printf -v _v %b "$_v" || return 1
_v=${_v//$'\1'/\(}
_v=${_v//$'\2'/\[}
_v=${_v//$'\3'/'`'}
_v=${_v//$'\4'/\\ }
_v=${_v//$'\5'/ }
printf -v "$2" %s "$_v"
}

请注意,这(我认为应该)处理所提供的字符串中的不连续引用(例如,输入中的'"a"b"c"将被指定为abc)。

此代码旨在执行以下操作:

  • 重新设置所有$(,' $ ['和`有希望的安全字符串。
  • 然后执行eval
  • 然后退回
  • 仅使用shell功能

为了便于阅读,我在答案中保留了一些可避免的分配,我会在最终代码中删除。我也可能会将第一个printf的stderr重定向到/dev/null

我使用%b作为printf的字符串格式,以允许配置文件中的换行符之类的内容。欢迎评论这是好是坏。