Skip to content

[Security] jshERP Role Button Permission BOLA / Privilege Escalation #158

Description

@cvecommit-byte

Affected Endpoint

jshERP-boot/src/main/java/com/jsh/erp/controller/UserBusinessController.java:89

Expected Functionality

POST /userBusiness/updateBtnStr updates the button permission string (btnStr) for a target role identified by roleId and type "RoleFunctions". The btnStr value controls which UI buttons are visible to users assigned to that role. This is a privileged tenant administration operation — only tenant administrators should be allowed to modify role permissions.

Vulnerability Description

The endpoint lacks any authorization enforcement. The controller has no permission annotations on either the class or the method. The service method updateBtnStr accepts a caller-supplied roleId and btnStr, then directly calls userBusinessMapper.updateByExampleSelective() to update the jsh_user_business table with no authorization check.

Any authenticated user can modify the button permissions of any role by supplying its roleId. This enables in-tenant privilege escalation — a low-privileged user can grant their own role (or any role they know the ID of) arbitrary button access, effectively bypassing the entire role-based access control system.

Code Evidence

Controller — jshERP-boot/src/main/java/com/jsh/erp/controller/UserBusinessController.java:89

@PostMapping(value = "/updateBtnStr")
@ApiOperation(value = "更新角色的按钮权限")
public BaseResponseInfo updateBtnStr(@RequestBody JSONObject jsonObject,
                                     HttpServletRequest request) throws Exception {
    BaseResponseInfo res = new BaseResponseInfo();
    try {
        String roleId = jsonObject.getString("roleId");
        String btnStr = jsonObject.getString("btnStr");
        String keyId = roleId;
        String type = "RoleFunctions";
        int back = userBusinessService.updateBtnStr(keyId, type, btnStr);
        // ...
    }
}

Service — jshERP-boot/src/main/java/com/jsh/erp/service/userBusiness/UserBusinessService.java

@Transactional(value = "transactionManager", rollbackFor = Exception.class)
public int updateBtnStr(String keyId, String type, String btnStr) throws Exception {
    logService.insertLog("关联关系",
            new StringBuffer(BusinessConstants.LOG_OPERATION_TYPE_EDIT)
                .append("角色的按钮权限").toString(),
            ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
    UserBusiness userBusiness = new UserBusiness();
    userBusiness.setBtnStr(btnStr);
    UserBusinessExample example = new UserBusinessExample();
    example.createCriteria().andKeyIdEqualTo(keyId).andTypeEqualTo(type);
    int result = 0;
    try {
        result = userBusinessMapper.updateByExampleSelective(userBusiness, example);
    } catch (Exception e) {
        JshException.writeFail(logger, e);
    }
    return result;
}

Attack Scenario

An attacker can supply arbitrary roleId and btnStr to modify the button permissions of any role, achieving in-tenant privilege escalation.

Remediation

Verify the authenticated user has tenant admin privileges before allowing role permission modification:

@PostMapping(value = "/updateBtnStr")
public BaseResponseInfo updateBtnStr(@RequestBody JSONObject jsonObject,
                                     HttpServletRequest request) throws Exception {
    User currentUser = userService.getCurrentUser();
    if (currentUser == null || !currentUser.getIsAdmin()) {
        BaseResponseInfo res = new BaseResponseInfo();
        res.code = 403;
        res.data = "Forbidden: admin privileges required";
        return res;
    }
    // ... proceed with update
}

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