| Title | JeecgBoot 3.9.0 Improper Control of Resource Identifiers |
|---|
| Description | # JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/getDeptRoleByUserId User Department Role Query Without Tenant Validation
## Contributors: huangweigang
### 1. Impact Scope
- JeecgBoot (latest)
- https://github.com/jeecgboot/jeecg-boot
### 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
|
|---|
| Source | ⚠️ https://github.com/Hwwg/cve/issues/34 |
|---|
| User | huangweigang (UID 88993) |
|---|
| Submission | 12/10/2025 13:04 (4 months ago) |
|---|
| Moderation | 12/27/2025 10:01 (17 days later) |
|---|
| Status | Accepted |
|---|
| VulDB entry | 338499 [JeecgBoot up to 3.9.0 getDeptRoleByUserId departId information disclosure] |
|---|
| Points | 20 |
|---|