DolphinPHP 全版本后台代码执行漏洞
DophinPHP(海豚PHP)是一个基于ThinkPHP5.1.39LTS开发的一套开源PHP快速开发框架,为开发集成了基于数据-角色的权限管理机制,集成多种灵活快速构建工具,可方便快速扩展的模块、插件、钩子、数据包,他没有前台的代码,所以的操作都在后台,所以,对这类cms的审计基本都只看后台的文件
分析
代码执行漏洞点
定位到漏洞文件 application/common.php
1 | function action_log($action = null, $model = null, $record_id = '', $user_id = null, $details = '') |
简单分析下这段代码,从数据库中读取数据赋值给$action_info,之后,从$action_info数组中取log下标的值,并通过正则赋值给了$match,之后,遍历$match的值,使用”|”分割并生成$param数组,将$param[1]和$log[$param[0]]带入了call_user_func函数。
$param的值是从数据库中传入的,如果能控制数据库,我们就能控制这个值,$log是一个数组,其中大多数参数都是外部传入,有可能可控,现在捋一捋思路,1、先控制数据库->将payload更新进对应的字段中->找调用action_log的控制器文件->传进action_log的参数可控->触发漏洞
先看看是否能把payload更新进数据库,这里跟进查询语句中的admin/action
model(‘admin/action’)调用的admin模块里的action模型,这里跟进这个模型
thinkphp5的写法,一般在controller目录下调用这个模型进行增删改查的文件,名字都相同,这里跟进controller目录下的Action.php
但是这个类中没有编辑函数,打开浏览器查看下
在页面上有编辑功能,这里回到源码中,跟进他的父类
在Admin这个类,存在edit函数,跟进他的逻辑看下是怎么更新的,重点是验证函数有无过滤
1 | public function edit($id = '') |
根据不同的表单项从cache中获取不同的配置,这里偷懒,直接打印配置就好,一般来讲,validate类和model类,名字也是一样的,这里跟进validate目录下的action.php查看验证规则
回到common.php查看带入参数有无在验证规则内
我们需要的是log字段,这个字段没做过滤,那将我们的payload带入数据库从这里看已经没问题了,接着往下看,payload要如何构造
首先,先构造最简单的call_user_func(‘phpinfo’,’1’),从这个逆推回$action_info[‘log’],可以得到$action_info[‘log’]=[$log的下标|phpinfo],$log这个变量中,从外界传入的就4个,能用的只有最后一个,所以,这里构造的payload应该是$action_info[‘log’]=[details|phpinfo]
将payload更新进数据库中,没有过滤
之后就要找触发这个漏洞的文件,在attachment.php的disable函数中,刚好满足我们的要求,传进action_log中的$details是由我们输入的ids,这里需要跟进下父类的parent::setStatus函数
1 | public function setStatus($type = '', $record = []) |
输入的值都没过滤,直接进入action_log函数
进入后台进行验证下
先上传一张图片
进入行为管理,编辑启动附件项
所属模块改成系统
日志规则改成[details|phpinfo]
在附件管理中启动附件,触发phpinfo
这几段代码在DophinPHP最初的版本就存在,所以应该是全版本都通用的