sec: enforce admin check on layout assignment and role grant endpoints#36344
sec: enforce admin check on layout assignment and role grant endpoints#36344mbiuki wants to merge 1 commit into
Conversation
ToolGroupResource._addtouser and ._removefromuser now require the caller to be a CMS Administrator before assigning or removing any layout other than the gettingStarted onboarding layout. Previously any backend user could self-assign the admin Settings layout (which contains the roles portlet), bypassing the intended privilege boundary. RoleAjax.addUserToRole and .removeUsersFromRole now require the caller to be a CMS Administrator in addition to the existing portlet-access check. Previously a user who had gained roles-portlet access could grant themselves (or any user) any role including CMS Administrator via DWR. Together these two gaps formed a privilege-escalation chain that allowed any authenticated backend user to reach CMS Administrator and subsequently execute arbitrary OS commands via OSGi bundle upload. Closes: dotCMS/private-issues#640 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
❌ Issue Linking RequiredThis PR could not be linked to an issue. All PRs must be linked to an issue for tracking purposes. How to fix this:Option 1: Add keyword to PR body (Recommended - auto-removes this comment)
Why is this required?Issue linking ensures proper tracking, documentation, and helps maintain project history. It connects your code changes to the problem they solve.--- This comment was automatically generated by the issue linking workflow |
|
Claude finished @mbiuki's task in 1m 42s —— View job Rollback Safety Analysis
Result: ✅ Safe To RollbackLabel applied: Analysis: The two changed files contain pure Java authorization logic only:
Checked against all unsafe categories — none apply:
Rollback scenario: Rolling back to N-1 simply removes the new admin guard — previously-unprotected endpoints become unprotected again, which is the known pre-patch state. No data, schema, or index state is affected by this change in either direction. |
🤖 dotBot Review (Bedrock)Reviewed 2 file(s); 0 candidate(s) → 0 confirmed, 0 uncertain (unverified, kept for review). ✅ No issues found after verification. us.deepseek.r1-v1:0 · Run: #28331363735 · tokens: in: 4318 · out: 1404 · total: 5722 · calls: 2 · est. ~$0.013 |
|
This PR fixes https://github.com/dotCMS/private-issues/issues/642 |
PRs linked to this issue |
Versions AffectedExploitable range: v21.02 → v26.06.22-03 (current latest)
No patched release has been cut yet — this PR is the fix. |
Vulnerability Introduction Timeline
|
| Date | Commit | Author | Event |
|---|---|---|---|
| 2020-12-16 | 8aa87f7b87 |
Will Ezell | Method created without any admin check (PR #19680, issue #19581) — only requiredBackendUser(true) enforced |
| 2021-03-22 | 890feffa94 |
Nollymar Longa | ?userid= parameter added — widened exploit surface from self-assignment to assigning layouts to any user |
| 2025-11-04 | 3babaf0d17 |
— | Partial portlet-level mitigation added (private-issues#482) — insufficient alone |
| PR #36344 | — | — | Full fix: admin-only gate added — not yet in any release |
Affected Versions
- First vulnerable release:
21.02(December 2020 commit shipped in the Feb 2021 release cut) - Widened attack surface (other-user assignment): ~
21.03–21.04(March 2021 commit) - All affected:
21.02→v26.06.22-03(current latest), including all LTS lines:- 23.10 LTS ✗
- 24.04 LTS ✗
- 24.12 LTS ✗
- 25.07 LTS ✗
- Partial mitigation from:
v25.11.07-1(still exploitable via chain with sec: enforce admin check on layout assignment and role grant endpoints #36344) - Fully fixed in: not yet released
Summary
Fixes a privilege-escalation chain (reported via responsible disclosure) that allowed any authenticated backend user to reach CMS Administrator and subsequently achieve remote code execution via OSGi bundle upload.
Attack chain closed by this PR:
PUT /api/v1/toolgroups/{id}/_addtouser— any backend user could self-assign the admin Settings layout (containing therolesportlet) with no privilege checkPOST /dwr/call/plaincall/RoleAjax.addUserToRole.dwr— with therolesportlet now accessible, the user could grant themselves the CMS Administrator role; the only gate was portlet-access, which step 1 satisfiedChanges
ToolGroupResource.java_addtouser: requireloggedInUser.isAdmin()for all layouts exceptgettingstarted(the onboarding layout — intentionally self-assignable)_removefromuser: same admin guard applied symmetricallyRoleAjax.javaaddUserToRole: addcaller.isAdmin()check after the existing portlet-access check; log unauthorized attempts viaSecurityLoggerremoveUsersFromRole: same admin guard applied symmetricallyTest plan
PUT /api/v1/toolgroups/{layout_id}/_addtouser(non-gettingStarted layout)gettingStartedlayout self-assignment still works for non-admin users (onboarding flow must not break)RoleAjax.addUserToRolevia DWRReferences
🤖 Generated with Claude Code