复现禅道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
结语
本文只用于参考学习,增强自己的代码审计能力,一切用于违法犯罪的均与作者无关。
网络不是法外之地,请不要轻易挑战法律底线。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)