Skip to content

JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/getDeptRoleByUserId User Department Role Query Without Tenant Validation #34

@Hwwg

Description

@Hwwg

JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/getDeptRoleByUserId User Department Role Query Without Tenant Validation

Contributors: huangweigang

1. Impact Scope

2. Vulnerable Endpoint

  • GET /sys/sysDepartRole/getDeptRoleByUserId?userId=...&departId=... (Get User's Assigned Department Roles 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:
      • @RequestMapping(value = "/getDeptRoleByUserId", method = RequestMethod.GET)
      • public Result<List<SysDepartRoleUser>> getDeptRoleByUserId(@RequestParam(value = "userId") String userId,@RequestParam(value = "departId") String departId)
    • Key code (lines 217–231):
      • Result<List<SysDepartRoleUser>> result = new Result<>();
      • //Query department roles
      • List<SysDepartRole> roleList = sysDepartRoleService.list(new QueryWrapper<SysDepartRole>().eq("depart_id",departId));
      • List<String> roleIds = roleList.stream().map(SysDepartRole::getId).collect(Collectors.toList());
      • //Query authorized roles based on role id and user id
      • List<SysDepartRoleUser> roleUserList = null;
      • if(roleIds!=null && roleIds.size()>0){
      • roleUserList = departRoleUserService.list(new QueryWrapper<SysDepartRoleUser>().eq("user_id",userId).in("drole_id",roleIds));
      • }
      • result.setSuccess(true);
      • result.setResult(roleUserList);
      • return result;
  • Problem points:
    • The endpoint directly uses departId to query department roles without verifying the department's tenant ownership
    • Directly uses userId to query user role authorizations without verifying whether the user belongs to the current tenant
    • Attackers can query the user department role authorization status of any tenant
    • May leak cross-tenant user permission configuration information

4. Reproduction

-- Prerequisites

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

-- Steps (Cross-tenant User Permission Information Disclosure)

  • Using attacker account (Tenant A):
    • curl -X GET -H "Authorization: Bearer <attacker_token>" "http://<host>/jeecgboot/sys/sysDepartRole/getDeptRoleByUserId?userId=<victim_user_id>&departId=<victim_dept_id>"
  • Observation: API returns 200 OK, returns the target user's role authorization list in the specified department
  • Verification:
    • Use Tenant B's administrator account to query the same user's roles and confirm data consistency
    • Database query sys_depart_role_user table to confirm the returned authorization relationship belongs to another tenant

5. Impact

  • Cross-tenant user permission information disclosure
    • Attackers can obtain other tenant users' department role authorization information
    • Understand the target user's permission level and functional scope within the organization
  • Permission system analysis
    • By querying different users' role authorizations in bulk, complete organizational permission architecture diagrams can be drawn
  • Personnel information disclosure
    • Confirm specific users' department affiliations and role responsibilities within the organization
  • Provides intelligence for privilege escalation attacks
    • Identify high-privilege users, providing targets for subsequent targeted attacks

6. Remediation

  • Department tenant ownership validation
    • Verify whether the department corresponding to departId belongs to the current tenant:
      • SysDepart depart = sysDepartService.getById(departId);
      • LoginUser currentUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
      • if(depart == null || !depart.getTenantId().equals(currentUser.getTenantId())) {
      • return Result.error("Unauthorized to access this department data");
      • }
  • User tenant ownership validation
    • Verify whether the user corresponding to userId belongs to the current tenant:
      • SysUser user = sysUserService.getById(userId);
      • if(user == null || !sysUserTenantService.userBelongsToTenant(userId, currentUser.getTenantId())) {
      • return Result.error("Unauthorized to query this user information");
      • }
  • Force tenant filtering
    • Add tenant ID filtering conditions in all database queries
  • Least privilege principle
    • Restrict ordinary users to only query their own role authorizations, only administrators can query other users
  • Audit logging
    • Record all user role query operations, especially cross-tenant access attempts

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