Skenario 23 / 26PASS

Broken Object Level Authorization - GraphQL - Transaction Summary

Lingkungan lab — bukan sistem produksi

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

vuln-bank/Evidence/[PASS] Broken Object Level Authorization - GraphQL - Transaction Summary

01 — Catatan

Catatan pengujian

Kerentanan

[PASS] Broken Object Level Authorization - GraphQL - Transaction Summary

Deskripsi

Pengujian berupaya membaca ringkasan transaksi milik pengguna lain melalui argumen accountNumber pada resolver GraphQL transactionSummary, termasuk rekening korban dan rekening administrator.

Dampak

Tidak ada dampak. Kontrol bertahan: resolver membandingkan accountNumber yang diminta dengan rekening milik pemegang token dan menolak permintaan lintas objek dengan galat eksplisit. Pengguna biasa hanya dapat membaca ringkasan transaksi rekeningnya sendiri. Catatan: jalur kode yang sama tetap bermasalah bagi pemanggil dengan peran administrator, karena nilai argumen diteruskan ke query SQL tanpa parameterisasi; hal tersebut dilaporkan terpisah pada temuan SQL Injection - GraphQL.

CWE

CWE-639: Authorization Bypass Through User-Controlled Key

OWASP

A01:2021 - Broken Access Control

Skenario

Normal: pengguna biasa meminta ringkasan transaksi rekeningnya sendiri -> berhasil. Percobaan: accountNumber diganti dengan rekening korban -> ditolak. Percobaan: accountNumber diganti dengan rekening administrator -> ditolak.

Endpoint

POST http://127.0.0.1:5001/graphql

Fitur terdampak

GraphQL transactionSummary (otorisasi objek)

Rekomendasi perbaikan

- Pertahankan pemeriksaan kepemilikan rekening pada resolver. - Lengkapi dengan parameterized query agar argumen yang sama tidak menjadi titik injeksi bagi pemanggil dengan hak lebih tinggi.

Bukti konsep

1) (Screenshot 1) NORMAL: pengguna biasa meminta ringkasan transaksi rekeningnya sendiri -> berhasil. 2) (Screenshot 2) PERCOBAAN: accountNumber diganti dengan rekening korban -> ditolak dengan galat You can only query your own transaction summary, kontrol bertahan. 3) (Screenshot 3) PERCOBAAN: accountNumber diganti dengan rekening administrator -> ditolak, kontrol bertahan.
Lihat catatan sumber (bahasa Indonesia)
Vulnerability:
[PASS] Broken Object Level Authorization - GraphQL - Transaction Summary

Description:
Pengujian berupaya membaca ringkasan transaksi milik pengguna lain melalui argumen accountNumber pada resolver GraphQL transactionSummary, termasuk rekening korban dan rekening administrator.

Impact:
Tidak ada dampak. Kontrol bertahan: resolver membandingkan accountNumber yang diminta dengan rekening milik pemegang token dan menolak permintaan lintas objek dengan galat eksplisit. Pengguna biasa hanya dapat membaca ringkasan transaksi rekeningnya sendiri.

Catatan: jalur kode yang sama tetap bermasalah bagi pemanggil dengan peran administrator, karena nilai argumen diteruskan ke query SQL tanpa parameterisasi; hal tersebut dilaporkan terpisah pada temuan SQL Injection - GraphQL.

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

OWASP:
A01:2021 - Broken Access Control

Scenario:
Normal: pengguna biasa meminta ringkasan transaksi rekeningnya sendiri -> berhasil. Percobaan: accountNumber diganti dengan rekening korban -> ditolak. Percobaan: accountNumber diganti dengan rekening administrator -> ditolak.

Endpoint:
POST http://127.0.0.1:5001/graphql

Affected Feature:
GraphQL transactionSummary (otorisasi objek)

Remediation:
- Pertahankan pemeriksaan kepemilikan rekening pada resolver.
- Lengkapi dengan parameterized query agar argumen yang sama tidak menjadi titik injeksi bagi pemanggil dengan hak lebih tinggi.

POC:
1) (Screenshot 1) NORMAL: pengguna biasa meminta ringkasan transaksi rekeningnya sendiri -> berhasil.
2) (Screenshot 2) PERCOBAAN: accountNumber diganti dengan rekening korban -> ditolak dengan galat You can only query your own transaction summary, kontrol bertahan.
3) (Screenshot 3) PERCOBAAN: accountNumber diganti dengan rekening administrator -> ditolak, kontrol bertahan.

02 — Tangkapan layar

Tangkapan layar (3)

01 / 1
02 / 2
03 / 3

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
POST /graphql 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-Type: application/json
Content-Length: 148

{"query": "query($a:String){transactionSummary(accountNumber:$a,limit:3){scope accountNumber totalTransactions}}", "variables": {"a": "0932191785"}}
HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 149
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:13 GMT

{
  "data": {
    "transactionSummary": {
      "accountNumber": "0932191785",
      "scope": "account",
      "totalTransactions": 11
    }
  }
}
REKAMAN 02 / 2
HTTP request
POST /graphql 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-Type: application/json
Content-Length: 148

{"query": "query($a:String){transactionSummary(accountNumber:$a,limit:3){scope accountNumber totalTransactions}}", "variables": {"a": "9159912486"}}
HTTP response
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
Content-Length: 361
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:14 GMT

{
  "data": {
    "transactionSummary": null
  },
  "errors": [
    {
      "message": "You can only query your own transaction summary.\n\nGraphQL request:1:18\n1 | query($a:String){transactionSummary(accountNumber:$a,limit:3){scope accountNumber totalTransactions}}\n  |                  ^",
      "path": [
        "transactionSummary"
      ]
    }
  ]
}
REKAMAN 03 / 3
HTTP request
POST /graphql 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-Type: application/json
Content-Length: 146

{"query": "query($a:String){transactionSummary(accountNumber:$a,limit:3){scope accountNumber totalTransactions}}", "variables": {"a": "ADMIN001"}}
HTTP response
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
Content-Length: 361
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:15 GMT

{
  "data": {
    "transactionSummary": null
  },
  "errors": [
    {
      "message": "You can only query your own transaction summary.\n\nGraphQL request:1:18\n1 | query($a:String){transactionSummary(accountNumber:$a,limit:3){scope accountNumber totalTransactions}}\n  |                  ^",
      "path": [
        "transactionSummary"
      ]
    }
  ]
}