Skip to content

JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/list Department ID Parameter Bypasses Tenant Validation #32

@Hwwg

Description

@Hwwg

JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/list Department ID Parameter Bypasses Tenant Validation

Contributors: huangweigang

1. Impact Scope

2. Vulnerable Endpoint

  • GET /sys/sysDepartRole/list?deptId=... (Department Role Paginated List Query API)

3. Code Analysis

  • Controller: jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysDepartRoleController.java
    • Route & method:
      • @GetMapping(value = "/list")
      • public Result<?> queryPageList(SysDepartRole sysDepartRole, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, @RequestParam(name="deptId",required=false) String deptId, HttpServletRequest req)
    • Key code (lines 73–104):
      • QueryWrapper<SysDepartRole> queryWrapper = QueryGenerator.initQueryWrapper(sysDepartRole, req.getParameterMap());
      • if(oConvertUtils.isNotEmpty(deptId)){
      • queryWrapper.eq("depart_id",deptId);
      • IPage<SysDepartRole> pageList = sysDepartRoleService.page(page, queryWrapper);
      • return Result.ok(pageList);
      • }
  • Problem points:
    • The endpoint directly uses the user-provided deptId parameter to query department roles without verifying whether the department belongs to the current tenant
    • The original tenant validation logic has been commented out (lines 81-92), leaving no tenant isolation checks in the current implementation
    • Attackers can enumerate or guess department IDs of other tenants to obtain their department role configuration information
    • Missing validation of the ownership relationship between tenant ID and department ID

4. Reproduction

-- Prerequisites

  • Attacker has a valid login session (authenticated user)
  • Attacker knows or can enumerate the target tenant's department ID (departId)
  • System has multi-tenancy mode enabled

-- Steps (Cross-tenant Information Disclosure)

  • Log in to the system using attacker account (Tenant A)
    • curl -X GET -H "Authorization: Bearer <attacker_token>" "http://<host>/jeecgboot/sys/sysDepartRole/list?deptId=<victim_dept_id>&pageNo=1&pageSize=10"
  • Observation: API returns 200 OK, response data contains the department role list information of target Tenant B
  • Verification:
    • Switch to Tenant B's account and call the same endpoint to confirm data consistency
    • Or query the database to verify that the returned department roles actually belong to another tenant

5. Impact

  • Cross-tenant information disclosure
    • Attackers can obtain other tenants' department role configuration information, including role codes, role names, permission scopes and other sensitive organizational structure data
  • Business isolation failure
    • Violates the data isolation principle of multi-tenant systems, where data from different tenants should be completely isolated
  • Organizational structure information disclosure
    • Exposes other tenants' organizational structures and permission system designs, which may be used for further attacks
  • Compliance risks
    • Multi-tenant data leakage may violate data protection regulations (such as GDPR, compliance requirements)

6. Remediation

  • Server-side tenant ownership validation
    • In the queryPageList method, query department information based on deptId and verify whether the department's tenantId matches the current logged-in user's tenant ID:
      • SysDepart depart = sysDepartService.getById(deptId);
      • if(depart == null || !depart.getTenantId().equals(currentUser.getTenantId())) {
      • return Result.error("Unauthorized to access this department data");
      • }
  • Enable tenant filter
    • Force add current tenant ID filter in query conditions:
      • queryWrapper.eq("tenant_id", TenantContext.getTenant());
  • Database-level isolation
    • Use MyBatis-Plus multi-tenancy plugin to automatically add tenant filtering conditions at the SQL level
  • Audit logging
    • Record cross-tenant access attempts for security auditing and anomaly detection

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions