原文连接的:http://www.am0s.com/functions/386.html
来自于p师傅小密圈的分享,不得不膜各位师傅。file_put_contents()在写入文件时的第二个参数可以传入数组,如果是数组的话,将被连接成字符串再进行写入。在正则匹配前,传入的是一个数组。得益于PHP的弱类型特性,数组会被强制转换成字符串,也就是Array,Array肯定是满足正则\A[ _a-zA-Z0-9]+\z的,所以不会被拦截。这样就可以绕过类似检测“<?”之类的waf 例如p师傅的实例: - <?php
- $text = $_GET['text'];
- if(preg_match('[<>?]', $text)) {
- die('error!');
- }
- file_put_contents('config.php', $text);
复制代码该代码检测了写入的内容是否存在“<”“>”“?”等字符。根据上面的trick,我们可以通过传入一个数组来达到写入shell的目的。可以看到虽然出错。但config.php确实被写入了。<? php phpinfo();
另一个关于file_put_contents的小trick,当file_put_contents、copy、file_get_contents等读取写入操作与unlink、file_exists等删除判断文件函数之间对于路径处理的差异导致的删除绕过 例如一下代码 - <?php
- $user=$_GET['user'];
- var_dump($user);
- echo $user['name'];
- $filename = __DIR__.'\\'.$user['name'];
- echo $filename;
- $data = $user['info'];
-
- file_put_contents($filename, $data);
- if(file_exists($filename)){
- unlink($filename);
- }
复制代码当file_put_contents和file_exists、unlink等一起使用时可是导致绕过。 p牛在小密圈说过类似问题 查看php源码,其实我们能发现,php读取、写入文件,都会调用php_stream_open_wrapper_ex来打开流,而判断文件存在、重命名、删除文件等操作则无需打开文件流。
我们跟一跟php_stream_open_wrapper_ex就会发现,其实最后会使用tsrm_realpath函数来将filename给标准化成一个绝对路径。而文件删除等操作则不会,这就是二者的区别。
所以,如果我们传入的是文件名中包含一个不存在的路径,写入的时候因为会处理掉“../”等相对路径,所以不会出错;判断、删除的时候因为不会处理,所以就会出现“No such file or directory”的错误。 所以,linux可以通过xxxxx/../test.php、test.php/. 来绕过删除 windows可以通过test.php:test test.ph<来绕过文件删除 拿windows实例: http://127.0.0.1/l.php?user[name]=2.php:test&user[info]=2y 会生成2.php http://127.0.0.1/l.php?user[name]=2.ph<&user[info]=2y 会写入内容
|