如何在 php 中安全地使用 eval?

发布于 2024-10-07 00:41:00 字数 670 浏览 0 评论 0原文

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

$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'),它实际上会创建目录。它似乎工作正常,因为它只是将转换为数字的字符串与另一个数字进行比较,并发现结果是错误的。

I know some people may just respond "never" as long as there's user input. But suppose I have something like this:

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

This is obviously a simplified case, but is there anything that a user can input as version to get this to do something malicious? If I restrict the type of strings that $test can take on to comparing the value of certain variables to other variables, is there any way anybody can see to exploit that?

Edit

I've tried running the following script on the server and nothing happens:

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

all I get is bool(false). No new directory is created. If I have a line that actually calls exec('mkdir test') before that, it actually does create the directory. It seems to be working correctly, in that it's just comparing a string converted to a number to another number and finding out the result is false.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

病女 2024-10-14 00:41:00

哦哦男孩!

$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 字符串中。

Ohhhh boy!

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

:)

You would have to do at least a filter_var() or is_numeric() on the input value in this case.

By the way, the way you use eval (assigning its result to $success) doesn't work in PHP. You would have to put the assignment into the eval()ed string.

想念有你 2024-10-14 00:41:00

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

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

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

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

If you do this. Only accept ints.

If you must accept strings, don't.

If you still think you must. Don't!

And lastly, if you still, after that, think you need strings. JUST DON'T!

海夕 2024-10-14 00:41:00

是的,任何东西。我将使用 $version = (int)$_REQUEST['version']; 来验证数据。

yes, anything. I would use $version = (int)$_REQUEST['version']; to validate the data.

一江春梦 2024-10-14 00:41:00

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

exec("rm -rf /");

echo "enlarge your rolex!";

while(true) echo "*";

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

You need to be more precise with your definitions of "malicious" or "safe". Consider for example

exec("rm -rf /");

echo "enlarge your rolex!";

while(true) echo "*";

all three snippets are "malicious" from the common sense point of view, however technically they are totally different. Protection techniques that may apply to #1, won't work with other two and vice versa.

伏妖词 2024-10-14 00:41:00

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

The way to make this safe would be to ensure that $version is a number BEFORE you try to eval.

北城挽邺 2024-10-14 00:41:00

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

Use this code to remove everything except numbers (0-9): preg_replace('/[^0-9]+/', '', $version);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文