禅道项目管理系统

您所在的位置:网站首页 禅道开源版 禅道项目管理系统

禅道项目管理系统

2023-04-24 20:13| 来源: 网络整理| 查看: 265

大家好,我是观宇战队Di@m1racl3,本篇文章主要分享前不久在互联网披露的禅道系统命令执行漏洞分析案例。

1. 简介

禅道研发项目管理软件是国产的开源项目管理软件,专注研发项目管理,内置需求管理、任务管理、bug管理、缺陷管理、用例管理、计划发布等功能,实现了软件的完整生命周期管理。该系统用户量巨大,已为1000000+项目提供服务。

2023年1月6日,互联网披露其旧版本中存在权限绕过与命令执行漏洞,攻击者可在无需登录的情况下构造恶意请求执行任意命令,控制服务器。

2. 漏洞影响版本

17.4 ≤ Zentao(禅道)开源版≤ 18.0.beta1

3.4 ≤ Zentao(禅道)旗舰版≤ 4.0.beta1

7.4≤ Zentao(禅道)企业版≤ 8.0.beta1

3. 漏洞源码分析3.1 权限绕过漏洞分析

根据受影响版本,使用diff软件进行对比分析,发现在checkPriv函数处将echo函数修改为了die函数,如下图所示。查找checkPriv函数的调用关系,并结合漏洞类型,最终定位到该函数在index.php里被调用,于是开始源代码审计分析。

查阅资料可知,该系统的所有HTTP请求均在index.php中进行解析并调用,主要函数如下图所示。parseRequest函数负责解析本次请求的入口方法,根据请求的类型(PATH_INFO、GET),获取需要调用的方法;setParams函数负责设置被调用方法的参数;checkPriv函数负责检查用户是否有权限调用该方法,如果没有则跳转到登录界面;loadModule函数负责加载相应模块并调用相应方法。

通过分析,权限绕过则只可能发生在checkPriv函数中,查看该函数源代码发现,首先会检查是否为重置密码请求,如果不是则检查是否已经登录了,如果已经登录,则进一步检查该用户是否有权限调用目标方法。这里的权限检查函数为hasPriv函数,如果发现没有权限调用目标方法,则会调用deny函数。

进一步跟踪deny函数,发现最终会调用helper::end函数,从而抛出一个异常。然后回到checkPriv函数中,被try catch逻辑捕捉到。

但是在try catch中并没有终止程序,程序依然会向下执行。因此这里就可以通过构造一个session,即写一个session['user']就能进行绕过。至此,权限绕过漏洞分析结束。

3.2 命令执行漏洞分析

同样使用diff软件分析,没有发现命令执行修复代码,最后发现有研究员对该漏洞进行了分析,于是这里借鉴一下该研究员的分析思路。漏洞代码出现在module/repo/model.php文件中,model.php文件中有一个checkConnection函数,该函数在判断SCM的值是否等于Subversion后则会调用exec函数执行命令。POST请求中的client参数未经任何校验,直接拼接到命令中执行,最终导致了命令注入,源代码如下图所示。

4. 漏洞复现详情4.1 权限绕过漏洞复现

分析可知,在在进入权限检查的流程时需要满足$this->app->user不为空,然后将$this->session->user赋值给$this->app->user,最后才做权限检查。因此只需要构造一个$this->session->user,即可绕过登录验证过程。同时又因为权限校验过程中,在检测到没有权限的情况下不会终止程序,而是继续向下执行,这样权限检查就形同虚设了。

经过代码审计发现captcha函数中可以实现写入一个自定义的session,此段代码本意是设置生成一个自定义session的验证码,正好可以利用该函数生成一个自定义的session。这样在进行权限检查的时候,$this->app->user就不为空了,从而顺利进入权限检查流程,抛出异常继续向下执行。captcha代码如下所示。

如果在不调用captcha函数生成session的情况下,直接调用repo模块的edit函数,则会出现$this->session->user为空,不能进行权限校验而直接返回,因此也不会调用到该函数,如下图所示。

同时在对被调用函数设置参数的函数setParams函数中,创建该模块的控制类时,会调用到控制类的构造方法,在构造方法中也进行了$this->app->user是否为空的校验。因此都需要伪造一个session才能进行绕过。

4.2命令执行漏洞复现

得到权限绕过漏洞之后,接下来开始复现命令执行漏洞,这里有两个地方存在命令执行的可能,一个是repo模块的create函数,在该函数中的checkConnection函数处存在代码执行的代码快。

跟进checkConnection函数,在使用versionCommand时没有对其进行任何过滤,只要scm的值为“Subversion”即可。

但是在调用checkConnection函数之前,checkClient函数会进行一些列校验,要想在create函数处实现命令执行变得不可行,代码如下。第一处检查scm的值是否等于“Gitlab”,如果不等于则检查checkClient是否为false,即判断是否已经校验过了,如果第一、二处检查都不通过,则进行第三步检查,是否有clientVersionFile文件,如果三个条件均不满足,返回false,校验不通过,无法进行命令执行操作。

如果想要在此处进行命令执行,则需要满足clientVersionFile文件存在才行,跟了一遍代码,没发现该文件创建的地方,因此create函数无法进行命令执行。

另一个是repo模块的edit函数,该函数中的commonAction函数有一个检验点,即检查系统仓库是否为空,如果为空则不能通过校验,则需要先创建一个仓库才行,如果该系统已经创建了仓库,则可以直接调用edit函数进行命令执行,如下图所示。

在edit函数中会调用update函数。

跟进update函数,最终调用到checkConnection达到任意命令执行。

4.3权限绕过+命令执行漏洞复现

最后将两个复现结合起来,首先访问misc模块的captcha函数,参数任意即可,这里使用user。需要注意的是,如果是使用一键安装包搭建,则访问URL为“/misc-captcha-user.html”,如果是使用源码搭建的,则使用“/index.php?m=misc&f=captcha&sessionVar=user”,访问之后我们就得到了一个session,session不为空则可以实现权限绕过。接着调用repo模块的edit函数执行命令,这里如果仓库不存在,则需要先调用repo模块的create函数创建一个仓库。

这里需要注意的是,Windows和Linux下,命令执行的方式不一样,Linux下使用“`”符号即可实现命令执行,但是Windows下使用该符号是不可行的,需要使用“%26”即字符“&”的URL编码,也是实现命令执行的技巧,验证方式使用dnslog或者Ceye均可,这里使用dnslog来验证。

在调试器下可以看到执行的命令和执行结果。

最后在dnslog也可以看到结果,如下图所示。在Widows平台下,想要回显会比较麻烦,有输出格式的限制,这里推荐直接使用dnslog或者Ceye来进行验证。

5. 漏洞修复方法

官方已于2023年1月12日发布了漏洞修复补丁,目前该系统已在最新版本中修复了此漏洞,建议升级到最新版本。

参考文献:

https://mp.weixin.qq.com/s/ZHsYaU31WkzAJijy1V0U1w



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3