Skip to content
Field Detail
Platform PortSwigger Web Security Academy
Type Race Conditions / Broken Cryptography
Difficulty Practitioner
Objective Exploit timestamp-based token generation by sending simultaneous password reset requests for wiener and carlos to obtain the same token, then use it to reset carlos's password

Exploiting Time-Sensitive Vulnerabilities

I logged in as wiener:peter and requested a password reset:

Screenshot
Screenshot

The reset token 2ef6891c9ce99cc9db45d68bfe8f1f11cbefdd1c is 40 hex characters — a SHA-1 hash:

Screenshot

Substituting carlos for wiener in the URL with the same token returned "invalid token" — user-specific. Resending the same forgot-password POST produced a different token each time, confirming it's generated fresh per request.

Screenshot

If the token is derived from a timestamp with insufficient entropy, two requests fired at the same millisecond would produce the same token. I duplicated the POST and sent both in parallel, measuring response times:

Screenshot
Screenshot

One took 584ms, the other 886ms — a ~300ms gap. Truly parallel requests should have similar response times. The staggered processing is PHP session locking: PHP serializes requests sharing a session ID, so what looks like a parallel send becomes sequential at the server. When you see this, create separate sessions for each request.

I fetched a fresh session by sending a GET with no cookie, extracting the new phpsessionid and a fresh CSRF token. Now with two independent sessions, both requests responded at the same time:

Screenshot

And the email client showed two emails with the same token. Timestamp-based token generation is cryptographically broken: a SHA-1 of a timestamp has a deterministic output for any two requests arriving in the same millisecond. Cryptographic token security requires a CSPRNG — timestamps provide neither secrecy nor sufficient entropy.

With the collision model confirmed, I updated one request to target carlos and sent both in parallel:

Screenshot
Screenshot

One email arrived in our client:

Screenshot

If the requests were truly simultaneous, wiener and carlos received the same token. Substituting carlos for wiener in the reset URL while keeping the token:

Screenshot

Reset form loaded for carlos — the token was valid. Setting a new password:

Screenshot

Logged in as carlos, navigated to /admin:

Screenshot

Deleted carlos. The vulnerability is that the token's input (the timestamp) is predictable when requests arrive simultaneously, making the output predictable too.

Lab solved

Resources