HTB CWEE study materials
HTB CWEE study resources

Reset-Code Brute Force With a Trusted X-Forwarded-For

HTB CWEE · Put your knowledge to work in context.

All case studies

Reset-Code Brute Force With a Trusted X-Forwarded-For

A B2B SaaS support portal uses a 4-digit numeric password-reset code sent by email. POST /api/reset/request accepts JSON {email} and always returns {"status":"sent"}. POST /api/reset/verify accepts {email, code, new_password}. Codes expire in 30 minutes and are not invalidated after failed attempts. The verify endpoint rate-limits per client IP: 10 requests per minute, then returns HTTP 429 for 60 seconds. The app trusts the X-Forwarded-For header set by the nginx ingress. You have a valid account [email protected]; the target is [email protected]. Login response times differ: existing users take about 450 ms, non-existing users about 120 ms, but reset requests always return 200. You need to take over the admin account without causing a prolonged outage or changing the admin password more than once.

1. How would you confirm the rate-limit key and design the brute-force sequence? Include exact headers and a stopping condition.

Read the worked answer

First confirm the key. Send 11 verify requests for [email protected] with the same X-Forwarded-For: 198.51.100.10; the 11th should return 429. Then send 11 requests with distinct values such as 198.51.100.11 through .21. If all return 401 rather than 429, the limiter is keyed on the header, not the real connection.

Now request a reset for [email protected], then iterate codes 0000-9999. Each request sets X-Forwarded-For to a unique documentation IP (for example, 203.0.113.<n>) and uses Content-Type: application/json. Keep concurrency at about 10 requests/second so the 30-minute expiry is comfortably covered: 10,000 codes takes about 17 minutes. Stop at the first response that is not 401 or 429, likely 200 or 302, then immediately log in with the new password, confirm admin access, and record the exact time. Do not re-run the reset after success; that invalidates the session and prolongs the outage. If rotation still produces 429, the limiter may also key on email, in which case do not brute force blindly; re-request a code and test a smaller rate with explicit approval.

2. What evidence would you capture, and what remediation would you recommend?

Read the worked answer

Capture the reset request and verify request timestamps, the successful code, the X-Forwarded-For sequence that bypassed the limiter, the before/after login responses, and a note that no other accounts were tested. Preserve the raw HTTP requests and responses hashed and time-stamped so the client can correlate them with server logs. Also record the elapsed time and request rate to show impact was bounded.

Remediation: enforce an attempt counter per account and per code, invalidate the code after five failures, and make the counter independent of IP. Do not trust X-Forwarded-For unless it is set or overwritten by a trusted proxy; strip client-supplied values at the ingress. Use at least six to eight digits, a cryptographically random generator, constant-time comparison, and a shorter TTL such as 10 minutes. Notify the account owner on reset and require the old password or a second factor for sensitive changes. The root cause is not the 4-digit code alone; it is the combination of unlimited attempts and a spoofable rate-limit key.