禅道11.6注入分析
2020-08-03 10:49:08 Author: xz.aliyun.com(查看原文) 阅读量:378 收藏

PAYLAOD:

http://127.0.0.1/zentao116/api-getModel-api-sql-sql=select+account,password+from+zt_user

(需要用户权限)

第一眼看到这种传参方式,我心里是懵逼的,利用到的文件都看不出来,所以先研究一下他的URL是怎么写的。

PS:使用禅道前要将本地的apache服务和mysql服务关闭,否则会发生冲突

PS:由于环境限制,没办法搭建调试环境,所以文章中若是有错误内容还请师傅们务必斧正!!!∑(゚Д゚ノ)ノ

URL地址格式分析

以URL:http://192.168.189.128/zentao/api-getModel-user-getRealNameAndEmails-users=admin为例来说明参数传递过程

不管三七二十一,先上首页:/www/index.php

可以看到这里利用router::createApp创建了一个新的应用,跟进该方法

应用名为:pms,根路径为index.php路径的上级路径,应用类名为router。

这里最后返回了一个实例化的类,将app名字与根路径作为参数传入。由于这里创建了一个新对象,先去router类中看一下是否有__construct()函数,没有找到就去他的父类baseRouter里找,果然在baseRouter中发现了__construct()函数

这里重要的是config文件,在358行调用到setConfigRoot设置了config文件的根目录:xxx/config/

接下来在363行调用到loadMainConfig来调用主配置文件

这里最后将主配置文件即/config/config.php做了include操作,跟进config.php文件

直接来看这一段

这段代码通过注释告诉我们,禅道的请求类型分为了三种:PATH_INFO、PATH_INFO2、GET

接下来回到index.php中,跳过运行app的过程,到达66行:$app->parseRequest();

跟进该函数:framework\base\router.class.php

可以发现,这里将PATH_INFOPATH_INFO2模式归为一类,以-方式传参,由于poc中出现了这种url传递的方式,所以继续跟进parsePathInfo看一下。

parsePathInfo()函数将URL以.为分隔,前面的部分作为URI,.后面的部分作为viewType。

回到parseRequets()函数中,继续跟进setRouteByPathInfo()函数

这里首先利用了$this->config->requestFix分隔URI并整理为一个数组$item,这里的$this->config->requestFix-,接下来将数组中各个元素进行分配,$items[0]为模块名,$item[1]为方法名,在函数末尾设置控制器文件,函数结束。

接下来回到index.php中,流程到$common->checkPriv();,检测用户是否有权限访问应用。

再到$app->loadModule();,加载模块,重要部分截图

这里会根据请求方式设置参数,由于是PATH_INFO方法,继续跟进函数看看

这里用到该函数来取删掉前两个后的剩下的参数,赋值给params数组中。

再调用mergeParams函数将参数取出来合并并做调用

最后返回了$defaultParams数组。

回到loadModule()函数中,可以看到,函数的结尾调用了call_user_func_array()函数,而且这里的函数也是我没见过的写法

/* 调用该方法   Call the method. */
call_user_func_array(array($module, $methodName), $this->params);
return $module;

搜索了一下这种写法,发现然之协同oa也有相同的代码,这种写法相当于$module::$methodName($this->params)$methodName必须是public类型才可以。

其实这里就是调用到了user模块的getRealNameAndEmails方法,传递的参数$paramsusers=admin

跟进发现该方法就是查询用户账户的信息并返回,这样就差不多就搞明白禅道的传参方式了。

漏洞分析

POC

http://127.0.0.1/zentao116/api-getModel-api-sql-sql=select+account,password+from+zt_user

根据前面的分析,先访问api模块的getModel方法

在函数50行的位置:

$result = call_user_func_array(array(&$module, $methodName), $params);

这样接下来就调用到api模块中的sql方法,跳转到该方法看一下

终于找到了执行SQL语句的位置,函数首先用trim去除首位的空白字符,在99行处先将SQL语句显示在页面上,然后若是未查找到'select '这样的字符串就直接查询SQL语句,看到这种代码,我瞬间感觉很是凌乱。

小结

从这里可以得出一个教训,任何有关数据库的操作都必须经过很好的过滤,不能抱有任何侥幸心理,问题代码藏得再深都会被发现。

参考

[渗透笔记]禅道(payload)

禅道11.6后台SQL注入漏洞复现分析(URL格式分析)


文章来源: http://xz.aliyun.com/t/8066
如有侵权请联系:admin#unsafe.sh