high · 8.8Jul 24, 2026

Poweradmin: API Broken Access Control Allows Non-Admin to Reset Any User's Password

Shubham Kandhare
Security Engagement Manager, SecureLayer7

A delegated user-manager in Poweradmin can send one API request to overwrite the administrator's password and fully take over the instance, because the REST API skips two authorization guards that…

Packagepoweradmin/poweradmin
Ecosystemcomposer
Affected>= 4.0.0, < 4.2.5
Fixed in4.2.5
Poweradmin: API Broken Access Control Allows Non-Admin to Reset Any User's Password

The problem

Poweradmin's REST API (v1 and v2) exposes a user-update endpoint that does not check whether the target account belongs to a superuser, and does not require the user_passwd_edit_others permission before writing a new password hash.

Any account holding user_edit_others (a normal delegated helpdesk or user-manager role) can therefore overwrite the password of the administrator account (typically id 1) with a single authenticated request. The web UI explicitly blocks this same action. The API and the web UI enforce completely different permission models, making the API the weaker path.

Proof of concept

A working proof-of-concept for this issue in poweradmin/poweradmin, with the exact payload below.

http
PUT /api/v2/users/1 HTTP/1.1
Host: TARGET_HOST
X-API-Key: pwa_umgr_key
Content-Type: application/json
Content-Length: 30

{"password":"NewAdminPass1!"}

The root cause is in ApiPermissionService::canEditUser(): it returns true for any caller with user_edit_others against any target, with no check on whether the target holds user_is_ueberuser. The web controller explicitly fetches that flag and returns an error if a non-superuser tries to edit a superuser.

A second, independent gap sits in UserManagementService::updateUser(): it writes a bcrypt hash of the supplied password whenever password is non-empty, with no permission gate at all (it only rejects external-auth accounts). The web path gates the same write behind user_passwd_edit_others.

The patch mirrors the web guards into the API layer: canEditUser() now rejects a non-superuser editing a superuser target, and updateUser() only writes the password column when the caller is editing their own account or holds user_passwd_edit_others. Both fixes apply to the V1 and V2 controllers.

CWE-620 (Unverified Password Change) and CWE-862 (Missing Authorization).

The fix

Upgrade to Poweradmin 4.2.5 or later (patch commits 36e9081, 9bdda77, b90fd83, ffb95d5). If you cannot upgrade immediately, disable the REST API (api.enabled = false in config/settings.php) or revoke API keys from any account holding user_edit_others but not user_is_ueberuser.

Reported by Saif Salah.

References: [1][2][3][4][5][6]

Related research