Php 有人能解释一下/e正则表达式修饰符吗?

Php 有人能解释一下/e正则表达式修饰符吗?,php,regex,Php,Regex,我目前正在提高对HTML、PHP、JavaScript等安全漏洞的认识。 几个小时前,我在正则表达式中偶然发现了/e修饰符,但我仍然不知道它是如何工作的。我已经看了文档,但这并没有真正的帮助 我所理解的是,可以操纵这个修饰符,使某人有机会在中执行PHP代码(例如,preg\u replace())。我已经看到下面的示例描述了一个安全漏洞,但是没有解释,所以请有人解释一下如何在下面的代码中调用phpinfo() $input = htmlentities(""); if (strpos($inpu

我目前正在提高对HTML、PHP、JavaScript等安全漏洞的认识。 几个小时前,我在正则表达式中偶然发现了
/e
修饰符,但我仍然不知道它是如何工作的。我已经看了文档,但这并没有真正的帮助

我所理解的是,可以操纵这个修饰符,使某人有机会在中执行PHP代码(例如,
preg\u replace()
)。我已经看到下面的示例描述了一个安全漏洞,但是没有解释,所以请有人解释一下如何在下面的代码中调用
phpinfo()

$input = htmlentities("");
if (strpos($input, 'bla'))
{
   echo preg_replace("/" .$input ."/", $input ."<img src='".$input.".png'>", "bla");
}
$input=htmlentities(“”);
if(STRPO($input,'bla'))
{
echo preg_替换(“/”$input./”,$input.“,$bla”);
}

这是邪恶的,你只需要知道:p

更具体地说,它会正常生成替换字符串,然后通过
eval
运行它


您应该改为使用。

这个
e
修饰符是一个特定于PHP的修饰符,它触发PHP以PHP代码的形式运行结果字符串。它基本上是一个包装在正则表达式引擎中的
eval()

eval()
本身被视为安全风险和性能问题;将其包装在正则表达式中会大大放大这两个问题

因此,它被认为是一种不好的做法,并且在即将发布的PHPV5.5中正式被弃用

PHP已经为几个版本提供了另一种解决方案,形式为,它使用回调函数而不是使用
eval()
。这是做这类事情的推荐方法

关于您引用的代码:

在您在问题中给出的示例代码中,我没有看到
e
修饰符。它的两端各有一个斜杠作为正则表达式分隔符;
e
必须在该范围之外,而事实并非如此。因此,我认为您引用的代码可能不会直接受到
e
修改器的攻击

但是,如果
$input
包含任何
/
字符,它将容易被完全破坏(即由于无效的正则表达式而引发错误)。如果它有任何其他东西使其成为无效的正则表达式,则同样适用


因此,将未经验证的用户输入字符串用作正则表达式模式的一部分是一个坏主意-即使您确信不能使用
e
修饰符对其进行黑客攻击,也可能会造成许多其他危害。

如本手册所述,
/e
修饰符实际上将正则表达式处理的文本作为PHP代码进行计算。本手册中给出的示例如下:

$html = preg_replace(
    '(<h([1-6])>(.*?)</h\1>)e',
    '"<h$1>" . strtoupper("$2") . "</h$1>"',
    $html
);
$html=preg\u replace(
“(*?)e”,
“.strtoupper($2”)”,
$html
);
这与任何“
XXXXX
”文本(即标题HTML标记)匹配,将此文本替换为“
”。strtoupper(“XXXXXX”)。“
”,然后执行“
”。strtoupper(“XXXXXX”)。“”
作为PHP代码,然后将结果放回字符串中

如果您在任意用户输入上运行此操作,任何用户都有可能插入一些实际将作为PHP代码计算的内容。如果他做得正确,用户可以利用这个机会执行他想要执行的任何代码。在上面的例子中,想象一下如果在第二步中文本是
”。strtoupper(“.shell('rm-rf/”)。”)。“”

PHP中的
e
Regex修饰符,带有示例漏洞和备选方案 e做了什么,举个例子…


e
修饰符是一个不推荐使用的正则表达式修饰符,它允许您在正则表达式中使用PHP代码。这意味着您解析的内容将作为程序的一部分进行评估

例如,我们可以使用如下内容:

$input = "Bet you want a BMW.";
echo preg_replace("/([a-z]*)/e", "strtoupper('\\1')", $input);
这将输出
打赌您想要一辆宝马。

如果没有
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
编写不受漏洞影响的代码,只是这样做比较困难

你应该用什么来代替…

你应该使用几乎所有的地方,你可以考虑使用<代码> 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
在大多数操作中并不比它的替代品快。对于给定的示例,它的速度是(50000次操作为0.14秒)和(50000次操作为0.32秒)的两倍。

从PHP5.5开始,不推荐使用
e
修饰符。建议改为使用。我认为OP应该接受答案。您的示例既不包含也不需要
e
修饰符。修复了,不确定我为什么会使用该切线。+1,提供了一个清晰的示例。这也说明了为什么它对性能如此有害——14
eval()
在一行代码中调用。哎哟
eval()
已经足够慢了。@Spudley:Perf