如何在 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'),它实际上会创建目录。它似乎工作正常,因为它只是将转换为数字的字符串与另一个数字进行比较,并发现结果是错误的。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
哦哦男孩!
:)
在这种情况下,您必须对输入值至少执行
filter_var()
或is_numeric()
操作。顺便说一句,您使用
eval
的方式(将其结果分配给$success
)在 PHP 中不起作用。您必须将赋值放入 eval()ed 字符串中。Ohhhh boy!
:)
You would have to do at least a
filter_var()
oris_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.如果你这样做。只接受整数。
如果您必须接受字符串,请不要接受。
如果你仍然认为你必须这样做。不!
最后,如果在那之后你仍然认为你需要字符串。只是不要!
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!
是的,任何东西。我将使用
$version = (int)$_REQUEST['version'];
来验证数据。yes, anything. I would use
$version = (int)$_REQUEST['version'];
to validate the data.您需要更准确地定义“恶意”或“安全”。例如,
从常识的角度来看,所有三个片段都是“恶意的”,但从技术上讲它们是完全不同的。可能适用于#1 的保护技术不适用于其他两种,反之亦然。
You need to be more precise with your definitions of "malicious" or "safe". Consider for example
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.
确保安全的方法是在尝试
eval
之前确保$version
是一个数字。The way to make this safe would be to ensure that
$version
is a number BEFORE you try toeval
.使用此代码删除除数字 (0-9) 之外的所有内容: preg_replace('/[^0-9]+/', '', $version);
Use this code to remove everything except numbers (0-9): preg_replace('/[^0-9]+/', '', $version);