如何拒绝使用危险的PHP函数?
可能重复:如何拒绝使用危险的PHP函数?,php,Php,可能重复: 您好,这是我的情况:我必须让我的客户输入PHP代码,但只有安全的函数,如字符串函数,日期函数等。所以我需要危险的PHP函数列表,以删除他们使用字符串替换之前保存到PHP文件。有什么建议吗?别提了。可靠的函数白名单在php中是不可能的。例如: $x = 'e' . str_replace('y', 'x', 'yec'); ...lots of code... $x('format c:'); 现实的选择是 禁用功能() 沙箱(参见) 给用户输入PHP代码的可能性是非常危险的。在
您好,这是我的情况:我必须让我的客户输入PHP代码,但只有安全的函数,如字符串函数,日期函数等。所以我需要危险的PHP函数列表,以删除他们使用字符串替换之前保存到PHP文件。有什么建议吗?别提了。可靠的函数白名单在php中是不可能的。例如:
$x = 'e' . str_replace('y', 'x', 'yec');
...lots of code...
$x('format c:');
现实的选择是
- 禁用功能()
- 沙箱(参见)
- 给用户输入PHP代码的可能性是非常危险的。在实现这一点之前,考虑所有其他选项。某种PHP代码生成器。灵感来源于查询生成器
如果您决定允许客户端使用PHP代码,最好使用白名单。您应该使用正则表达式从发布的代码中提取这些函数。如果您想正确执行,您需要做的是非常艰苦的工作。我将从输入的php代码开始,检查每个被调用的函数,完全禁止,等等
换句话说:如果你想允许一个子集的PHP,你必须实现你自己的(即使PHP为你提供了一个开箱即用的工具)。据我所知,你只能使用黑名单方法:
更新:我错误地认为
token\u get\u all()。它们都是T_STRING
s.最安全和易于维护的选项是用php编写专用的“迷你语言”。您可以将其作为php的一个子集,或使其看起来像Excel公式,甚至可以发明自己的公式。这样,您将始终能够完全控制正在发生的事情
//
只是为了好玩,这里有一个小口齿不清给你
function lisp($x) {
if(is_string($x)) {
$re = '~\(([^()]*)\)~';
while(preg_match($re, $x))
$x = preg_replace_callback($re, 'lisp', $x);
return trim($x);
}
$x = preg_split('~\s+~', $x[1]);
$e = array_shift($x);
if(!$x)
return is_numeric($e) ? floatval($e) : $e;
switch($e) {
case '+': return lisp($x[0]) + lisp($x[1]);
case '-': return lisp($x[0]) - lisp($x[1]);
case '*': return lisp($x[0]) * lisp($x[1]);
case '/': return lisp($x[0]) / lisp($x[1]);
case 'concat': return lisp($x[0]) . lisp($x[1]);
}
return function_exists($e) ?
call_user_func_array($e, array_map('lisp', $x)) : '';
}
$input = '
(strtolower
(concat
(strrev olleh)
(+ 22 20)))';
echo lisp($input); // hello42
()) PHP不是一种正规语言。@Gumbo:请解释这与这种情况有什么关系?@Stegeman你不能在一种非正规语言上使用正则表达式。也许我错了,但他说的是enter,据我理解,这意味着他将发布代码。在这种情况下,代码只是一个字符串,可以在字符串上使用正则表达式,不是吗?如果他想上传代码,我知道我错了。只是想了解和学习一下:)@Stegeman:当然你可以在字符串上使用正则表达式。但是字符串中的数据(即PHP代码)不是常规语言。只需考虑删除PHP代码中的foobar
函数调用:@stereofrog,这就是我不推荐它的原因。请随意编辑我的答案,以减少混淆。我不擅长解释,难道这不应该是“可靠的函数白名单在PHP中是不可能的”吗?因为禁用函数可以将其列入黑名单。没有注意到,我会编辑它:p.+1,我不明白为什么人们会将这些问题过于复杂,过于复杂并不会使其更安全,请坚持使用原始方法,例如禁用函数
和禁用类
@stereofrog,我已经明白了你的意思(你并没有说),并相应地编辑了我的文章。PHP.net的令牌文档非常缺乏。他们遗漏了某些标记,也错误地定义了一些标记——或者是这些标记,或者它们的用法是由token\u get\u all()
和PHP的警告/错误消息所决定的,它们是由后者决定的。@stereofrog:当然,你是对的。这甚至不值得尝试。这可能需要大量的工作。您可以制作一个动态范围的lisp-1。你不必告诉他们这是口齿不清。或者,如果您愿意,您可以使用LIME for PHP实现中缀代数,也许可以在[方括号]中实现,并制作类似于TCL的东西。为什么它必须看起来像PHP?或者您可以在PHP中编写PHP子集的解析器,并只运行选定的函数!:D