我想允许提交用户定义的小型正则表达式进行测试。但是,从无用的服务器使用到更恶劣的eval()
用法,需要考虑许多问题。
据我所知,我已经处理了以下代码中我能想到的所有问题。他们没有想到的任何攻击媒介吗? (我知道一个相当幼稚的问题)
function testRegex($regex)
{
// null character allows a premature regex end and "/../e" injection
if (strpos($regex, 0) !== false || ! trim($regex)) {
return false;
}
$backtrack_limit = ini_set('pcre.backtrack_limit', 200);
$recursion_limit = ini_set('pcre.recursion_limit', 20);
$valid = @preg_match("~$regex~u", null) !== false;
ini_set('pcre.backtrack_limit', $backtrack_limit);
ini_set('pcre.recursion_limit', $recursion_limit);
return $valid;
}
$regexes = array(
"InvalidRegular)Expression",
'',
'\w+',
'\/\w+/',
'foo[bar]*',
'\/\x00known/e' . chr(0x00) . chr(0),
'known~e' . chr(0),
'known~e' . chr(0x00),
'[a-z]+',
'\p{Lu}+',
);
foreach($regexes as $regex) {
var_dump($regex, testRegex($regex));
}
如果您想查看null-byte
注射的示例:
$user_regex = '.+~e' . chr(0);
$user_match = 'system("whoami")';
var_dump(preg_replace("~$user_regex~u", $user_match, 'foo'));
答案 0 :(得分:8)
显然,测试一个字符串是否是一个有效的正则表达式的唯一方法是编译它(这是在你调用任何匹配函数时完成的),所以你正在做的事情很有意义。
您添加的空字节保护实际上不一定是自5.4 ,因为已经在the leader,the middle和the ending中进行了检查。后者尤其是一个相对较新的commit(2011)来修复this bug。
设置较低的回溯和递归限制是一个足够好的沙箱,也许您可以检查最大长度。
也就是说,这个特定的解决方案不能提供使用/s
,/i
和/m
等修饰符的功能。也许这不是你目前关注的主要问题,而是深思熟虑:)
答案 1 :(得分:1)
您可以告诉他们输入类似{expression}的内容然后使用preg_replace()。这样,他们只使用你允许的东西。