Test case 20 / 26FAIL

Unrestricted Resource Consumption - Authentication - Login Rate Limiting

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] Unrestricted Resource Consumption - Authentication - Login Rate Limiting

01 — Notes

Test notes

Vulnerability

[FAIL] Unrestricted Resource Consumption - Authentication - Login Rate Limiting

Description

The /login endpoint applies no rate limiting, account lockout, progressive delay, or CAPTCHA. Consecutive failed login attempts are all served at full speed. Failure responses also differ by condition, making username enumeration easier.

Impact

Confidentiality (Medium): an attacker can brute force and credential stuff any account, including administrator, without restriction. Fifty consecutive attempts against the admin account triggered neither lockout nor delay, and after all those failures a login with the correct credentials was still accepted, proving there is no lockout mechanism at all.

CWE

CWE-307: Improper Restriction of Excessive Authentication Attempts

OWASP

A07:2021 - Identification and Authentication Failures

Scenario

Normal: one login attempt with a wrong password is rejected with HTTP 401. Exploitation: fifty consecutive attempts against the admin account are sent without delay -> all are served HTTP 401, with no HTTP 429 and no lockout. Impact: after 50 failures, logging in with the correct password still succeeds, showing the account is never locked so brute force can run to completion.

Endpoint

POST http://127.0.0.1:5001/login

Affected feature

User authentication

Remediation

- Apply per-account and per-IP rate limiting with progressive delay. - Temporarily lock the account or require CAPTCHA after a number of consecutive failures. - Standardize error messages so they do not disclose username existence. - Log and alert on spikes in authentication failures, and enforce MFA.

Proof of concept

1) (Screenshot 1) NORMAL: one login attempt with a wrong password -> HTTP 401 Invalid credentials. 2) (Screenshot 2) EXPLOITATION: 50 consecutive failed attempts against the admin account -> all HTTP 401, with no HTTP 429 and no lockout. 3) (Screenshot 3) CIA IMPACT: after 50 failures, logging in with the correct password is still accepted -> the account is never locked, so brute force can run until it succeeds.
View source note (English)
Vulnerability:
[FAIL] Unrestricted Resource Consumption - Authentication - Login Rate Limiting

Description:
The /login endpoint applies no rate limiting, account lockout, progressive delay, or CAPTCHA. Consecutive failed login attempts are all served at full speed. Failure responses also differ by condition, making username enumeration easier.

Impact:
Confidentiality (Medium): an attacker can brute force and credential stuff any account, including administrator, without restriction. Fifty consecutive attempts against the admin account triggered neither lockout nor delay, and after all those failures a login with the correct credentials was still accepted, proving there is no lockout mechanism at all.

CWE:
CWE-307: Improper Restriction of Excessive Authentication Attempts

OWASP:
A07:2021 - Identification and Authentication Failures

Scenario:
Normal: one login attempt with a wrong password is rejected with HTTP 401. Exploitation: fifty consecutive attempts against the admin account are sent without delay -> all are served HTTP 401, with no HTTP 429 and no lockout. Impact: after 50 failures, logging in with the correct password still succeeds, showing the account is never locked so brute force can run to completion.

Endpoint:
POST http://127.0.0.1:5001/login

Affected Feature:
User authentication

Remediation:
- Apply per-account and per-IP rate limiting with progressive delay.
- Temporarily lock the account or require CAPTCHA after a number of consecutive failures.
- Standardize error messages so they do not disclose username existence.
- Log and alert on spikes in authentication failures, and enforce MFA.

POC:
1) (Screenshot 1) NORMAL: one login attempt with a wrong password -> HTTP 401 Invalid credentials.
2) (Screenshot 2) EXPLOITATION: 50 consecutive failed attempts against the admin account -> all HTTP 401, with no HTTP 429 and no lockout.
3) (Screenshot 3) CIA IMPACT: after 50 failures, logging in with the correct password is still accepted -> the account is never locked, so brute force can run until it succeeds.

02 — Screenshots

Screenshots (2)

01 / 1
02 / 3

03 — Process details

Process details

Credential values are masked in this HTML view; references to complete tokens describe the source capture.

PROCESS 01 / 2
01 / Test login rate limiting

Test login rate limiting

Consecutive failed logins for user 'admin'

attempt   1  ->  HTTP 401
attempt   2  ->  HTTP 401
attempt   3  ->  HTTP 401
attempt   4  ->  HTTP 401
attempt   5  ->  HTTP 401
            ...
attempt  46  ->  HTTP 401
attempt  47  ->  HTTP 401
attempt  48  ->  HTTP 401
attempt  49  ->  HTTP 401
attempt  50  ->  HTTP 401

04 — 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
HTTP request
POST /login HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 53
Content-Type: application/json

{"username": "admin", "password": "[REDACTED-LAB-VALUE]"}
HTTP response
HTTP/1.1 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 162
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:12:54 GMT

{
  "debug_info": {
    "attempted_username": "admin",
    "time": "2026-09-30 03:12:54.415082"
  },
  "message": "Invalid credentials",
  "status": "error"
}
CAPTURE 02 / 3
HTTP request
POST /login HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 45
Content-Type: application/json

{"username": "admin", "password": "[REDACTED-LAB-VALUE]"}
HTTP response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 470
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:56 GMT

{
  "accountNumber": "ADMIN001",
  "debug_info": {
    "account_number": "ADMIN001",
    "is_admin": true,
    "login_time": "2026-09-30 03:12:56.612726",
    "user_id": 1,
    "username": "admin"
  },
  "isAdmin": true,
  "message": "Login successful",
  "status": "success",
  "token": "[REDACTED-LAB-VALUE]"
}