Submit #711774: JeecgBoot 3.9.0 Improper Control of Resource Identifiersinfo

TitleJeecgBoot 3.9.0 Improper Control of Resource Identifiers
Description# JeecgBoot Tenant Privilege Escalation: GET /sys/sysDepartRole/datarule/{permissionId}/{departId}/{roleId} Data Rule Query Without Tenant Validation ## Contributors: huangweigang ### 1. Impact Scope - JeecgBoot (latest) - https://github.com/jeecgboot/jeecg-boot ### 2. Vulnerable Endpoint - GET `/sys/sysDepartRole/datarule/{permissionId}/{departId}/{roleId}` (Query Data Rule Information 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 = "/datarule/{permissionId}/{departId}/{roleId}")` - `public Result<?> loadDatarule(@PathVariable("permissionId") String permissionId,@PathVariable("departId") String departId,@PathVariable("roleId") String roleId)` - Key code (lines 236–260): - `//Query authorized department rules` - `List<SysPermissionDataRule> list = sysDepartPermissionService.getPermRuleListByDeptIdAndPermId(departId,permissionId);` - `if(list==null || list.size()==0) {` - ` return Result.error("Permission configuration information not found");` - `}else {` - ` Map<String,Object> map = new HashMap(5);` - ` map.put("datarule", list);` - ` LambdaQueryWrapper<SysDepartRolePermission> query = new LambdaQueryWrapper<SysDepartRolePermission>()` - ` .eq(SysDepartRolePermission::getPermissionId, permissionId)` - ` .eq(SysDepartRolePermission::getRoleId,roleId);` - ` SysDepartRolePermission sysRolePermission = sysDepartRolePermissionService.getOne(query);` - ` if(sysRolePermission==null) { ... }` - ` else {` - ` String drChecked = sysRolePermission.getDataRuleIds();` - ` if(oConvertUtils.isNotEmpty(drChecked)) {` - ` map.put("drChecked", drChecked.endsWith(",")?drChecked.substring(0, drChecked.length()-1):drChecked);` - ` }` - ` }` - ` return Result.ok(map);` - `}` - Problem points: - The endpoint directly uses path parameters `departId`, `roleId`, `permissionId` to query data permission rules - Does not verify whether the department and role belong to the current tenant - Attackers can obtain other tenants' data permission rule configurations - Data permission rules are sensitive permission control information, and leakage may be used to bypass access controls ### 4. Reproduction -- Prerequisites - Attacker has a valid login session - Attacker knows or can enumerate the target tenant's department ID, role ID, permission ID - System has data permission rules configured -- Steps (Cross-tenant Data Permission Rule Disclosure) - Using attacker account (Tenant A): - `curl -X GET -H "Authorization: Bearer <attacker_token>" "http://<host>/jeecgboot/sys/sysDepartRole/datarule/<permission_id>/<victim_dept_id>/<victim_role_id>"` - Observation: API returns 200 OK, returns target tenant's data permission rule configuration, including: - `datarule`: List of department permission data rules - `drChecked`: Data rule IDs selected for this role - Verification: - Use Tenant B's administrator account to query the same data rule configuration and confirm data consistency - Database query confirms the returned data rules belong to another tenant ### 5. Impact - Data permission rule disclosure - Attackers can obtain other tenants' data permission control rules - Understand the target system's data access control policies (such as filtering rules by department, region, etc.) - Complete permission system exposure - Combined with other vulnerabilities, attackers can completely map the target tenant's permission architecture - Provides intelligence for permission bypass attacks - After understanding data permission rules, targeted bypass strategies can be constructed - Business logic disclosure - Data permission rules often reflect the business's organizational structure and data access policies ### 6. Remediation - Department tenant ownership validation - Verify whether the department belongs to the current tenant before querying: - `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 rules");` - `}` - Role tenant ownership validation - Verify whether the role belongs to the current tenant's department: - `SysDepartRole role = sysDepartRoleService.getById(roleId);` - `if(role == null || !role.getDepartId().equals(departId)) {` - ` return Result.error("Role does not match department");` - `}` - Force tenant filtering - Add tenant ID filtering conditions in all queries - Permission level control - Restrict only department administrators or system administrators to view data permission rules - Audit logging - Record all data permission rule query operations for security auditing
Source⚠️ https://github.com/Hwwg/cve/issues/35
User
 huangweigang (UID 88993)
Submission12/10/2025 13:06 (4 months ago)
Moderation12/27/2025 10:01 (17 days later)
StatusAccepted
VulDB entry338500 [JeecgBoot up to 3.9.0 datarule loadDatarule departId/roleId improper authorization]
Points20

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!