ech*_*hox 199
eval是 POSIX 的一部分。它是一个接口,可以是内置的外壳。
它在“POSIX程序员手册”中有描述:http : //www.unix.com/man-page/posix/1posix/eval/
eval - construct command by concatenating arguments
Run Code Online (Sandbox Code Playgroud)
它将接受一个参数并构造它的命令,该命令将由 shell 执行。这是联机帮助页的示例:
1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
Run Code Online (Sandbox Code Playgroud)
$foo使用 value'10'和$xvalue 进行定义'foo'。$y,它由字符串组成'$foo'。美元符号必须用 转义'$'。echo $y.'$foo'eval。它将首先评估$x为 string 'foo'。现在我们有了y=$foo将被评估为的语句y=10。echo $y现在是值'10'。这是许多语言中的常见功能,例如 Perl 和 JavaScript。查看 perldoc eval 以获取更多示例:http : //perldoc.perl.org/functions/eval.html
and*_*coz 77
是的,eval是 bash 内部命令,因此在bash手册页中进行了描述。
eval [arg ...]
The args are read and concatenated together into a single com-
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
Run Code Online (Sandbox Code Playgroud)
通常它与Command Substitution结合使用。如果没有明确的eval,shell 会尝试执行命令替换的结果,而不是评估它。
假设您要编写等效于VAR=value; echo $VAR. 请注意 shell 如何处理以下内容的不同之处echo VAR=value:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
Run Code Online (Sandbox Code Playgroud)
shell 尝试执行echo和VAR=value作为两个单独的命令。它会引发关于第二个字符串的错误。分配仍然无效。
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
Run Code Online (Sandbox Code Playgroud)
shell 合并(连接)两个字符串echo和VAR=value,根据适当的规则解析这个单个单元并执行它。最后但并非最不重要的,eval可能是一个非常危险的命令。eval必须仔细检查命令的任何输入以避免安全问题。
小智 26
eval 语句告诉 shell 将 eval 的参数作为命令并通过命令行运行它们。它在以下情况下很有用:
在你的脚本中,如果你将一个命令定义到一个变量中,然后你想使用该命令,那么你应该使用 eval:
/home/user1 > a="ls | more"
/home/user1 > $a
bash: command not found: ls | more
/home/user1 > # Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there
/home/user1 > eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp
/home/user1 >
Run Code Online (Sandbox Code Playgroud)
jw0*_*013 23
eval没有手册页,因为它不是一个单独的外部命令,而是一个内置的 shell,这意味着一个命令在 shell 内部并且只有 shell ( bash)知道。bash手册页的相关部分说:
eval [arg ...]
The args are read and concatenated together into a single command.
This command is then read and executed by the shell, and its exit
status is returned as the value of eval. If there are no args, or only
null arguments, eval returns 0
Run Code Online (Sandbox Code Playgroud)
此外,输出 ifhelp eval是:
eval: eval [arg ...]
Execute arguments as a shell command.
Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.
Exit Status:
Returns exit status of command or success if command is null.
Run Code Online (Sandbox Code Playgroud)
eval是一个强大的命令,如果你打算使用它,你应该非常小心地避免它带来的可能的安全风险。
小智 22
eval 是一个 shell 命令,通常作为内置命令实现。
在 POSIX 中,它作为“2.14. Special Built-In Utilities”的一部分在“eval”条目中列出。
内置的意思是:
术语“内置”意味着 shell 可以直接执行该实用程序而无需搜索它。
简单来说:使输入行被解析两次。
shell 有一系列步骤来“处理”一行。您可以查看此图像并意识到 eval 是唯一向上的行,返回到左侧的第 1 步。从POSIX 描述:
2.1 外壳介绍
- shell 读取它的输入....
- shell 将输入分解为标记:单词和运算符
- shell 将输入解析为简单和复合命令。
- 外壳执行各种扩展(单独)...
- Shell 执行重定向并从参数列表中删除重定向运算符及其操作数。
- shell 执行一个函数、内置的、可执行的文件或脚本......
- shell 可以选择等待命令完成并收集退出状态。
在第 6 步,将执行一个内置函数。
在第 6 步,eval 使处理过的行被发送回第 1 步。
这是执行序列返回的唯一条件。
这就是为什么我说:使用 eval 输入行被解析两次。
和最重要的效果要了解。一行第一次受制于上面显示的七个 shell 步骤的一个结果是引用. 在第 4 步(扩展)中,还有执行所有扩展的 一系列步骤,最后一个是引用删除:
报价删除应始终最后执行。
因此,总是会删除一级引用。
作为第一个效果的结果,该行的其他/不同部分暴露于外壳解析和所有其他步骤。
这允许执行间接扩展:
a=b b=c ; eval echo \$$a ### shall produce "c"
Run Code Online (Sandbox Code Playgroud)
为什么?因为在第一个循环中,第一个$被引用。
因此,shell 会忽略它进行扩展。名称为 a
的下$一个扩展为 "b"。
然后,删除一级引用,使第一个不$引用。
第一个循环结束。
然后,在第二个循环中,$bshell 读取字符串。
然后扩展为 "c"
并作为参数提供给echo.
要“查看” eval 在第一个循环中会产生什么(要再次评估),请使用 echo。或者任何明确显示参数的命令/脚本/程序:
$ a=b b=c
$ eval echo \$$a;
c
Run Code Online (Sandbox Code Playgroud)
用 echo 替换 eval 以“查看”正在发生的事情:
$ echo echo \$$a
echo $b
Run Code Online (Sandbox Code Playgroud)
也可以显示一行的所有“部分”:
$ printf '<%s> ' echo \$$a
<echo> <$b>
Run Code Online (Sandbox Code Playgroud)
在这个例子中,这只是一个回声和一个变量,但记住它有助于评估更复杂的情况。
不得不说:上面的代码有一个错误,你能看出来吗?。
简单:缺少一些引号。
如何?你可能会问。简单,让我们改变变量(不是代码):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Run Code Online (Sandbox Code Playgroud)
看到缺失的空格了吗?
那是因为里面的值$b被shell分割了。
如果这不能说服您,请尝试以下操作:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
Run Code Online (Sandbox Code Playgroud)
缺少引号。使其正常工作(添加内部"$a"和外部\"引号)。
试试这个(非常安全):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Run Code Online (Sandbox Code Playgroud)
没有它的手册页..
不,没有独立的手册页。搜索手册man -f eval甚至apropos eval显示没有条目。
它包含在man bash. 就像任何内置的一样。
搜索“SHELL BUILTIN COMMANDS”,然后搜索“eval”。
获得帮助的更简单方法是:在 bash 中,您可以help eval查看内置帮助。
因为它动态地将文本绑定到代码。
换句话说:它将其参数列表(和/或此类参数的扩展)转换为已执行的行。如果出于任何原因,攻击者设置了参数,您将执行攻击者代码。
或者更简单,使用 eval 你告诉谁定义了一个或多个参数的值:
来吧,坐在这里输入任何命令行,我会用我的力量执行它。
那很危险吗?每个人都应该清楚它是。
eval 的安全规则应该是:
只对你赋予它的值的变量执行 eval 。
Sté*_*las 15
eval是大多数解释型语言 ( TCL, python, ruby...) 的一个特性,不仅仅是 shell。它用于动态评估代码。
在 shell 中,它是作为 shell 内置命令实现的。
基本上,eval将字符串作为参数并评估/解释其中的代码。在 shell 中,eval可以接受多个参数,但eval只需将这些参数连接起来形成要计算的字符串。
它非常强大,因为您可以动态构建代码并运行它,这是在编译语言(如 C)中无法做到的。
喜欢:
varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
# which in Bourne-like shell language
# is a variable assignment.
Run Code Online (Sandbox Code Playgroud)
但这也很危险,因为对传递给的动态(外部提供)部分进行清理非常重要,eval因为它被解释为 shell 代码。
例如,在 if $1is之上evil-command; var,eval最终会评估evil-command; var=$varvalueshell 代码,然后运行它evil-command。
的邪恶eval往往被夸大了。
好吧,这很危险,但至少我们知道它很危险。
很多其他的命令将在其参数评估shell代码如果不消毒,(取决于外壳),像[又名test,export,printf,GNU sed,awk,当然sh/ bash/perl和所有解释...
示例(此处uname用作evil-command和$a外部提供的未经处理的数据):
$ a='$(uname>&2)' sh -c 'eval "echo $a"'
Linux
$ a='x[0$(uname>&2)]' mksh -c 'export "$a=$b"'
Linux
$ a='x[0$(uname>&2)]' ksh93 -c 'printf "%d\n" "$a"'
Linux
0
$ a='x[0$(uname>&2)]' ksh93 -c '[ "$a" -gt 0 ]'
Linux
$ a=$'bar/g;e uname>&2\n;s//'; echo foo | sed "s/foo/$a/g"
Linux
bar
$ a='";system("uname");"'; awk "BEGIN{print \"$a\"}"
Linux
$ a=';uname'; sh -c "echo $a"
Linux
Run Code Online (Sandbox Code Playgroud)
这些sed,export...命令可以因为虽然它显然认为更危险eval "$var"会造成的内容$var作为shell代码进行评估,它不是那么明显与sed "s/foo/$var/"或export "$var=value"或[ "$var" -gt 0 ]。危险性是相同的,但它隐藏在其他命令中。
这个例子可能会有所启发:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
Run Code Online (Sandbox Code Playgroud)
上面脚本的输出:
$VAR2
$VAR1
25
Run Code Online (Sandbox Code Playgroud)