Zentao Privilege Escalation
2024-10-14 08:32:30

漏洞分析

https://github.com/easysoft/zentaopms/commit/695055c6b1d2e6a8c944bdbc38308c06820c40ce?diff=split&w=0
[framework/api/entry.class.php]
Zentao权限绕过 20240428142030068
此文件修改了两处

  1. !isset($this->app->user) -> !isset($this->app->user->account)
  2. return $this->send(403xxx) -> die($this->send(403))
    第二处修改则是权限绕过得一处关键,return虽然会渲染出403页面但不会中断流程,而die则是直接中断不会再向下执行。

[framework/base/router.class.php]
Zentao权限绕过 20240428142943392
修改了条件判断顺序将HTTP_TOKEN分支上移

[module/common/model.php]
Zentao权限绕过 20240428143138194
此处修改较多,移除了checkNewEntry函数,流程不会在checkNewEntryreturn false中断后续的token认证流程。
Zentao权限绕过 20240429105714139
[www/api.php]
Zentao权限绕过 20240428143449576
此处为进入checkEntry做了前提条件

关键条件是$this->app->user从哪里设置
发现在[module/common/model.php#deny] 方法中进行了设置
Zentao权限绕过 20240428150104303

  1. $user->rights
    Zentao权限绕过 20240428150316060
    这里$account是没有内容的所以$user->rights=false
  2. $user->groups
    Zentao权限绕过 20240428150509970
    $account是没有内容的所以$user->groups=[]
  3. $user->admin=false
    1
    $user->admin = strpos($this->app->company->admins, ",{$user->account},") !== false;//$user->account=null
    后面将$user赋值给$this->app->user 虽然user内容为
    1
    2
    3
    4
    5
    { 
    ["rights"]=>bool(false)
    ["groups"]=>array(0) {}
    ["admin"]=>bool(false)
    }
    不过已经可以绕过framework/api/entry.class.php中401

接下来就是怎么进入到deny方法中而且要求调用时参数为两个或者传入的第三个参数为true并且路由在openMethods列表中

Zentao权限绕过 20240428152635273
符合条件的有三个

  1. testcase.getxmindimport
  2. testcase.showxmindimport
  3. testcase.savexmindimport
    在构造方法中还要满足isAjaxRequest条件
    Zentao权限绕过 20240428153202375

Zentao权限绕过 20240428153259777

构造poc

1
/api.php?m=testcase&f=getxmindimport&HTTP_X_REQUESTED_WITH=XMLHttpRequest&productID=1&branch=1

获取到cookie
Zentao权限绕过 20240428153404217
使用cookie请求api接口
Zentao权限绕过 20240428153722283

Zentao权限绕过 20240429105830145

Prev
2024-10-14 08:32:30