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
修饰符。这是一个您可以很容易遇到的问题的示例:e
$password = 'secret';
...
$input = $_GET['input'];
echo preg_replace('|^(.*)$|e', '"\1"', $input);
如果我将输入提交为"$password"
,则此函数的输出将是secret
。因此,对我来说访问会话变量非常容易,所有变量都在后端使用,甚至可以eval('cat /etc/passwd');
通过这段简单的写得不好的代码对您的应用程序进行更深层次的控制(?)。
与类似被弃用的mysql
库一样,这并不意味着您不能使用 编写不受漏洞影响的代码e
,只是这样做更难。
你应该改用什么......
您应该在几乎所有您会考虑使用修饰符的地方使用preg_replace_callback 。e
在这种情况下,代码绝对没有那么简短,但不要让它愚弄你——它的速度是原来的两倍:
$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 修改器(50,000 次操作为 0.32 秒)