On this page
Username Enumeration via Response Timing
Lab
Username enumeration via response timing · Practitioner
Solution
Given
This lab is vulnerable to username enumeration using its response times. To solve the lab, enumerate a valid username, brute-force this user's password, then access their account page.
Your credentials: wiener:peter
Candidate usernames
Candidate passwords
Analyzing the task
We need to set up a brute-force based on analyzing server response times. First we extract a username, then the password for it. Username and password wordlists are provided.
Recon
Let's see how the login form is set up. As usual:
POST /login
username=xxx&password=123
We run a brute-force attack on usernames. We pay attention to how long it takes the server to respond. Set the password to anything, just long — about 100 characters. After a dozen requests the response starts coming back as:
You have made too many incorrect login attempts. Please try again in 30 minute(s).
Oh!
For cases like this we can try using the X-Forwarded-For header — it tells the backend the IP address of the client that made the request when it went through a proxy. Some IP-based checks look at this header, and by setting it we can bypass the limit above, as if we became a different IP.
For this, in Intruder we need to choose attack type Pitchfork — that allows inserting several variables into the request. At the end of the request, before the body, we add X-Forwarded-For:
X-Forwarded-For: §ip§
For the first payload we can set type Number, from 1 to 10000. For the second we drop in our list of users.
After the attack finishes, we add the Response received column to see the time until the server starts responding. We sort requests by the "Response received" column. Among the requests we see one with a response time of 1414, while the others are no more than 457.
We can try brute-forcing the password for ajax — looks like that's our candidate. Payload #1 with X-Forwarded-For stays. Payload #2 will now be in the password field, and we fix the username as ajax. We look for code 302 — a redirect after a successful login. Found — summer, returned 302.
Okay, we get ajax / summer.
Lab solved.
More in this category
Web Shell Upload via Extension Blacklist Bypass (PortSwigger Lab)
.php is blacklisted, but .htaccess uploads without complaint — we slip our own Apache config in and make the server execute shell.bug as PHP.
Web Shell Upload via Obfuscated File Extension (PortSwigger Lab)
Extension blacklist rejects .php and a double-extension shell.php.jpg is served as an image — a null byte in shell.php%00.jpg bypasses both checks.
Remote Code Execution via Web Shell Upload (PortSwigger Lab)
Avatar upload has no validation — drop a PHP web shell and read /home/carlos/secret.