当前位置: 首页 > news >正文

ThinkPHP5漏洞分析之文件包含

目录

漏洞概要

漏洞环境

环境搭建

配置

测试:

漏洞分析:

extract: 

参数

Lua::assign

示例

array_merge

说明

返回值

 array_merge() 示例

fetch:

漏洞修复


漏洞概要

本次漏洞存在于 ThinkPHP 模板引擎中,在加载模版解析变量时存在变量覆盖问题,而且程序没有对数据进行很好的过滤,最终导致 文件包含漏洞 的产生。漏洞影响版本: 5.0.0<=ThinkPHP5<=5.0.185.1.0<=ThinkPHP<=5.1.10

漏洞环境

thinkphp5.0.10

环境搭建

GitHub - top-think/think at v5.0.10

GitHub - top-think/framework at v5.0.10

将这两个文件下载到本地,将framework改名为thinkphp放到think-5.0.10中。

原因是我们要加载的thinkphp框架默认路径写的是thinkphp

这里使用的是nginx,所以将文件放在nginx文件夹下了,这都不重要,根据自己情况决定。

将think-5.0.10改名为tp5010了,这个改不改不影响。

配置

application/index/controller/Index.php 文件代码设置如下:

<?php
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{public function index(){$this->assign(request()->get());return $this->fetch(); // 当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html}
}

创建 application/index/view/index/index.html 文件,内容随意(没有这个模板文件的话,在渲染时程序会报错)

到这里就可以访问了,我这里什么都没写,但是可以访问。。。

http://localhost/tp5010/public/index.php

测试:

写了一个图片马放到public文件下,访问该图片马即可触发 文件包含漏洞

使用蚁剑连接

http://192.168.10.128/tp5010/public/index.php?cacheFile=open.png

成功添加,可以看到已经成功

漏洞分析:

在官方发布的 5.0.19 版本更新说明中,发现其中提到该版本包含了一个安全更新

我们可以查阅其 commit 记录,发现其改进了模板引擎,其中存在危险函数 extract ,有可能引发变量覆盖漏洞。接下来,我们直接跟进代码一探究竟。

extract: 

参数

array

一个关联数组。此函数会将键名当作变量名,值作为变量的值。 对每个键/值对都会在当前的符号表中建立变量,并受到 flags 和 prefix 参数的影响。

必须使用关联数组,数字索引的数组将不会产生结果,除非用了 EXTR_PREFIX_ALL 或者 EXTR_PREFIX_INVALID

flags

对待非法/数字和冲突的键名的方法将根据取出标记 flags 参数决定。可以是以下值之一:

EXTR_OVERWRITE

如果有冲突,覆盖已有的变量。

EXTR_SKIP

如果有冲突,不覆盖已有的变量。

EXTR_PREFIX_SAME

如果有冲突,在变量名前加上前缀 prefix

EXTR_PREFIX_ALL

给所有变量名加上前缀 prefix

EXTR_PREFIX_INVALID

仅在非法/数字的变量名前加上前缀 prefix

EXTR_IF_EXISTS

仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。 举个例子,以下情况非常有用:定义一些有效变量,然后从 $_REQUEST 中仅导入这些已定义的变量。

EXTR_PREFIX_IF_EXISTS

仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。

EXTR_REFS

将变量作为引用提取。这有力地表明了导入的变量仍然引用了 array 参数的值。可以单独使用这个标志或者在 flags 中用 OR 与其它任何标志结合使用。

如果没有指定 flags,则被假定为 EXTR_OVERWRITE

prefix

注意 prefix 仅在 flags 的值是 EXTR_PREFIX_SAMEEXTR_PREFIX_ALLEXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。 如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。前缀和数组键名之间会自动加上一个下划线。

首先,用户可控数据未经过滤,直接通过 Controller 类的 assign 方法进行模板变量赋值,并将可控数据存在 think\View 类的 data 属性中。

Lua::assign

Lua::assign — 将一个php变量赋值给Lua

示例

示例  Lua::assign()示例

<?php
$lua = new Lua();
$lua->assign("php_var", array(1=>1, 2, 3)); //lua table index begin with 1
$lua->eval(<<<CODE
print(php_var);
CODE
);
?>

以上示例会输出:

Array([1] => 1[2] => 2[3] => 3) 

array_merge

array_merge — 合并一个或多个数组

说明

array_merge(array ...$arrays): array

将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。

如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。然而,如果数组包含数字键名,后面的值将 不会 覆盖原来的值,而是附加到后面。

如果输入的数组存在以数字作为索引的内容,则这项内容的键名会以连续方式重新索引。

返回值

返回合并后的结果数组。如果参数为空,则返回空 array。

 array_merge() 示例

<?php
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>

以上示例会输出:

Array
([color] => green[0] => 2[1] => 4[2] => a[3] => b[shape] => trapezoid[4] => 4
)

走到这里,GET传入的"cacheFile:open.php"参数给了data,然后data走进fetch方法中 

接着,程序开始调用 fetch 方法加载模板输出。这里如果我们没有指定模板名称,其会使用默认的文件作为模板,模板路径类似 当前模块/默认视图目录/当前控制器(小写)/当前操作(小写).html ,如果默认路径模板不存在,程序就会报错。

fetch:

/tp5010/thinkphp/library/think/view/driver/Php.php

我们可以通过这个路径找到View类所在的源代码文件。在View.php源文件中,有一个View类,其中定义了fetch()方法的代码,如下所示:

/**
* 渲染模板输出
* @access public
* @param string    $templateFile 模板文件名
* @param array     $vars         模板输出变量
* @param array     $config       模板参数
* @return void
* @throws Excepton
*/
public function fetch($templateFile =&#39;&#39;,$vars =[],$config =[])
{//将变量赋值到视图模板中if(!empty($vars)){$this->assign($vars);}//处理模板文件名并判断是否存在$templateFile =$this->parseTemplateFile($templateFile);if(!is_file($templateFile)){throw new Exception(&#39;template file not exists:&#39; . $templateFile);}// 模板输出过滤$this->filter($templateFile);// 解析视图模板中的函数$content =$this->fetchParse($templateFile, $config);// 视图模板编译缓存if ($this->config(&#39;tpl_cache&#39;)&& !empty($TemplateCache)){$TemplateCache->set($cacheFile,$content);}//返回解析后的视图模板内容return $content;
}

在这段代码中,我们可以看到fetch方法的定义和具体实现。

我们跟进到 Template 类的 fetch 方法,可以发现可控变量 $vars 赋值给 $this->data 并最终传入 File 类的 read 方法。而 read 方法中在使用了 extract 函数后,直接包含了 $cacheFile 变量。这里就是漏洞发生的关键原因(可以通过 extract 函数,直接覆盖 $cacheFile 变量,因为 extract 函数中的参数 $vars 可以由用户控制)。

漏洞修复

官方的修复方法是:先将 $cacheFile 变量存储在 $this->cacheFile 中,在使用 extract 函数后,最终 include 的变量是 $this->cacheFile ,这样也就避免了 include 被覆盖后的变量值。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • UE开发中的设计模式(三) —— 对象池模式
  • duilib 之 窗口枚举显示实例 一
  • 高阶数据结构(Java):AVL树插入机制的探索
  • spring boot-18
  • 前端工程化16-什么是节流防抖
  • C#进阶-ASP.NET实现可以缩放和旋转的图片预览页
  • 《Linux运维总结:基于x86_64架构CPU使用docker-compose一键离线部署etcd 3.5.15容器版分布式集群》
  • Python办公自动化:使用openpyxl对工作表进行基本操作
  • 【性能优化】DNS解析优化
  • Python,Spire.Doc模块,处理word、docx文件,极致丝滑
  • 数据结构-排序的概念、应用及其算法实现1(直接插入排序、希尔排序、选择排序、堆排序、冒泡排序)
  • C++第三十六弹---二叉搜索树的性能飞跃:AVL树原理与实现
  • 钢铁百科:A572Gr60和SA572Gr60材质分析、A572Gr60和SA572Gr60简介
  • 【智能启航,速通电工电子!SmartEDA如何成为你的学习加速器】
  • KCP协议(一)
  • [译]如何构建服务器端web组件,为何要构建?
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • HTML5新特性总结
  • Vue2.x学习三:事件处理生命周期钩子
  • vue的全局变量和全局拦截请求器
  • 从tcpdump抓包看TCP/IP协议
  • 从零开始学习部署
  • 动态魔术使用DBMS_SQL
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 前端之React实战:创建跨平台的项目架构
  • 少走弯路,给Java 1~5 年程序员的建议
  • 字符串匹配基础上
  • 国内开源镜像站点
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​用户画像从0到100的构建思路
  • #includecmath
  • #Z2294. 打印树的直径
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (11)MATLAB PCA+SVM 人脸识别
  • (20)docke容器
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (STM32笔记)九、RCC时钟树与时钟 第二部分
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (六)激光线扫描-三维重建
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (一)WLAN定义和基本架构转
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • .net dataexcel winform控件 更新 日志
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET_WebForm_layui控件使用及与webform联合使用
  • .net6+aspose.words导出word并转pdf
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .NET设计模式(11):组合模式(Composite Pattern)
  • /etc/motd and /etc/issue
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @ConfigurationProperties注解对数据的自动封装
  • [ 蓝桥杯Web真题 ]-布局切换