Skenario 21 / 26FAIL
Unrestricted Resource Consumption - Password Reset - PIN Rate Limiting
Lingkungan lab — bukan sistem produksi
Tangkapan layar dan trafik mentah tidak diterjemahkan; teks di dalamnya mungkin menggunakan bahasa lain.
vuln-bank/Evidence/[FAIL] Unrestricted Resource Consumption - Password Reset - PIN Rate Limiting
01 — Catatan
Catatan pengujian
Kerentanan
[FAIL] Unrestricted Resource Consumption - Password Reset - PIN Rate Limiting
Deskripsi
Endpoint reset password tidak menerapkan rate limiting, penguncian akun, maupun pembatasan jumlah percobaan PIN. PIN pemulihan hanya terdiri dari 3 digit sehingga ruang tebakan hanya 1000 kemungkinan dan dapat dihabiskan dalam hitungan detik.
Dampak
Confidentiality + Integrity (High): pengambilalihan akun tanpa perlu membocorkan PIN terlebih dahulu. Penyerang yang hanya mengetahui username dapat memicu permintaan reset lalu menebak seluruh ruang PIN. Pada pengujian, PIN korban ditemukan pada percobaan ke-451 dan password korban berhasil diganti, dilanjutkan login sebagai korban. Serangan ini berlaku pada endpoint v2 dan v3 yang tidak membocorkan PIN, sehingga tetap efektif meski kebocoran PIN pada v1 diperbaiki.
CWE
CWE-307: Improper Restriction of Excessive Authentication Attempts
OWASP
A07:2021 - Identification and Authentication Failures
Skenario
Normal: permintaan reset diajukan melalui /api/v2/forgot-password, PIN tidak dibocorkan pada respons. Kontrol: satu PIN salah ditolak dengan pesan Invalid reset PIN. Eksploitasi: percobaan berturut-turut dikirim tanpa jeda dan seluruhnya dilayani dengan HTTP 400 tanpa satu pun HTTP 429, penguncian, atau perlambatan. Dampak: PIN yang benar ditemukan, password korban diganti, dan login sebagai korban berhasil.
Endpoint
POST http://127.0.0.1:5001/api/v2/forgot-password
POST http://127.0.0.1:5001/api/v2/reset-password
Fitur terdampak
Pemulihan password (verifikasi PIN)
Rekomendasi perbaikan
- Terapkan rate limiting per akun dan per alamat IP, serta penguncian sementara setelah beberapa percobaan PIN yang gagal.
- Ganti PIN 3 digit dengan token acak minimal 128 bit yang sekali pakai dan berumur pendek.
- Batalkan token pemulihan setelah sejumlah kecil percobaan gagal dan haruskan permintaan reset baru.
- Kirim notifikasi ke pemilik akun pada setiap permintaan dan keberhasilan reset.
Bukti konsep
1) (Screenshot 1) NORMAL: permintaan reset via /api/v2/forgot-password -> PIN tidak dibocorkan pada respons.
2) (Screenshot 2) KONTROL: satu PIN salah (000) -> ditolak dengan Invalid reset PIN.
3) (Screenshot 3) EKSPLOITASI: percobaan PIN berturut-turut tanpa jeda -> seluruhnya dilayani HTTP 400, tidak ada HTTP 429, penguncian, maupun perlambatan.
4) (Screenshot 4) EKSPLOITASI: PIN yang benar ditemukan pada percobaan ke-451 -> reset_success true, password korban diganti.
5) (Screenshot 5) DAMPAK CIA: login sebagai pentest_victim dengan password hasil brute force -> token terbit, akun korban diambil alih.
Lihat catatan sumber (bahasa Indonesia)
Vulnerability:
[FAIL] Unrestricted Resource Consumption - Password Reset - PIN Rate Limiting
Description:
Endpoint reset password tidak menerapkan rate limiting, penguncian akun, maupun pembatasan jumlah percobaan PIN. PIN pemulihan hanya terdiri dari 3 digit sehingga ruang tebakan hanya 1000 kemungkinan dan dapat dihabiskan dalam hitungan detik.
Impact:
Confidentiality + Integrity (High): pengambilalihan akun tanpa perlu membocorkan PIN terlebih dahulu. Penyerang yang hanya mengetahui username dapat memicu permintaan reset lalu menebak seluruh ruang PIN. Pada pengujian, PIN korban ditemukan pada percobaan ke-451 dan password korban berhasil diganti, dilanjutkan login sebagai korban. Serangan ini berlaku pada endpoint v2 dan v3 yang tidak membocorkan PIN, sehingga tetap efektif meski kebocoran PIN pada v1 diperbaiki.
CWE:
CWE-307: Improper Restriction of Excessive Authentication Attempts
OWASP:
A07:2021 - Identification and Authentication Failures
Scenario:
Normal: permintaan reset diajukan melalui /api/v2/forgot-password, PIN tidak dibocorkan pada respons. Kontrol: satu PIN salah ditolak dengan pesan Invalid reset PIN. Eksploitasi: percobaan berturut-turut dikirim tanpa jeda dan seluruhnya dilayani dengan HTTP 400 tanpa satu pun HTTP 429, penguncian, atau perlambatan. Dampak: PIN yang benar ditemukan, password korban diganti, dan login sebagai korban berhasil.
Endpoint:
POST http://127.0.0.1:5001/api/v2/forgot-password
POST http://127.0.0.1:5001/api/v2/reset-password
Affected Feature:
Pemulihan password (verifikasi PIN)
Remediation:
- Terapkan rate limiting per akun dan per alamat IP, serta penguncian sementara setelah beberapa percobaan PIN yang gagal.
- Ganti PIN 3 digit dengan token acak minimal 128 bit yang sekali pakai dan berumur pendek.
- Batalkan token pemulihan setelah sejumlah kecil percobaan gagal dan haruskan permintaan reset baru.
- Kirim notifikasi ke pemilik akun pada setiap permintaan dan keberhasilan reset.
POC:
1) (Screenshot 1) NORMAL: permintaan reset via /api/v2/forgot-password -> PIN tidak dibocorkan pada respons.
2) (Screenshot 2) KONTROL: satu PIN salah (000) -> ditolak dengan Invalid reset PIN.
3) (Screenshot 3) EKSPLOITASI: percobaan PIN berturut-turut tanpa jeda -> seluruhnya dilayani HTTP 400, tidak ada HTTP 429, penguncian, maupun perlambatan.
4) (Screenshot 4) EKSPLOITASI: PIN yang benar ditemukan pada percobaan ke-451 -> reset_success true, password korban diganti.
5) (Screenshot 5) DAMPAK CIA: login sebagai pentest_victim dengan password hasil brute force -> token terbit, akun korban diambil alih.
02 — Tangkapan layar
Tangkapan layar (4)
03 — Detail proses
Detail proses
Nilai kredensial disamarkan dalam tampilan HTML ini; keterangan tentang token lengkap merujuk pada rekaman sumber.
PROSES 01 / 3
Uji rate limit PIN reset kata sandi
Percobaan PIN berturut-turut
attempt 1 -> HTTP 400
attempt 2 -> HTTP 400
attempt 3 -> HTTP 400
attempt 4 -> HTTP 400
attempt 5 -> HTTP 400
attempt 6 -> HTTP 400
attempt 7 -> HTTP 400
attempt 8 -> HTTP 400
attempt 9 -> HTTP 400
attempt 10 -> HTTP 40004 — 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
POST /api/v2/forgot-password HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 30
Content-Type: application/json
{"username": "pentest_victim"}HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 187
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:12:46 GMT
{
"debug_info": {
"timestamp": "2026-09-30 03:12:46.701456",
"username": "pentest_victim"
},
"message": "Reset PIN has been sent to your email.",
"status": "success"
}REKAMAN 02 / 2
POST /api/v2/reset-password HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 82
Content-Type: application/json
{"username": "pentest_victim", "reset_pin": "000", "new_password": "BruteForced1"}HTTP/1.1 400 BAD REQUEST
Content-Type: application/json
Content-Length: 59
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:12:48 GMT
{
"message": "Invalid reset PIN",
"status": "error"
}REKAMAN 03 / 4
POST /api/v2/reset-password HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 82
Content-Type: application/json
{"username": "pentest_victim", "reset_pin": "450", "new_password": "BruteForced1"}HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 80
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:12:51 GMT
{
"message": "Password has been reset successfully",
"status": "success"
}REKAMAN 04 / 5
POST /login HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 58
Content-Type: application/json
{"username": "pentest_victim", "password": "[REDACTED-LAB-VALUE]"}HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 498
Set-Cookie: token=[REDACTED-LAB-TOKEN]; HttpOnly; Path=/
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:12:53 GMT
{
"accountNumber": "9159912486",
"debug_info": {
"account_number": "9159912486",
"is_admin": false,
"login_time": "2026-09-30 03:12:53.293519",
"user_id": 3,
"username": "pentest_victim"
},
"isAdmin": false,
"message": "Login successful",
"status": "success",
"token": "[REDACTED-LAB-VALUE]"
}