这是eval cat inside a function的后续问题。
我正在使用eval
来模仿来自其他语言(例如JavaScript)的import
功能。这是我想在我的本地机器上做一段时间的事情,因为我已经建立了压倒性的脚本文件集合。
原因是我现在在单独的文件中有很多单独的函数,我不希望每次想要调用该函数时一次又一次地使用source
读取文件。
这主要是为了娱乐,但如果我在一个不那么随意的环境中使用它,我不想拍我的脚:
import_as() {
import_name="$1"
import_fnname="${2:-"$import_name"}"
if test -f "$1"; then
echo "File '$1' doesn't exist."
fi
case "$2" in
*[!-a-zA-Z0-9_]* ) echo "BAD";;
*) eval "$2"'() { '"$(< $1.sh)"'; }' ;;
esac
}
这是一个使用它的例子:
add.是
#!/bin/sh
echo "$(($1 + $2))"
苏北.是
#!/bin/sh
echo "$(($1 - $2))"
example_import.是
import_as "add" "math_add"
import_as "sub"
math_add 2 5 # Returns "7"
math_subtract 5 1 # Returns "4"
我的问题是eval
的这个用例是否在我执行检查后容易受到攻击,或者在这个脚本中是否有可利用的东西?
PS:我理解eval
被认为是邪恶的,我不想听到这个答案。如果您认为在eval
的这个用例中可能存在漏洞,我想要对此用例进行具体推理。
如果你相信你对import_as
的论点 - $1
和$2
,以及$1
引用的文件的内容 - 以上是安全的。 eval
是邪恶的,因为它允许将数据作为代码进行评估;如果您对这些内容进行硬编码,则它们是(受信任的)代码的一部分,而不是(不受信任的)数据。
在查看了Charles Duffy的精彩答案和评论之后,这段代码被评估为更安全:
import_as() {
# Charles Duffy's suggestions, including side effect reduction.
current_lc_ctype="$LC_CTYPE"
LC_CTYPE=C
import_name="$1"
import_fnname="${2:-"$import_name"}"
case "$import_name" in
*[!/]*) echo "BAD - local directory only."; return ;;
*) echo "Okay" ;;
esac
if test -f "$import_name"; then
echo "File '$import_name' doesn't exist."
fi
case "$2" in
*[!-a-zA-Z0-9_]*) echo "BAD"; return;;
*) eval "$2"'() { '"$(< $1.sh)"'; }' ;;
esac
# Change LC_CTYPE back to prior to function call
LC_CTYPE="$current_lc_ctype"
}