All my security senses are tiggling when I wrote the title, but here's the scenario:

When a user wants to connect to their account, but can't remember their password, they can use the "Lost password" form, which will send an email that contains a 6 digit code that expires in 15 minutes.

The interface, when the user hit "submit" from the "Lost Password" page, will be presented with a "Enter your code" form, that expects the 6-digits number received by email.

Now, that number is not tied with anything else, so anyone entering the right code will be able to access the app. This is the point that bothers me. To mitigate this, I was planning on restricting the number of submissions for this form to 3 per minute.

So to recap:

In order for an attacker to successfully access the account, (s)he must be able to successfully guess a code that will expire in less than 15 minutes, while being throttled at 3 requests per minutes, giving them the possibility to test up to ... 45 codes (quick maf).

Can this be considered non-secure?

  • 2
    "... that number is not tied with anything else ..." - why this restriction? Why not require that the password reset init page sends a cookie and the pin enter page requires the same cookie send back and the PIN is tied to the cookie? And why not limit the total number of retries before the user is required to ask for a new PIN? With your design it is easy to DoS the password reset function for all users. Commented Jan 28, 2021 at 9:48
  • I could indeed tied the pin with the email, that's possible. I can also restrict the number of tries before asking for a new pin. But for the DoS, I don't see how: If there's a rate limit (based on the IP, not the email), one attacker will only be able to request up to 3 pin per minutes. Am I missing something?
    – Cyril N.
    Commented Jan 28, 2021 at 10:10
  • I'd say no, but I'd throttle to less than three requests per minute -- three requests in the fifteen minute grace period ought to be enough. More than that, they've a problem with their email or something.
    – LSerni
    Commented Jan 28, 2021 at 12:05
  • @CyrilN.: If the pin is not bound to anything you have a total of 3 pin per minute for all users combined. This means if an attacker does 3 pins in a minute no other user can do a password reset - that's a low bandwidth DoS of the password reset function. Commented Jan 28, 2021 at 13:13
  • @SteffenUllrich The rate limiting is tied to the IP, so the anyone can request for up to 3 PIN per minutes.
    – Cyril N.
    Commented Jan 28, 2021 at 13:15

1 Answer 1


The potential problems with the "lost password" form are several. Some of those I'm aware of:

It can be used to test / enumerate the accounts

So my form says: "Enter the username or email for your account" and then "Thank you. If this data is in the database, an email will be sent. If you do not receive the email in a few minutes, it is possible you entered the wrong username or email". Whether the user exists, or not. The page takes the start time for the submission and answers only after a set time has passed, a random number of milliseconds between 4900 and 5100.

It can be used to mount a denial of service attack

The page closes all resources and frees all memory before entering the final wait state and outputting the result, which is always '{ "status": "OK" }'. Also, there is a concurrent connection limit and a per-IP limit.

It can be used to harass someone (if the mail is right)

There is a limit of emails sent per day. And you cannot ask a new email if at least one minute hasn't passed (there is a Javascript timer to tell you this). Trying to circumvent the intentionally weak security will notify the sysadmin and lock you out for a longer time.

Also, when you request the "lost password", the account may enter a "password recovery" mode whereby the PIN and its expiry timestamp is recorded in the account aside with the intact password hash (the account has now two passwords, one of which will expire in 15 minutes). Any attempt to log in will afterward clear the PIN. This means that after every attempt to guess a PIN, the attacker has to repeat the whole "I lost my password" rigmarole, otherwise the PIN will simply be rejected.

If there is an open session for that account, and the session shows any activity during the recovery phase, the session is left undisturbed and the IP requesting the reset is blacklisted (which means that any PIN attempts from that IP will always fail). Before doing that, and only if the PIN is correct, the open session is shown a "Someone is trying to log in with your email. Is that you?" (failure to answer within a set time means that the session will be disconnected. The user having performed the successful PIN login is shown a countdown explaining that there is an outstanding session that has to be closed first

The above takes care of the "password brute force" possibility. It also tries to minimize discomfort for the legitimate users.

I sometimes use other checks on IP, browser etc., that allow putting an account into suspicious status. Users in this status may be restricted in some operations until they have performed some task that clears them, or the admin does so (e.g. if you just recovered the password and try changing some key parameters, you're told that the change was approved and pending -- but what really happens is that the admin calls you on the phone).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .