复现禅道V17.4的sql注入漏洞

漏洞详情

  简述:禅道是第一款国产的开源项目管理软件,它的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序地跟踪管理起来,完整地覆盖了项目管理的核心流程。

漏洞危害

  该漏洞是由于禅道项目管理系统权限认证存在缺陷导致,攻击者可利用该漏洞在未授权的情况下,通过权限绕过在服务器执行sql进而可以写入webshell。

影响范围

  • V17.4<= 禅道 <= V18.0.beta1(开源版)
  • V3.4<= 禅道 <= V4.0.beta1(旗舰版)
  • V7.4<= 禅道 <= V8.0.beta1(企业版)

复现过程

我下载了开源版V17.4的程序来进行代码审计

其中关键部分在于权限绕过,

代码文件:framework\base\control.class.php

复制代码
 1 if($this->config->installed && !in_array($this->moduleName, $this->config->openModules) && empty($this->app->user) && !$this->loadModel('common')->isOpenMethod($this->moduleName, $this->methodName))
 2 {
 3     $uri = $this->app->getURI(true);
 4     if($this->moduleName == 'message' and $this->methodName == 'ajaxgetmessage')
 5     {
 6         $uri = helper::createLink('my');
 7     }
 8     elseif(helper::isAjaxRequest())
 9     {
10         die(json_encode(array('result' => false, 'message' => $this->lang->error->loginTimeout)));
11     }
12  
13     $referer = helper::safe64Encode($uri);
14     die(js::locate(helper::createLink('user', 'login', "referer=$referer")));
15 }
复制代码

empty($this->app->user) 处进行了权限判断,但只判断了user不为空的情况,而user的信息主要存在session中,所以只要能构造一个user的键即可。

对允许访问的模块和方法进行审计发现了在misc模块的captcha方法中可以伪造session,且只能控制键不能控制值,正好可以用来绕过权限认证:

代码文件:module\misc\control.php

复制代码
 1 public function captcha($sessionVar = 'captcha', $uuid = '')
 2 {
 3     $obLevel = ob_get_level();
 4     for($i = 0; $i < $obLevel; $i++) ob_end_clean();
 5  
 6     header('Content-Type: image/jpeg');
 7     $captcha = $this->app->loadClass('captcha');
 8     $this->session->set($sessionVar, $captcha->getPhrase());
 9     $captcha->build()->output();
10 }
复制代码

权限认证绕过之后,发现可以访问一部分代码,在对后台的功能审计时候发现,在导入数据时候的数据库判断存在sql注入

代码文件:module\convert\model.php

1 public function dbExists($dbName = '')
2 {
3     $sql = "SHOW DATABASES like '{$dbName}'";
4     return $this->dbh->query($sql)->fetch();
5 }

审查该段代码可以发现,存在sql注入

同文件下的该段代码一样存在sql注入,且为堆叠注入

复制代码
 1 public function connectDB($dbName = '')
 2 {
 3     $dsn = "mysql:host={$this->config->db->host}; port={$this->config->db->port};dbname={$dbName}";
 4     try
 5     {
 6         $dbh = new PDO($dsn, $this->config->db->user, $this->config->db->password);
 7         $dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
 8         $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
 9         $dbh->exec("SET NAMES {$this->config->db->encoding}");
10         $this->sourceDBH = $dbh;
11         return $dbh;
12     }
13     catch (PDOException $exception)
14     {
15         return $exception->getMessage();
16     }
17 }
复制代码

至此已复现完毕!

回顾权限验证函数

1 catch(EndResponseException $endResponseException)
2 {
3     echo $endResponseException->getContent();
4 }

其中这个就是权限不满足时候执行的,原本这时候应该就要结束了,但是这里采用的是echo 所以导致了可以继续执行代码,所以只要上面的验证绕过,这里就可以继续执行。

在官方发布的新版中这里修改为了die,如下:

die($endResponseException->getContent());

代码不能继续执行了。

禅道的rce poc已经在github上发布了,作者在这就不做过多赘述,sql注入的poc已放上github:https://github.com/spmonkey/zentao_sql_poc

 

结语

本文只用于参考学习,增强自己的代码审计能力,一切用于违法犯罪的均与作者无关。

网络不是法外之地,请不要轻易挑战法律底线。

posted @   spmonkey  阅读(1450)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示