PHP 中的e 正则表达式修饰符以及示例漏洞和替代方法
e 做了什么,举个例子……
e 修饰符是一个已弃用的正则表达式修饰符,它允许您在正则表达式中使用 PHP 代码。这意味着您解析的任何内容都将作为程序的一部分进行评估。
例如,我们可以这样使用:
$input = "Bet you want a BMW.";
echo preg_replace("/([a-z]*)/e", "strtoupper('\\1')", $input);
这将输出BET YOU WANT A BMW.
如果没有 e 修饰符,我们会得到这个非常不同的输出:
strtoupper('')Bstrtoupper('et')strtoupper('') strtoupper('you')strtoupper('') strtoupper('want')strtoupper('') strtoupper('a')strtoupper('') strtoupper('')Bstrtoupper('')Mstrtoupper('')Wstrtoupper('').strtoupper('')
e 的潜在安全问题...
e 修饰符是 deprecated for security reasons。这是一个使用e 很容易遇到的问题示例:
$password = 'secret';
...
$input = $_GET['input'];
echo preg_replace('|^(.*)$|e', '"\1"', $input);
如果我将输入提交为"$password",则此函数的输出将为secret。因此,对我来说访问会话变量非常容易,所有变量都在后端使用,甚至可以通过这段写得不好的简单代码对您的应用程序进行更深层次的控制 (eval('cat /etc/passwd');?)。
与同样被弃用的mysql 库一样,这并不意味着您不能使用e 编写不受漏洞影响的代码,只是这样做更难。
你应该改用什么...
您应该在几乎所有您会考虑使用e 修饰符的地方使用preg_replace_callback。在这种情况下,代码绝对没有那么简短,但不要被它欺骗了——它的速度是原来的两倍:
$input = "Bet you want a BMW.";
echo preg_replace_callback(
"/([a-z]*)/",
function($matches){
foreach($matches as $match){
return strtoupper($match);
}
},
$input
);
在性能方面,没有理由使用e...
与mysql 库(出于安全目的也已弃用)不同,e 在大多数操作中并不比它的替代品快。对于给出的示例,它的速度要慢两倍:preg_replace_callback(50,000 次操作为 0.14 秒)vs e modifier(50,000 次操作为 0.32 秒)