我怎样才能在php中安全地使用eval?

时间:2010-12-09 15:39:48

标签: php eval

我知道只要有用户输入,有些人可能只会回答“从不”。但是假设我有这样的事情:

$version = $_REQUEST['version'];
$test = 'return $version > 3;';
$success = eval($test);

这显然是一个简化的案例,但是有什么用户可以输入version来让它做恶意的事吗?如果我限制$test可以采用的字符串类型来将某些变量的值与其他变量进行比较,那么有没有人可以看到利用它?

修改

我已尝试在服务器上运行以下脚本,但没有任何反应:

<?php
  $version = "exec('mkdir test') + 4";
  $teststr = '$version > 3;';
  $result = eval('return ' . $teststr);
  var_dump($result);
?>

我得到的只是bool(false)。没有创建新目录。如果我之前有一行实际调用exec('mkdir test'),它实际上会创建目录。它似乎工作正常,因为它只是将转换为数字的字符串与另一个数字进行比较,并发现结果为false。

6 个答案:

答案 0 :(得分:3)

哦,小男孩!

$version = "exec('rm-rf/...') + 4"; // Return 4 so the return value is "true" 
                                    // after all, we're gentlemen!
$test = "return $version > 3"; 
eval($test);

:)

在这种情况下,您必须至少对输入值filter_var()is_numeric()

顺便说一下,使用eval(将结果分配给$success)的方式在PHP中不起作用。您必须将赋值放入eval()ed字符串中。

答案 1 :(得分:3)

如果你这样做。只接受整理。

如果你必须接受字符串,请不要。

如果你仍然认为你必须这样做。不要!

最后,如果你仍然在那之后,认为你需要字符串。只是不要!

答案 2 :(得分:1)

是的,什么都有。我会使用$version = (int)$_REQUEST['version'];来验证数据。

答案 3 :(得分:0)

确保此安全的方法是在尝试$version之前确保eval是一个数字。

答案 4 :(得分:-1)

您需要更准确地定义“恶意”或“安全”。考虑例如

exec("rm -rf /");

echo "enlarge your rolex!";

while(true) echo "*";
从常识的角度来看,所有三个片段都是“恶意的”,但从技术上讲,它们完全不同。可能适用于#1的保护技术不适用于其他两种,反之亦然。

答案 5 :(得分:-2)

使用此代码删除除数字(0-9)以外的所有内容:preg_replace('/ [^ 0-9] + /','',$ version);