【问题标题】:Safe (and restricted) version of evaleval 的安全(和受限)版本
【发布时间】:2017-02-20 12:06:54
【问题描述】:

在研究从配置文件中(安全地)加载分配的方法的过程中,我试图提出一个 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

【问题讨论】:

  • 除了接受第二个参数 - 这很容易添加 - this 我的答案,我们 previously discussed 满足您的要求(除了您想考虑替换 tr 调用带有外壳参数扩展)。
  • @123 我认为采购不符合我的安全要求。
  • @mklement0 我将根据您上面的答案提供一个答案,但这并不完全相同。请多多包涵。
  • 听起来不错,但请在您的问题中添加任何其他要求。
  • @mklement 顺便说一句,在你之前的回答中尽量避免 tr 是我尽可能避免的一件事。

标签: bash shell eval code-injection


【解决方案1】:

在我问过上一个问题之后( Reading assignments from configuration files) 和 mklement0 对 cme​​ts 的回答让我得到 mklemen0 对这个问题的回答: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
  • 然后还原
  • 只使用外壳功能

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

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

【讨论】:

猜你喜欢
  • 2012-06-05
  • 2016-12-27
  • 1970-01-01
  • 2023-03-13
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多