我正在接管一些在 php中使用eval()函数的网页游戏代码。我知道这可能是一个严重的安全问题,因此在我决定是否取消该部分代码之前,我需要一些帮助来审查检查其参数的代码。目前我已经从游戏中删除了这部分代码,直到我确定它是安全的,但功能的损失并不理想。我宁愿对此进行安全证明,也不愿重新设计整个段以避免使用 eval(),假设这样的事情是可能的。据称可以防止恶意代码注入的相关代码片段如下。$value 是一个用户输入的字符串,我们知道它不包含“;”。
1 $value = eregi_replace("[ \t\r]","",$value);
2 $value = addslashes($value);
3 $value = ereg_replace("[A-z0-9_][\(]","-",$value);
4 $value = ereg_replace("[\$]","-",$value);
5 @eval("\$val = $value;");
Run Code Online (Sandbox Code Playgroud)
到目前为止,这是我的理解:
1) 从 $value 中删除所有空格
2)转义数据库调用需要它的字符(我不清楚为什么需要它)
3) 查找字母数字字符后紧跟 \ 或 ( 并用 - 替换它们的组合。大概这是为了删除字符串中与函数调用类似的任何内容,尽管我不清楚为什么它还删除前面的字符,这就是为什么在第 2 行明确添加它们之后,它也会删除 \。
4) 用 - 替换 $ 的所有实例,以避免任何类似于对字符串中 php 变量的引用。
那么:这里有没有留下任何漏洞?我是否误解了上面的任何正则表达式?最后,有没有办法在不排除 ( 字符?要输入的字符串是理想的数学公式的情况下对此进行安全证明,并且允许 ( 将允许操作操作顺序,目前这是不可能的。
评估虚拟机内的代码 - 请参阅Runkit_Sandbox
或者为您的数学创建一个解析器。我建议您使用内置的分词器。您需要迭代标记并跟踪括号、T_DNUMBER
、T_LNUMBER
、 运算符,也许还有T_CONSTANT_ENCAPSED_STRING
。忽略其他一切。然后您可以安全地计算结果表达式。
谷歌快速搜索发现了这个库。它正是你想要的......
使用分词器的简单示例:
$tokens = token_get_all("<?php {$input}");
$expr = '';
foreach($tokens as $token){
if(is_string($token)){
if(in_array($token, array('(', ')', '+', '-', '/', '*'), true))
$expr .= $token;
continue;
}
list($id, $text) = $token;
if(in_array($id, array(T_DNUMBER, T_LNUMBER)))
$expr .= $text;
}
$result = eval("<?php {$expr}");
Run Code Online (Sandbox Code Playgroud)
(测试)
仅当输入是有效的数学表达式时,这才有效。否则,由于空括号和类似的东西,您将在评估代码中遇到解析错误。如果您也需要处理这个问题,请清理另一个循环内的输出表达式。这应该可以解决大部分无效部分:
while(strpos($expr, '()') !== false)
$expr = str_replace('()', '', $expr);
$expr = trim($expr, '+-/*');
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
4509 次 |
最近记录: |