Test case 05 / 26FAIL

Broken Object Level Authorization - Users - User Detail API

Lab environment — not a production system

Screenshots and raw traffic are not translated; text within them may be in another language.

vuln-bank/Evidence/[FAIL] Broken Object Level Authorization - Users - User Detail API

01 — Notes

Test notes

Vulnerability

[FAIL] Broken Object Level Authorization - Users - User Detail API

Description

The /api/v3/user/<user_id> endpoint returns a user profile based on the user_id in the path without checking that the profile belongs to the token holder or that the caller is an administrator. user_id is a sequential integer.

Impact

Confidentiality (High): any authenticated user can increment user_id to harvest every customer's profile, including account number, balance, bio, and administrator flag. This data fuels follow-on attacks: harvested account numbers are used in balance IDOR and transfers, while the is_admin flag identifies high-value targets.

CWE

CWE-639: Authorization Bypass Through User-Controlled Key

OWASP

A01:2021 - Broken Access Control

Scenario

Normal: the attacker reads their own profile (user_id 2). Exploitation: user_id is changed to 3 -> the victim's profile is readable. Impact: user_id 1 is read -> the administrator profile with account number, balance, and is_admin true is exposed to an ordinary user.

Endpoint

GET http://127.0.0.1:5001/api/v3/user/<user_id>

Affected feature

User detail API (used by the admin panel for the user detail modal)

Remediation

- Restrict the endpoint to returning only the token holder's profile, and provide a separate administrative endpoint that checks the role from the database. - Use random UUIDs as user identifiers. - Reduce response fields to the minimum required by the interface.

Proof of concept

1) (Screenshot 1) NORMAL: the attacker reads their own profile at user_id 2. 2) (Screenshot 2) EXPLOITATION: user_id 3 is read -> the victim's profile is exposed. 3) (Screenshot 3) CIA IMPACT: user_id 1 is read -> the administrator profile, account number ADMIN001, balance, and is_admin true are exposed to an ordinary user.
View source note (English)
Vulnerability:
[FAIL] Broken Object Level Authorization - Users - User Detail API

Description:
The /api/v3/user/<user_id> endpoint returns a user profile based on the user_id in the path without checking that the profile belongs to the token holder or that the caller is an administrator. user_id is a sequential integer.

Impact:
Confidentiality (High): any authenticated user can increment user_id to harvest every customer's profile, including account number, balance, bio, and administrator flag. This data fuels follow-on attacks: harvested account numbers are used in balance IDOR and transfers, while the is_admin flag identifies high-value targets.

CWE:
CWE-639: Authorization Bypass Through User-Controlled Key

OWASP:
A01:2021 - Broken Access Control

Scenario:
Normal: the attacker reads their own profile (user_id 2). Exploitation: user_id is changed to 3 -> the victim's profile is readable. Impact: user_id 1 is read -> the administrator profile with account number, balance, and is_admin true is exposed to an ordinary user.

Endpoint:
GET http://127.0.0.1:5001/api/v3/user/<user_id>

Affected Feature:
User detail API (used by the admin panel for the user detail modal)

Remediation:
- Restrict the endpoint to returning only the token holder's profile, and provide a separate administrative endpoint that checks the role from the database.
- Use random UUIDs as user identifiers.
- Reduce response fields to the minimum required by the interface.

POC:
1) (Screenshot 1) NORMAL: the attacker reads their own profile at user_id 2.
2) (Screenshot 2) EXPLOITATION: user_id 3 is read -> the victim's profile is exposed.
3) (Screenshot 3) CIA IMPACT: user_id 1 is read -> the administrator profile, account number ADMIN001, balance, and is_admin true are exposed to an ordinary user.

02 — Screenshots

Screenshots (3)

01 / 1
02 / 2
03 / 3

03 — Requests and responses

HTTP captures

Some credential values are masked in this public HTML view. This does not mean every sensitive value or linked file has been redacted.

CAPTURE 01 / 1
HTTP request
GET /api/v3/user/2 HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]

HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 197
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:15 GMT

{
  "status": "success",
  "user": {
    "account_number": "0932191785",
    "balance": -8100.0,
    "bio": null,
    "id": 2,
    "is_admin": false,
    "username": "pentest_attacker"
  }
}
CAPTURE 02 / 2
HTTP request
GET /api/v3/user/3 HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]

HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 195
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:16 GMT

{
  "status": "success",
  "user": {
    "account_number": "9159912486",
    "balance": 10100.0,
    "bio": null,
    "id": 3,
    "is_admin": false,
    "username": "pentest_victim"
  }
}
CAPTURE 03 / 3
HTTP request
GET /api/v3/user/1 HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]

HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 185
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:17 GMT

{
  "status": "success",
  "user": {
    "account_number": "ADMIN001",
    "balance": 1000000.0,
    "bio": null,
    "id": 1,
    "is_admin": true,
    "username": "admin"
  }
}