1.文件包含漏洞概述
1.1什么是文件包含
开发人员将需要重复调用的函数写入一个文件,对该文件进行包含时产生的操作。这样编写代码能减少代码冗余,降低代码后期维护难度。保证网站整体风格统一。
1.2漏洞产生原因
文件包含函数加载的参数没有经过过滤或严格定义,可以被用户控制,包含其他恶意文件,导致了执行非预期代码。
下面是一个例子。网页代码如下:
再创建一个phpinfo的页面,代码如下:
利用文件包含,我们可以通过include函数来执行phpinfo页面,成功解析
将phpinfo文件的后缀改为txt后进行访问,依然可以解析
改为jpg格式,也可以解析
可以看出,include()函数不在意被包含的文件是什么类型,只要有php代码,都会被解析。
在文件上传漏洞中,上传一个jpg格式的一句话木马,如果网站有文件包含漏洞,jpg文件就可以被当做php文件解析,所以这就是文件上传漏洞通常配合文件上传使用。
PHP中的文件包含函数
-
require组:
require:函数出现错误时,会直接报错并退出程序执行。
require_once:出错时直接退出,且仅包含一次。
-
include组:
include:函数出现错误时,会抛出一个警告,程序继续运行。
include_once:函数出现错误时,会抛出警告,且仅包含一次。
2.文件包含漏洞类型及利用
2.1本地文件包含LFI
被包含的文件在服务器本地
利用方式:包含本地敏感文件、上传文件
测试网页代码如下:
利用该代码,我们可以读取一些系统本地的敏感信息。
例如:C:\Windows\system.ini
文件
-
使用绝对路径
2. 使用相对路径
通过./表示当前位置路径,…/表示上一级路径位置,在linux中同样适用。
例如:../../windows/system.ini
一些常见的敏感目录信息路径
-
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/password //账户信息 /etc/shadow //账户密码信息 /usr/local/app/apache2/conf/httpd.conf //Apache2默认配置文件 /usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置 /usr/local/app/php5/lib/php.ini //PHP相关配置 /etc/httpd/conf/httpd.conf //Apache配置文件 /etc/my.conf //mysql配置文件
LFI漏洞利用技巧
-
file://
协议file://
用于访问本地文件系统,在ctf中通常用来读取本地文件,且不受allow_url_fopen与allow_url_include的影响。格式:
file://
文件的绝对路径和文件名 -
php://filter伪协议
主要用来查看源码,直接包含php文件时会被解析,不能看到源码,故使用filter协议来读取
php://filter伪协议可以用于如下函数:
include();
file();
file_get_contents();
readfile();
file_put_contents();
一般使用方法:
php://filter/ [read|write =]过滤器|过滤器/resource=要过滤的数据流 conversion filter(转换过滤器) convert.base64-encode & convert.base64-decode(base64加密解密) 例如:php://filter/convert.base64-encode/resource=flag.php
过滤器可以设置多个
php://filter读取源代码并进行base64编码输出,例如一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个PHP文件,PHP代码是不会显示到页面上的,例如:
他只显示了一条语句,这时我们可以以base64编码的方式读取指定文件的源码:
-
php://input协议
input协议可以访问请求的原始数据的制度刘,将post请求中的数据作为PHP代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容作为文件内容,从而导致任意代码的执行。
利用该方法,我们可以直接写入php文件,输入
file=php://input
,然后用burp抓包,写入PHP代码: -
data://text/plain协议
同样类似php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当做php文件执行,从而导致任意代码执行。
利用data://伪协议可以直接达到执行php代码的效果,例如执行phpinfo();
格式:
data://text/plain,流
例如:
data://text/plain,<?php phpinfo();?> //如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入: data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
-
zip://、bzip://、zlib://协议
都属于压缩流,可以访问压缩文件中的子文件。
格式:zip://[压缩文件绝对路径]#[压缩文件内的子文件名]
-
phar://协议
类似于zip协议,但是可以使用相对路径。
格式:phar://[压缩文件绝对/相对路径]/[压缩文件内的子文件名]
伪协议利用方法总结:
2.2远程文件包含RFI
被包含的文件在远程服务端
利用方式:包含攻击者指定远程url文件。
如果PHP的配置选项allow_url_include、allow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含
首先我们来看一段代码
<?php $path=$_GET['path']; include($path . '/phpinfo.php'); ?>
访问本地site目录下 的phpinfo.php文件:
该页面没有对$path做任何过滤,因此存在文件包含漏洞。
我们在远端web服务器/site/目录下创建一个test.php文件,内容为phpinfo(),利用漏洞去读取这个文件。
但是代码会给我们输入的路径后面加上'/phpinfo.php'后缀,如果php版本小于5.3.4,我们可以尝试使用%00截断,这里php版本为7.3.4,不适用
还有一种截断方式是?截断,在路径后面输入?,服务器会认为?后面的内容为GET方法传递的参数,成功读取test.php如下:
如果test.php是恶意的webshell文件,那么利用该漏洞可以获取到服务器权限。