「作者主页」:士别三日wyx
「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者
文件包含漏洞
一、什么是文件包含漏洞?
文件包含漏洞常出现在「PHP语言」中。
PHP为了提高「代码复用性」,提供了文件包含函数
include()
和
require()
,被包含的文件内容会被当做代码来执行。
就像造轮子一样:把「重复使用」的一段代码,单独写到一个文件里,再用文件包含函数来包含这个文件。
为了灵活的包含文件,一些程序员会把文件名通过「参数」的形式传递给文件包含函数。
当传递文件名的参数可以被用户「修改」时,用户就可以包含任意文件,而文件中的代码就会被服务器执行,这就造成了文件包含漏洞。
二、文件包含函数
PHP提供了四个文件包含函数:
- include() :当被包含的文件不存在时,会报错(Error),后面的代码不被执行。
- include_once() :只包含一次,包含过的文件不会被重复包含。
- require() :当被包含的文件不存在时,会告警(Wrainng),后面的代码可以继续执行。
- require_once() :只包含一次,包含过的文件不会被重复包含。
文件包含函数「不关心」文件的「后缀名」,它只是简单的执行被包含的文件,如果文件的内容是代码,就会执行代码;如果不是代码,就当做文本输出到页面。这个特点在后面的练习中可以体现出来。
三、两种文件包含
文件包含漏洞根据包含文件的「位置」可以分为「本地文件包含」和「远程文件包含」。
1、本地文件包含
本地文件包含是指:包含「服务器本地」的文件。
本地文件包含的payload通常以根目录(/)或文件名开头。也就是绝对路径和相对路径。
利用条件:
- 配置文件开启fopen(
allow_url_fopen=On
) - 用户可控参数,后台未过滤包含的文件。
1.1 使用教程演示
我们拿DVWA中的 File Injection 模块,简单了解一下本地文件包含的使用。
功能很简单:点不同的链接,跳转到对应的文件。
在地址栏中,手动修改page的参数为
file1.php
和
file2.php
,页面也会跳转到对应的页面,本质上是后台用文件包含函数 包含了这个文件。
这意味着「参数可控」,我们可以通过修改page的参数,让页面包含指定的文件,前提是文件存在。
我们提交账号文件的路径,在地址栏输入
/etc/passwd
:
可以看到,页面显示了passwd文件的内容。我们可以修改成其他的文件名,来包含服务器上其他的文件。
2、远程文件包含
远程文件包含是指:包含「远端」的文件。
远程文件包含的payload通常以
http://
或
ftp://
开头。
利用条件:
- 配置文件开启 fopen 和 include(allow_url_include=On)
- 用户参数可控,且后台没有过滤包含的文件。
1.1 使用教程演示
还是拿DVWA中的 File Injection 模块,简单了解一下远程文件包含的使用。
地址栏提交一个某牛的主页文件:
可以看到,页面包含了这个文件,网下滑可以看到,DVWA的页面被顶到下面去了:
这意味着,我们包含的远端文件,被执行了。我们可以更换其他远端文件
四、配置文件
PHP的配置文件 php.ini 中,有两个文件包含相关的配置:allow_url_fopen、allow_url_include。
可以根据这两个配置项来判断,文件包含漏洞是否存在。
1、allow_url_fopen
所有版本默认开启。
开启后,可以把
http://
和
ftp://
形式的URL当成文件打开。
allow_url_fopen=On,允许打开URL文件。
allow_url_fopen=Off,禁止打开URL文件。
2、allow_url_include
PHP5.2开始默认关闭。
开启后,文件包含函数
include()
和
require()
可以把
http://
和
ftp://
形式的URL当成文件打开。
allow_url_include=On,允许包含URL文件。
allow_url_include=Off,禁止包含URL文件。
禁用 fopen 和 include,只能防止
http://
和
ftp://
这种URL文件的,对5.2版本提供的php和data则无能为力。
五、PHP伪协议
PHP提供了一些「伪协议」,这些伪协议可以帮助我们更好的使用文件包含。
1、php://filter
php://filter 常用来「读取文件源码」。
php文件被包含时,里面的代码会被执行,我们就看不到文件中的内容了。
1)用 php://filter 把文件内容进行base64编码,编码后的内容不会被当做代码执行,而是在页面中显示出来。我们复制下来用工具解码,就能拿到文件的源码了。使用格式如下:
?url=php://filter/read=convert.base64-encode/resource=phpinfo.php
前面是固定格式,只需要把后面的 phpinfo.php换成其他文件就可以了。
2、php://input
php://input 会把「post请求体」的内容当做文件执行,导致任意代码执行。
1)GET请求参数中使用 php://input 伪协议:
?url=php://input
2)(配合其他工具)post请求体中,写需要执行的代码:
<?phpsystem('ls');?>
enctype=multipart/form-data 时,php:/input 无法使用。
3、phar://
phar:// 可以「读取压缩文件」。
1)把代码文件压缩成zip格式,再上传到服务器(配合文件上传漏洞)。
2)用 phar:// 从服务器中读取压缩文件中的文件。
?url=phar://temp/shell.zip/shell.txt
提示:读取时,注意压缩文件中,目录的层级关系。
4、zip://
zip:// 可以「读取压缩文件」
1)把代码文件压缩成zip格式,再上传到服务器(配合文件上传漏洞)。
2)用zip:// 从服务器中读取压缩文件中的文件。
?url=phar://temp/shell.zip%23shell.txt
提示:zip:// 与 phar:// 相似,他们有两个区别
- zip:// 只能读取单级目录,而 phar:// 可以读取多级目录
- 压缩文件中的分隔符
/
需要换成%23
(/ 换成 # 后 再url编码成 %23)
5、data://
data:// 常用来「任意代码执行」
与php://input 相似,不同的是,php://input是将post请求体中的内容当做文件执行,而data://将GET请求中,逗号后面的内容当做文件执行。
方式一:
data://text/plain,
逗号后面的内容,以纯文本形式执行
?url=data://text/plain,<?php phpinfo();?>
方式二:
data://text/html,
逗号后面的内容,以html形式解析
?url=data://text/html,<?php phpinfo();?>
方式三:
data://text/plain;base64,
先把需要执行的命令进行base64编码;
逗号后面的内容,先base64解码,再以纯文本形式执行(一种绕过方式)
?url=data://text/plain;base64,JTNDJTNGcGhwJTIwcGhwaW5mbyUyOCUyOSUzQg==
提示:
JTNDJTNGcGhwJTIwcGhwaW5mbyUyOCUyOSUzQg==
是
<?php phpinfo();
base64加密的结果,加密代码时,后面不要加
?>
,否则会报语法错误。
六、包含日志
包含日志文件,文件内容会显示到页面中,如果日志中包含代码,则会被执行。
1、包含Web访问日志
1)包含Web日志(Nginx日志路径:
/usr/local/nginx//access_log
),页面显示出日志内容。
2)Burp Suite修改访问请求,将代码写入Web日志。
3)再次访问Web日志,日志中的代码将被执行。
2、包含ssh登录日志
1)ssh登录
ssh "<?php phpinfo();?>"@192.168.0.1
,代码被记录到登录日志中。
2)包含日志文件,默认路径
/var/log/auth.log
或
/var/log/secure
,日志中的代码将被执行。
版权归原作者 士别三日wyx 所有, 如有侵权,请联系我们删除。