On this page
apsyleg1 min read
#portswigger #authentication #web-security

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.