长亭百川云 - 文章详情

Thinkphp5 RCE 代码审计

InBug实验室

61

2024-07-13

             

前言

本着知其然,知其所以然的精神,对thinkphp5 控制器过滤不严导致的RCE漏洞进行了一次审计

POC:

影响版本:thinkphp 5.0.23及以下

环境:phpstorm+xdebug

POC效果:

开始审计

前置知识:

入口文件:Thinkphp5的入口文件位于public目录下的index文件

跟进入口文件,先进行了一些配置加载、设置路由规则的工作

加载完之后进入start.php开始执行

Run方法:

public static function run(Request $request = null)

跟进run方法,首先是自动加载机制autoload加载think\app类

初始化、语言包加载、模块绑定等工作完成后开始获取调度信息dispatch,未设置调度信息则进入routecheck()方法进行url检测

Routecheck方法:

public static function routeCheck($request, array $config)

跟进routecheck()方法,routecheck方法对pathinfo进行分析(tips:thinkphp的pathinfo格式为模块/控制器/操作/[参数名/参数值])

调用path()方法获取到url的pathinfo信息,返回path=” index/think\app/invokefunction” 

格式为模块名:index  

控制器名:think\app

操作名:invokefuncton

Routecheck()方法载入路由,对比pathinfo以生成调度信息

随后进入路由检测,读取路由缓存内容、导入路由配置,随后进入check()方法根据解析的pathinfo信息与路由进行对比,因路由规则中不存在对应的路由信息,返回$result=fasle,代表路由无效,无调度信息

因为根据路由缓存检测出调度信息无效,所以进入parseURL进行URL的解析进行url的解析以再次获取调度信息

跟进parseURL,parseURL中调用了parseUrlPath来解析url,此时url= “index|think\app|invokefunction”。 parseurlPath将url解析为数组形式,$path:{“index”,”think\app”,”invokefunction”},分别为模块、控制器、操作

ParseURL对parseURLpath返回的数组$path进行模块、控制器、操作的解析,得到结果:模块$module = “index”  控制器$controller=”think\app”  操作 $action = “invokefunction”

随后对获取的信息进行路由封装,得到$route = {“index“,”think\app”,”invokefunction”}

继续跟进,对路由进行记录、检测缓存信息,完成后进入exec()方法

Exec方法:

protected static function exec($dispatch, $config)

跟进exec()方法,exec根据dispatch数组中type字段的值进入module分支,并调用module方法

跟进module方法,module方法首先对模块进行部署、初始化、缓存检查

随后module方法获取模块名index、控制器名think\app、操作名invokefunction

随后分别进入controller()方法、parseName()方法、action()方法设置控制器、操作并载入

设置并加载控制器、操作后通过is_callable()查看invokefunction是否能被调用,若不可调用则抛出404不存在

随后进入invokemethod方法

跟进invokemethod,invokemethod通过反射机制ReflectionMethod调用操作invokefunction,bindParams用于获取绑定参数 args = {“call_user_func_array”,”{system”, {“whoami”}}”}

此时通过反射机制将调用操作指定为invokefunction ,将参数绑定为args = {“call_user_func_array”,”{system”, {“whoami”}}”}

随后进入invokeargs方法,invokeargs通过反射进入invokefunction方法,在此设置反射为call_user_func_array(),绑定参数为system和whoami

再次调用invokeargs()方法,成功调用call_user_func(system(“whoami”))达到远程代码执行的目的 

退出module达到命令执行目的

总结

结合此次RCE审计流程来看,漏洞点主要是解析pathinfo的时候并没有对控制器操作进行过滤,导致恶意用户将控制器操作指向invokefunction,再结合call_user_fun_array达到了远程代码任意执行的攻击效果,通过对比thinkphp发布的补丁可以看出,thinkphp通过增加对控制器名的过滤达到修复。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2