IIBOS 是一个基于PHP开发、Yii框架、免费开源的,快速、高效的协同办公管理系统 ,从2012年研发以来,是为了简化企业协同应用开发而诞生的。IBOS从诞生以来一直秉承简洁实用的设计原则,在保持出色的功能和的优秀的用户体验同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内用户体验最好和最具影响力的协同办公管理系统,众多的典型案例确保可以稳定用于商业以及门户级的开发。
通过前面的介绍以及阅读官网帮助文档,我们初步发现该系统后端使用了YII框架。我们可以简单的了解
一下他这里用到的框架,这有利于我们后续的代码审计,我们在代码中插入 yii::getVersion() 查看
当前使用的YII版本,Yii目前有两个主要的版本: 2.0 和 1.1。Yii 最先发布稳定版本为:1.1.14 (2013年8月 11日发布),Yii 最新发布稳定版本为:2.0.0 (发布于 2014年10月12日发布)。
通过前面的介绍以及阅读官网帮助文档,我们初步发现该系统后端使用了YII框架。我们可以简单的了解
一下他这里用到的框架,这有利于我们后续的代码审计,我们在代码中插入 yii::getVersion() 查看
当前使用的YII版本,Yii目前有两个主要的版本: 2.0 和 1.1。Yii 最先发布稳定
例如1.X中存在一些SQL注入,XSS漏洞。
且该框架完全面向对象(OOP),坚持严格的面向对象编程范式。它没有定义任何全局函数或变量。而
且,它定义的类层次结构允许最大的可重用性和定制。
YII框架实现了MVC设计模式,models 目录包含了所有模型类,views 目录包含了所有视图脚本,
controllers 目录包含了所有控制器类,这一点在后续的目录结构会有所体现。
在进行功能点测试的时候发现该系统管理后台存在一个数据库备份的功能点,然后进入更多选项功能处。
发现只有最后备份文件名处内容可能可控,我们根据路径去定位源代码。
该处调用了 actionBackup() 方法,然后进行判断。在33行代码处调用了database类下的 databaseBackup() 方法,从这个方法名来看该方法可能是用来进行数据库备份的,跟进该方法。通过 Env::getRequest 方法,filename参数来传入我们上传的文件名,也就是我们上面所提到的可以控制的部分,然后对文件名进行过滤,这里对一些后缀进行了过滤。getRequest()方法则是获取我们不同类型的请求参数,getQuery、getPost、getParam这些方法是YII框架下封装好的一些获取请求参数的方法这些方法可直接调用。首先在 $method == 'multivol' 这个if分支中将 $backupFileName 参数进行拼接并赋值给$dumpfile ,经过分析发现在该if分支中 $dumpfile 在传递的过程中并未有危险操作。而在else分支中 $backupFileName 经过拼接传递到了 $dumpFile 参数中.
而在else分支中 $backupFileName 经过拼接传递到了 $dumpFile 参数中。
我们继续向下分析。
上述的 $dumpFile 参数最终被拼接到了453行的代码中,在PHP中反引号中的字符串可以被当做命令来执行,且这里的$dumpFile参数是可控的。
成功rce。
在常规黑盒测试的时候发现该处功能点在添加特殊字符时存在报错
功能点通过Api控制器调用了module层的 GetList 类,我们跟进该类进行查看
结合数据包以及代码进行分析,我们可以发现存在报错的数组下的 keyword 下的 subject 参数,在代码30行判断keyword参数是否为空,在32行将参数值带到 getListCondition() 方法中,这个方法是用来进行SQL语句拼接的,最后带到代码33行处的 getReportByCondition() 方法进行一些列的SQL语句执行的操作。
在 getListCondition() 方法中最后返回分支选择后的部分SQL语句。
在 getReportByCondition() 方法中,经过一系列的跟踪调试,得到了完整的SQL语句,在参数传递的过程中代码层没有对特殊字符进行过滤导致SQL注入的产生。
由于YII框架的DB类库中没有对SQL进行良好的化处理且开发人员在后期二次开发的过程中对报错没有进
行及时的异常捕获处理导致报错注入的产生。
在功能点文件柜处存在一处下载功能点,该功能点通过参数值来下载文件.
输入单引号,发现报错。经过测试之后,发现此处也存在注入。
通过路由发现该处调用了 actionAjaxEnt() 方法并接收一个op参数进行功能的选择。
通过路由发现该处调用了 actionAjaxEnt() 方法并接收一个op参数进行功能的选择,在代码中调用了 BaseController 类下的 download() 方法。通过框架的db类库下的 buildQuery() 方法跟踪得到完整的SQL语句
在fied参数后面,输入sql注入的payload,成功注入出数据库名。
在测试过程中发现一处上传点,然后我们接着将构造好的.php文件进行上传。发现定义.php后不还是不能成功上传通过该处功能点找到相应代码进行分析
发现这里调用了 actionadd() 这个方法,其实该方法通过op参数帮助我们进行功能定位,但在执行该方法前会先执行该类下的 actionIndex() 方法获取后台的配置参数。在 actionIndex() 方法中调用了getUploadConfig()获取上传配置参数在 actionIndex() 方法中调用了getUploadConfig()获取上传配置参数
在self::$dangerTags 变量中则unset掉。
在后台设置中设置了php后缀,在这里也不会生效,.php后缀也不自然不会上传成功
接着来看upload()方法,在该方法中调用了CommonAttach() 类下的方法,该类下封装了所有用于上传的方法。
在通过上传方法中28行的 chechExt() 方法就是另一处过滤的地方。
在system目录中搜索unlink函数,在 DatabaseController.php 中发现一处很明显的参数可控造成的任
意文件删除。这里通过post方式接收参数key,在代码72行进行简单判断是否是文件就进行了删除。
在代码中可以清除的看到我们传入的路径被带到unlink()函数中
在/system/modules/dashboard/controllers/CronController.php
有问题的函数在actionIndex()第 16 行。
看第40行getRealCronFile()函数会形成一个完整的文件路径,第41行到第47行,这是用来过滤修改计划任务的文件名的字符串。
getRealCronFile()功能代码。
通过漏洞点,去定位源码。
接着发现使用creaturl这个方法。
跟进这个方法。
在代码中发现,没有对用户的输入内容进行过滤。导致可以在发送邮件的过程中产生xss漏洞。
https://www.skrskr.me/index.php/posts/open-source-version-of-IBOS-oa-system-getshell.html
https://gitee.com/ibos/IBOS/issues/I189ZF
https://gitee.com/ibos/IBOS/issues/I18JRG
公众号长期更新安全类文章,关注公众号,以便下次轻松查阅
觉得文章对你有帮助 请转发 点赞 收藏