文件包含漏洞学习总结

什么是文件包含

简单一句话,为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含函数将文件包含进来,直接使用包含文件的代码。

文件包含漏洞成因

在包含文件时候,为了灵活包含文件,将被包含文件设置为变量,通过动态变量来引入需要包含的文件时,用户可以对变量的值可控而服务器端未对变量值进行合理地校验或者校验被绕过,这样就导致了文件包含漏洞。通常文件包含漏洞出现在PHP语言中。

PHP文件包含的函数
  • include( )
    当使用该函数包含文件时,只有代码执行到 include()函数时才将文件包含
    进来,发生错误时之给出一个警告,继续向下执行。
  • include_once( )
    功能与 Include()相同,区别在于当重复调用同一文件时,程序只调用一次
  • require( )
    require()与 include()的区别在于 require()执行如果发生错误,函数会输出
    错误信息,并终止脚本的运行。
  • require_once( )
    功能与 require()相同,区别在于当重复调用同一文件时,程序只调用一次。
文件包含漏洞分类
  • 本地文件包含漏洞

当包含的文件在服务器本地时,就形成了本地文件包含。

下面简单做个测试:

先说一下文件包含的一个要点:文件包含可以包含任意文件,即便被包含的文件并不是与当前编程语言相关,甚至为图片,只要文件被包含,其内容会被包含文件包含,并以当前服务器脚本语言执行。
可以看到,以上代码中可以控制可控参数file来控制包含的$file的值。

  1. 因此可以建立随意后缀文件进行包含,比如新建文件file.txt,文件内容如下:

然后包含file.txt文件:

image.png

如果包含的文件内容不符合php语言语法的,会直接将文件内容输出,比如:

image.png
  1. 接下来再看一种情况,开发者限制了包含文件的后缀,代码如下:

这样就找不到要包含的文件了,如下:

image.png

此时,可以使用%00截断,不过需要有前提条件:
1). PHP版本 < 5.3 (不包括5.3) ;
2). PHPmagic_quotes_gpc = off;
3).PHP对所接收的参数,如以上代码的$_GET['file']未使用addslashes函数。

因为PHP大于等于5.3的版本已经修复了这个问题,如果开启了gpc或者使用了addslashes函数的话则会对其进行转义

首先看php版本小于5.3,并且magic_quotes_gpc = Off1.php内容如下

";
include($file);
phpinfo();
image.png

那么我们看magic_quotes_gpc = On是什么情况呢(效果与使用函数的为一致)

image.png

接下来看php版本为5.3的情况。

image.png

可以看到。是没有任何效果的。

总结
对于限制了包含文件后缀的情况,PHP版本小于5.3,php.inimagic_quotes_gpc = off,对可控参数未使用addslashes函数,满足这三个条件就可以使用%00截断。

那么这两种包含有什么区别呢?其实是没有区别的,原理都一样,只不过第一种是将后缀一起传入,第二种则在程序内固定死了后缀。但是在满足一定条件下可以使用%00,因为当程序流遇到%00终止符的时候将直接终止。

  1. 除此之外,还有包含Apache 日志文件。
    具体不再讲解,简单直接做一遍一看就懂了。
    首先第一步:
image.png
image.png

此处后来又看到一个骚姿势,开始是访问路径由于url编码原因需要抓包再修改,稍微麻烦,后来看到使用可以直接写进User Agent里面也可以被写进日志里,厉害了。

第二步:本地包含日志文件

图片.png

注意:开始明明php代码写进日志文件里面了,可怎么也包含不成功,弄了好久才发现httpd文件夹其他用户没有x权限,此处记录下哈!

  • 远程文件包含漏洞

当包含的文件在远程服务器上时,就形成了远程文件包含。

远程文件包含的注意点:
1). 需要php.iniallow_url_include = on以及allow_url_fopen=on
2). 所包含远程服务器的文件后缀不能与目标服务器语言相同。(比如目标服务器是php脚本语言解析的,那么包含的远程服务器文件后缀不能是php)

主要解释下第2点:
比如远程服务器文件yuancheng.php,内容为:


image.png

再来看下目标服务器的信息

image.png

接下来目标服务器包含远程服务器上的文件yuancheng.php

image.png

可以看到包含后得到的结果是我们远程机的信息,而不是我们想要的目标机信息。为什么呢?
因为目标服务器包含的代码并不是:


而是而是远程服务器执行完这段代码的源代码,如下图:


image.png

所以说远程文件包含只有符合了以上两点才能正常包含。


因此,正确远程包含文件漏洞利用如下:
首先确保配置文件allow_url_fopen = On以及allow_url_include = On,如果修改为On记得重启服务

image.png

其次,修改文件后缀,只要不是php就行,比如后缀为.txt,然后再来包含。

image.png

很明显,这次就是我们想要获取的信息了。
接下来就尝试拿webshell了。

image.png
image.png

文件包含漏洞之伪协议

伪协议在文件包含的利用,本文演示以下伪协议:
data:text/plaindata:text/plain;base64
php://input
php://filter
file://
zip://

其它协议可阅读官方文档:传送门

  • data:text/plain

直接在对应URL参数内输出:data:text/plain,,需要执行的php代码 如下图:

image.png

这个伪协议还有另一种使用方法,那么就是将需要执行的php代码使用base64编码:data:text/plain;base64,,需要执行的base64编码后的php代码如下图:

image.png

此处开始在浏览器使用hackbar测试不成功,寻其原因,应该是hackbar有问题。

注意:这里base64编码的php代码不能有;
补充修正:回看写的这个,有问题,不知道之前怎么写的,写了句这话,后经思考应该是base64编码为PD9waHAgcGhwaW5mbygpOz8+,里面有+,所以应该是这个原因,故可以写为PD9waHAgcGhwaW5mbygpOz8%2b即可。


  • php://input

php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。

图片.png

  • php://filter

php://filter 该伪协议可以读取php文件代码以base64编码输出,比如说我们想读取一个php文件但是不想让它正常php执行代码后的结果,我们想要这个php文件的代码的时候就可以使用这个伪协议。

使用方法:php://filter/read=convert.base64-encode/resource=需要读取源码的文件名

image.png
image.png

  • file://

file:// 用于访问本地文件系统,且不受allow_url_fopenallow_url_include的影响。
使用方法:file://文件绝对路径 file://C:/Windows/system.ini

image.png

  • zip://

zip://可以访问压缩文件中的文件。但是需要绝对路径。
使用方法: zip://[压缩包绝对路径]#[压缩文件内的文件名]

在本地创建一个文件2.php,并且压缩成2.zip压缩包,然后包含压缩包里面的文件:

image.png

可以看到我已经填写了绝对路径以及文件名称,但是为什么不能成功包含呢,可以看到它的报错Warning: include(zip://E:/soft/phpmystudy/WWW/file_include/2.zip): 我们并不是包含这个压缩包,我们是要包含这个zip里面的文件,为什么#后面的值没了呢,是因为#和URL规则里面的#冲突了,所以我们需要使用编码%23的形式,如下图:

image.png

附:php伪协议深入理解

文件包含漏洞防御
  1. PHP 中使用 open_basedir 配置限制访问在指定的区域
  2. 过滤.(点)/(反斜杠)\(反斜杠)
  3. 禁止服务器远程文件包含

参考

文章1
文章2
文章3
文章4
文章5

你可能感兴趣的:(文件包含漏洞学习总结)