Summary
The POST /users/:id/change-password endpoint accepts the target user's ID from the URL path but performs no authorization check to verify that the requesting user is either the account owner or an administrator. Any authenticated user with the lowest-privilege (normal) role can change the password of any other user, including the administrator, effectively taking over arbitrary accounts.
Details
The handler PostUserChangePassword is defined in core/controllers/user_v2.go:
func PostUserChangePassword(c *gin.Context) {
// get id -- taken directly from URL, no ownership check
id, err := primitive.ObjectIDFromHex(c.Param("id"))
...
// get user (authenticated requester, used only for audit timestamp)
u := GetUserFromContextV2(c)
modelSvc := service.NewModelServiceV2[models.UserV2]()
// update password for the URL-supplied id, no check that id == u.Id or u.Role == admin
user, err := modelSvc.GetById(id)
...
user.Password = utils.EncryptMd5(payload.Password)
if err := modelSvc.ReplaceById(user.Id, *user); err != nil {
...
}
HandleSuccess(c)
}
The function retrieves the authenticated caller via GetUserFromContextV2(c) (used only to set the updatedBy audit field), then loads and replaces the password of the account identified by :id in the URL. There is no comparison between u.Id and id, and no check for u.Role == "admin". The route is registered on groups.AuthGroup (requires a valid JWT) but any valid JWT suffices regardless of the holder's role.
The GET /users endpoint is likewise accessible to all authenticated users and returns the full list of user records including their ObjectIDs, making it trivial for a low-privileged attacker to enumerate and target any account.
Additionally, POST /users (create user) has no role check either. A normal user can supply "role":"admin" in the request body and create a new administrator account, which is a parallel privilege-escalation path.
PoC
(available on request)
Impact
Any authenticated user, regardless of role, can permanently take over the administrator account or any other account by resetting its password. Combined with Crawlab's ability to execute arbitrary spider scripts on worker nodes, account takeover of the administrator leads to full remote code execution across the cluster. In multi-tenant or team deployments this also allows horizontal takeover of any peer account.
Affected Versions: confirmed on v0.6.3
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-639 -- Authorization Bypass Through User-Controlled Key
Summary
The
POST /users/:id/change-passwordendpoint accepts the target user's ID from the URL path but performs no authorization check to verify that the requesting user is either the account owner or an administrator. Any authenticated user with the lowest-privilege (normal) role can change the password of any other user, including the administrator, effectively taking over arbitrary accounts.Details
The handler
PostUserChangePasswordis defined incore/controllers/user_v2.go:The function retrieves the authenticated caller via
GetUserFromContextV2(c)(used only to set theupdatedByaudit field), then loads and replaces the password of the account identified by:idin the URL. There is no comparison betweenu.Idandid, and no check foru.Role == "admin". The route is registered ongroups.AuthGroup(requires a valid JWT) but any valid JWT suffices regardless of the holder's role.The
GET /usersendpoint is likewise accessible to all authenticated users and returns the full list of user records including their ObjectIDs, making it trivial for a low-privileged attacker to enumerate and target any account.Additionally,
POST /users(create user) has no role check either. A normal user can supply"role":"admin"in the request body and create a new administrator account, which is a parallel privilege-escalation path.PoC
(available on request)
Impact
Any authenticated user, regardless of role, can permanently take over the administrator account or any other account by resetting its password. Combined with Crawlab's ability to execute arbitrary spider scripts on worker nodes, account takeover of the administrator leads to full remote code execution across the cluster. In multi-tenant or team deployments this also allows horizontal takeover of any peer account.
Affected Versions: confirmed on v0.6.3
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE: CWE-639 -- Authorization Bypass Through User-Controlled Key