使用`eval`来定义来自文件邪恶的文本的函数?

问题描述 投票:2回答:2

这是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的这个用例中可能存在漏洞,我想要对此用例进行具体推理。

shell eval exploit
2个回答
0
投票

如果你相信你对import_as的论点 - $1$2,以及$1引用的文件的内容 - 以上是安全的。 eval是邪恶的,因为它允许将数据作为代码进行评估;如果您对这些内容进行硬编码,则它们是(受信任的)代码的一部分,而不是(不受信任的)数据。


0
投票

在查看了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"
}
© www.soinside.com 2019 - 2024. All rights reserved.