0x01 ThinkPHP简介
ThinkPHP是一个基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布。从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,注重开发体验和易用性,为web应用开发提供了强有力的支持。
0x02 漏洞简介
(1)漏洞名称
ThinkPHP5远程命令执行
(2)漏洞描述
由于ThinkPHP5框架对控制器名没有进行足够的安全检测,导致在没有开启强制路由的情况下,攻击者构造指定的请求,可以直接getshell。
(3)影响范围
- ThinkPHP 5.0系列 <5.0.23
- ThinkPHP 5.1系列< 5.1.31
- 基于ThinkPHP5二次开发的CMS:如AdminLTE后台管理系统、Thinkcmf、ThinkSNS等。
0x03 测试环境
- centos 7.5
- nginx 1.14.0
- php 7.2.10
- thinkphp5.1beta
0x04 环境部署
查看服务开启状态

将thinkPHP5.1源码K拷贝到nginx目录/usr/local/nginx/html下

赋予权限chmod -R 777 thinkphp5.1/

检测是否部署成功
url:http://192.168.162.128/thinkphp5.1/public/index.php

0x05 漏洞验证
payload:http://192.168.162.128/thinkphp5.1/public/index.php?s=index/\think\Request/input&filter=phpinfo&data=1

0x06 漏洞产生原因
1. 概述
该漏洞出现的原因在于ThinkPHP5框架底层对控制器名过滤不严,从而让攻击者可以通过url调用到ThinkPHP框架内部的敏感函数,进而导致getshell漏洞。
2. 代码审计
由结果推原因
thinkphp5.1\public\index.php,17行,请求start.php

thinkphp5.1\thinkphp\start.php,21行,run()函数

thinkphp5.1\thinkphp\library\think\App.php,280行,run()函数,进行URL路由检测

thinkphp5.1\thinkphp\library\think\App.php,371行,path()函数

thinkphp5.1\thinkphp\library\think\Request.php,
path()函数:获取当前请求URL的pathinfo信息(不含URL后缀)并返回

pathinfo()函数:获取当前请求URL的pathinfo信息(含URL后缀)并返回
从配置文件中获取var_pathinfo的值

配置文件thinkphp5.1\config\app.php中var_pathinfo的值为s;

注意这里的$_GET[$this->config->get('var_pathinfo')],当请求报文包含 $_GET['s'],就取其值作为pathinfo,并返回pathinfo给调用函数,来传递路由信息。而$_GET['s']是用户可控的。

上面将用户可控的pathinfo返回给调用函数path(),再跟进函数path()
将pathinfo传递给$this->path之后返回给调用函数routeCheck()

再跟进routeCheck()函数,得到返回值并赋值给$path,再调用check($path, $depr, $must)函数,

跟进check($path, $depr, $must)函数,$path作为参数之一
thinkphp5.1\thinkphp\library\think\Route.php,744行,
check($path, $depr, $must)函数:检测URL路由,传递进来的参数$url是可控的

跟踪可控变量$url:
首先经过str_replace函数:将url中的/替换为|;
调用check函数,url作为参数之一

又调用check函数,检查路由;
之后创建UrlDispatch实例,$url作为参数之一传递给UrlDispatch的构造函数

跟进UrlDispatch的构造函数,thinkphp5.1\thinkphp\library\think\route\Dispatch.php,29行,将值传递给this->action,之后调用抽象run()函数

\thinkphp5.1beta\thinkphp\library\think\route\dispatch\Module.php,19行,类Module继承了抽象类Dispatch,实现了函数run(),

将$this->action的值传递给$result,
获取控制器名

获取操作名

实例化控制器

跟进实例化函数,thinkphp5.1beta\thinkphp\library\think\App.php,461行,查看实例化过程
可以看到,如果name中包含\,就将name的值赋值给class,之后返回,以此这里控制器的实例化是用户可控的,

之后便是执行实例化后的函数,然后返回给浏览器。

本文深入分析了ThinkPHP5框架中的远程命令执行漏洞,详细介绍了漏洞产生的原因、影响范围及如何利用该漏洞获取服务器权限。通过代码审计,揭示了框架对控制器名过滤不严导致的安全风险。
298

被折叠的 条评论
为什么被折叠?



