最近看 P 神以前写的文章,其中在 3 个参数的回调函数中提到了 preg_replace /e 命令执行,对这块不是很熟悉的我特此写这篇文章总结学习一下。
preg_matchint preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
preg_match 函数用于执行一个正则表达式匹配
参数
说明
$pattern
要搜索的模式,字符串形式。
$subject
要搜索检测的目标字符串
$matches
如果提供了参数matches,它将被填充为搜索结果 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。
$flags
$offset
可选参数 offset 用于指定从目标字符串的某个未知开始搜索(单位是字节)。
preg_replace
preg_replace — 执行一个正则表达式的搜索和替换
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed
搜索subject中匹配pattern的部分, 以replacement进行替换。
参数
说明
$pattern
要搜索的模式,可以是字符串或一个字符串数组
$replacement
用于替换的字符串或字符串数组
$subject
要搜索替换的目标字符串或字符串数组
$limit
可选,对于每个模式用于每个 subject 字符串的最大可替换次数。 默认是-1(无限制)
$count
可选,为替换执行的次数
如果subject是一个数组, preg_replace()返回一个数组, 其他情况下返回一个字符串。
如果匹配被查找到,替换后的subject被返回,其他情况下 返回没有改变的 subject。如果发生错误,返回 NULL 。
场景1 嵌套双写绕过
依然来使用 XSS 的例子:
error_reporting(0);
$name = $_GET["name"];
$name = preg_replace('/script/i','',$name);
echo $name;
?>
虽然使用了 /i 匹配大小写字母,但是逻辑有问题,只是仅仅将关键词替换为空,可以使用嵌套双写绕过:
http://x.x.x.x/xxx.php?name=alert(2333)
类似这种过滤逻辑,在 str_replace 函数中也常见到:
$name = str_replace( 'script', '', $_GET[ 'name' ] );
嵌套双写的加固方法: