在hw期间和客户聊天的时候,听到客户说他们在外网还开了一个禅道项目管理系统,但是在hw的期间关闭了,
hw过了在开启。因为开在外网,而且禅道管理系统以前就爆过一些漏洞,于是询问客户是多少版本的禅道,客户
说:不知道是多少版本的,反正开了几年了。几年······那就能很肯定是老版本了,于是协助客户帮忙测试了一
下。
Url: index.php?Mode=getconfig
源码分析:./index.php
我们成功获取到禅道系统的版本是7.3版,于是百度找一下7.3版本的历史漏洞。
发现该版本存在一个前台sql注入漏洞,为了快速验证漏洞,给客户展示危害,直接利用网上的payload打过去:
Url: /block-main.html?mode=getblockdata&blockid=task¶m=payload2
Payload2的值用如下代码生成:
测试的时候,发现并没有任何反应,页面空白,开启debug模式再尝试:
再一次测试payload,依然是空白页面,第一次测试失败告终。
为了验证漏洞的准确性,我用自己的电脑下载了一个7.3版本的环境,
依然同上步骤进行测试,结果如下:
可以看到,成功进行了报错,证明了这个漏洞还是真实存在的,但是为什么在客户系统上就是空白页面呢?
这里猜想可能是因为打了补丁或者被安全软件拦截了已知exp导致了在客户系统上利用失败。
这里选择先从打补丁方向排除问题,通过搜索发现官方发布了7.3版本的漏洞修复补丁:
修复后的证明就是在根目录下会存在一个ok.txt文件,客户系统上就存在一个ok.txt,证明漏洞已经修复了。
漏洞分析:
在block模块的main方法中进行了动态调用,而且将我们输入的数据赋值给了$this->params属性,
方便在后续的调用中使用,代码如图:
当我们通过url传入参数:?blockid=task的时候,就会去调用printtaskBlock()方法:
可以看到函数将我们输入的数据作为第二个参数传递进了getUserTasks方法中去,查看该方法代码:
看到很直白的就将我们输入的数据作为了字段拼接进了sql语句中去,造成了sql注入漏洞。
补丁分析:
先对比一下补丁,尝试能不能绕过补丁再次进行注入:
修复后的代码中添加了一个__construct方法,并且进行了一个if(!$this->loadModel('sso')->checkKey()) die('');
判断,如果条件满足就会进行退出操作,跟进查看checkkey()方法,看看是怎么判断的:
判断$this->config->sso->turnon是否有值,如果没值就会进行退出,
在这里调试输出看看是否存在值:
调试发现这里默认是不存在值的,这里的功能是为了实现禅道和然之系统的集成,
只有当你在后台集成了然之系统,这里才会有值,默认是不会集成的,所以这里也就是空数据,
这也就导致我们没办法再访问block这个模块了。
因为不能访问block模块了,所以其他版本在该模块里面的注入一概失败。
既然网上爆出来的历史漏洞不能利用,那么尝试一下能不能挖掘到新的漏洞来证明其危害。
因为禅道管理系统对每个用户的权限都进行了划分管理,大部分的功能都需要登录后才能访问,
不需要登陆就可以访问的方法在isOpenMethod方法中定义:
这里定义的方法不需要登录就可以访问,但是block模块进行了再次验证,以往存在高危漏洞的block模块就排除
了,然后查看其他的方法中,发现并没有一个方法可以在不登录时造成高危漏洞,但是我们也不能直接放弃,
给客户说系统绝对安全,没有问题。
退而求其次:
因为没有不需要登录就能造成漏洞的地方,所以再次挖掘登录后能getshell的漏洞,因为这是项目管理系统,
必然会存在很多用户账号,有的用户可能安全意识没有那么强,可能使用弱密码等,只要我们能获取到其中
任意一个账号后能造成getshell漏洞,也能证明其系统存在一定风险性。
所以这里的目标就是挖掘一个任意账户的getshell漏洞。
先看看禅道管理系统用户等级共划分了11个等级:
那么我们挖掘的漏洞就尽量等级越低越好,最好是guest组的用户也可以造成getshell,
这样我们随便获取到一个能登录的账号就可以造成gehshell。
每个组用户对应的访问权限储存在zt_grouppriv数据表中的:
Group=11代表的就是guest组的权限。
对于这种严格划分了权限的系统,我们可以尝试两种方法:
第一种:就是对照着每个组的权限,挨个查看其方法是否能造成漏洞,这种办法有点笨重,
花费时间大,但是比较全面。
第二种:先查找造成漏洞的地方,然后再去查找对应的访问权限,这种办法相对灵活高效。
漏洞挖掘:
我这里就使用的第二种方法,先去查找造成漏洞的地方,再去查找对应的权限。