Everything you ever wanted to know about secure password reset. Part 1

I recently had time to think again about how the secure password reset feature should work, first when I built the functionality into ASafaWeb, and then when he helped to do something similar to another person. In the second case, I wanted to give him a link to the canonical resource with all the details of the safe implementation of the reset function. However, the problem is that such a resource does not exist, at least not one that describes everything that seems important to me. So I decided to write it myself.

You see, the world of forgotten passwords is actually quite mysterious. There are many different, perfectly acceptable points of view and a lot of rather dangerous ones. It is likely that you have encountered each of them many times as an end user; so I'll try to use these examples to show who does it right and who doesn't, and what you need to focus on to properly implement a feature in your application.

Everything you ever wanted to know about secure password reset. Part 1

Password storage: hashing, encryption and (oh!) plain text

We can't discuss what to do with forgotten passwords before we discuss how they are stored. Passwords are stored in the database in one of three main types:

  1. Plain text. There is a column with a password, which is stored in plain text.
  2. encrypted. Usually using symmetric encryption (one key is used for both encryption and decryption), and encrypted passwords are also stored in the same column.
  3. hashed. One-way process (password can be hashed but not dehashed); password, hopefully, followed by a salt, and each one is in its own column.

Let's deal with the simplest question right away: never store passwords in plain text! Never. One single vulnerability injections, one carelessly made backup copy or one of dozens of other simple mistakes - and that's it, gameover, all your passwords - that is, sorry, passwords for all your clients will become public property. Of course, this will mean a huge likelihood that all their passwords from all their accounts in other systems. And it will be your fault.

Encryption is better, but has its weaknesses. The problem of encryption is in decryption; we can take these crazy looking ciphers and convert them back to plain text, and when that happens, we're back to the situation with readable passwords. How does this happen? A small flaw gets into the code that decrypts the password, making it publicly available - this is one way. Access to the machine on which the encrypted data is stored is obtained by hackers - this is the second way. Another way, again, is to steal the backup of the database, and someone also gets the encryption key, which is often stored very insecurely.

And that brings us to hashing. The idea behind hashing is that it is done one way; the only way to compare the password entered by the user with its hashed version is to hash the password entered and compare them. To prevent attacks using tools like rainbow tables, we use salt to add randomness to the process (for the full picture, read my post about cryptographic storage). Ultimately, if implemented correctly, we can safely assume that hashed passwords will never become plain text again (I will discuss the benefits of different hashing algorithms in another post).

Quick argument about hashing and encryption: The only reason you'll ever need to encrypt rather than hash a password is when you need to see the password in plain text instead of you should never want it, at least in the situation of a standard website. If you need this, then most likely you are doing something wrong!

Attention!

A little further down in the text of the post is part of a screenshot of the pornographic website AlotPorn. It's neatly cropped, so there's nothing that can't be seen on the beach, but if that still causes problems, then don't scroll down the page.

Always reset your password never don't remind him

Have you ever been asked to create a function reminders password? Take a step back and think about this request in reverse: why is this β€œreminder” needed? Because the user has forgotten the password. What do we really want to do? Help him to log in again.

I understand the word "reminder" is used (often) colloquially, but what we're really trying to do is safely help the user to be online again. Since we need security, there are two reasons why a reminder (i.e. sending the user their password) is not appropriate:

  1. Email is an insecure channel. Just as we wouldn't send anything confidential over HTTP (we'd use HTTPS), we shouldn't send anything over email because its transport layer is insecure. In fact, this is much worse than simply sending information over an insecure transport protocol, because mail is often stored on the drive, available to system administrators, forwarded and distributed, available to malware, and so on. Unencrypted mail is an extremely insecure channel.
  2. You should not have access to the password anyway. Reread the previous section on storage - you must have a hash of the password (with a good strong salt), meaning there is no way you should be able to extract the password and mail it.

Let me demonstrate the problem with an example usoutdoor.com: Here is a typical login page:

Everything you ever wanted to know about secure password reset. Part 1
Obviously the first problem is that the login page doesn't load over HTTPS, but the site also offers to send a password ("Send Password"). Perhaps this is an example of the colloquial use of the term mentioned above, so let's take it one step further and see what happens:

Everything you ever wanted to know about secure password reset. Part 1
It doesn't look much better, unfortunately; and the email confirms there is a problem:

Everything you ever wanted to know about secure password reset. Part 1
This tells us about two important aspects of usoutdoor.com:

  1. The site does not hash passwords. At best, they are encrypted, but it is likely that they are stored in plain text; We see no evidence to the contrary.
  2. The site sends a long-term password (we can go back and use it again and again) over an insecure channel.

With that out of the way, we need to check if the reset process is running in a safe manner. The first step to do this is to make sure that the requester has the right to perform the reset. In other words, before that we need an identity check; Let's take a look at what happens when an identity is verified without first verifying that the requester is indeed the owner of the account.

Enumeration of usernames and its impact on anonymity

This problem is best illustrated visually. Problem:

Everything you ever wanted to know about secure password reset. Part 1
See? Pay attention to the message "There is no user registered with this email address". The problem obviously arises if a similar site confirms availability registered with such an e-mail address of the user. Bingo - you've just discovered your husband/boss/neighbor's porn fetish!

Of course, porn is a fairly canonical example of the importance of privacy, but the dangers of being matched with a particular website are far greater than the potentially embarrassing situation described above. One danger is social engineering; if an attacker can match a person to a service, then he will have information that he can start using. For example, he may contact a person posing as a representative of a website and request additional information in an attempt to spearphishing.

Such practices also raise the danger of "username enumeration", in which it is possible to check the existence of an entire collection of usernames or email addresses on a website by simple bulk queries and examining the responses to them. Do you have a list of all employees' email addresses and a few minutes to write a script? Then you see what the problem is!

What is the alternative? In fact, it is quite simple, and remarkably implemented on Entropay:

Everything you ever wanted to know about secure password reset. Part 1
Here, Entropay does not reveal anything at all about the existence of an email address in its system. to someone who does not own this address... If you own address and it does not exist in the system, you will receive an email like this:

Everything you ever wanted to know about secure password reset. Part 1
Of course, there are acceptable situations in which someone thinksthat registered on the website. but this is not the case, or did it from a different mail address. The above example successfully handles both situations. Obviously, if the address matches, then you will receive an email that makes it easy to reset your password.

The subtlety of the solution chosen by Entropay is that identification verification is performed by e-mail prior to any online check. Some sites ask users for the answer to a security question (more on this below) to how the reset can start; however, the problem with this is that you have to answer the question while providing some form of identification (email or username), which makes it next to impossible to answer intuitively without revealing the existence of an anonymous user account.

With this approach, there a little decrease in usability, because in case of an attempt to reset a non-existent account, there is no instant feedback. Of course, this is the whole point of sending an email, but from the point of view of the real end user, if he enters the wrong address, he will only know about it for the first time when he receives the letter. This can cause some tension on his part, but this is a small price to pay for such a rare process.

Another slightly off-topic note: Login assist functions that reveal the correct username or email address have the same problem. Always respond to the user with the message "You username and password combination is invalid", rather than explicitly confirming the existence of the identity information (for example, "the username is correct, but the password is incorrect").

Sending a Reset Password vs Sending a Reset URL

The next concept we need to discuss has to do with the password reset method. There are two popular solutions:

  1. Generating a new password on the server and sending it by email
  2. Sending an email with a unique URL to simplify the reset process

Despite many guides, the first point should never be used. His problem is that it means having stored password, to which you can return and use again at any time; it was transmitted over an insecure channel and remains in your inbox. There is a chance that inboxes are synced with mobile devices and email client, plus they can be kept online in a web based email service for a very long time. The point is that the mailbox cannot be considered as a reliable means for long-term storage.

But besides this, the first paragraph has another serious problem - it simplifies as much as possible account blocking with malicious intent. If I know the email address of someone who owns an account on a website, then I can block him at any time by simply resetting his password; it's a denial of service attack on a silver platter! That is why the reset should be performed only after a successful check with the requester for rights to it.

When we talk about the reset URL, we mean the website address, which is unique to this particular case of the reset process. Of course, it must be random, it must not be easy to guess, and it must not contain any external references to the account that make it easy to reset. For example, the reset URL should not just be a path like "Reset/?username=JohnSmith".

We want to create a unique token that can be mailed as a reset URL and then matched against the server record of the user account, thus verifying that the account owner is indeed the same person who is trying to reset the password. . For example, a token might look like "3ce7854015cd38c862cb9e14a1ae552b" and stored in a table along with the resetting user ID and the token generation time (more on that in a moment). When the email is sent, it contains a URL like "Reset/?id=3ce7854015cd38c862cb9e14a1ae552b", and when the user loads it, the page asks for the existence of the token, then confirms the user's information and allows the password to be changed.

Of course, since the above process (hopefully) allows the user to create a new password, we need to ensure that the URL is loaded over HTTPS. No, passing it as a POST request over HTTPS is not enough, this URL with the token must use transport layer security so that the new password entry form cannot be attacked MITM and the password created by the user was transmitted over a secure connection.

Also, for the reset URL, you need to add a token time limit so that the reset process can be completed within a certain interval, say, within an hour. This ensures that the reset time window is kept as short as possible so that the recipient of this reset URL can only act within this very small window. Of course, an attacker can start the reset process again, but he will need to get another unique reset URL.

Finally, we need to ensure that this process is disposable. Once the reset process is complete, the token must be removed so that the reset URL is no longer valid. The previous point is needed so that the attacker has a very small window during which he can manipulate the reset URL. Plus, of course, after the successful completion of the reset, the token is no longer needed.

Some of these steps may seem redundant, but they do not interfere with usability and actually improve safety, albeit in situations that we hope will be rare. In 99% of cases, the user will enable the reset within a very short period of time and will not reset the password again in the near future.

Role of CAPTCHA

Oh, CAPTCHA, the security measure we all love to hate! In fact, CAPTCHA is not so much a means of protection as identification - you are a person or a robot (or an automated script). Its purpose is to avoid automatic form submissions, which, of course, can be used as an attempt to break the protection. In the context of resetting passwords, CAPTCHA means that the reset function cannot be brute-forced to either spam the user or try to determine the existence of accounts (which, of course, would not be possible if you followed the tips in the section on identity verification).

Of course, CAPTCHA itself isn't perfect; there are many precedents for it to be programmatically "hacked" and achieve sufficient success rates (60-70%). Also, there is a solution shown in my post about CAPTCHA cracking by automated people, where you can pay people fractions of a cent to solve each CAPTCHA and get a 94% success rate. That is, it is vulnerable, but (slightly) raises the entry barrier.

Let's take a look at a PayPal example:

Everything you ever wanted to know about secure password reset. Part 1
In this case, the reset process simply cannot start before the CAPTCHA is solved, so theoretically it is impossible to automate the process. In theory.

However, for most web applications this will be overkill and absolutely right represents a decrease in usability - people just don't like CAPTCHAs! In addition, CAPTCHA is such a thing that you can easily return to if necessary. If the service starts to be attacked (logging comes in handy here, but more on that later), then adding a CAPTCHA couldn't be easier.

Secret Questions and Answers

With all the methods we looked at, we were able to reset the password, just by having access to the email account. I say "just", but of course, illegally gaining access to someone else's mail account must be a complex process. However it is not always so.

In fact, the above link about Sarah Palin's Yahoo! serves two purposes; first, it illustrates how easy it is to hack (some) email accounts, and second, it shows how bad security questions can be used maliciously. But we will return to this later.

The problem with resetting passwords that are XNUMX% email dependent is that the account integrity of the site you're trying to reset becomes XNUMX% dependent on the integrity of the email account. Anyone who has access to your email has access to any account that can be reset by simply receiving an email. For such accounts, email is the "key to all doors" of your online life.

One way to mitigate this risk is to implement a security question and answer pattern. No doubt you have already seen them: choose a question that only you have know the answer, after which, when you reset your password, you are asked it. This adds to the confidence that the person trying to reset is indeed the owner of the account.

Back to Sarah Palin, the mistake was that the answers to her secret question/questions were easy to find. Particularly when you're such a big public figure, information about your mother's maiden name, school history, or where someone might have lived in the past isn't all that secret. In fact, most of it can be found by just about anyone. This is what happened to Sarah.

Hacker David Kernell gained access to Palin's account by finding her background details, such as her high school and date of birth, and then using Yahoo!'s lost account password recovery feature.

This is primarily a design error on the part of Yahoo! - By specifying such simple questions, the company essentially sabotaged the value of the security question, and therefore the protection of its system. Of course, resetting passwords on an email account is always trickier, since you can't verify ownership of it by emailing the owner (without having a second address), but thankfully there aren't many uses for such a system today.

Back to secret questions - there is an option to allow the user to create their own questions. The problem is that the result will be terribly obvious questions:

What color is the sky?

Questions that put people in an uncomfortable position when a security question uses a secret question to identify people (for example, in a call center):

Who did I sleep with at Christmas?

Or frankly stupid questions:

How do you spell "password"?

When it comes to security questions, users need to be saved from themselves! In other words, the secret question should determine the site itself, or even better, ask series security questions from which the user can choose. And don't just choose one; ideally the user should select two or more security questions at the time of account registration, which will then be used as a second identification channel. Having multiple questions increases confidence in the verification process, and also allows for randomness (not always showing the same question), plus provides a bit of redundancy in case the real user forgets the password.

What should be a good security question? Several factors influence this:

  1. He must be brief The question should be clear and unambiguous.
  2. The answer must be specific β€” we do not need a question that one person can answer in different ways
  3. Possible answers should be varied Asking someone's favorite color gives a very small subset of possible answers.
  4. Search the answer must be complex - if the answer can easily be found any (think of people in a high position), then he is bad
  5. The answer must be permanent in time - if you ask someone's favorite movie, then a year later the answer may be different

As it happens, there is a website dedicated to good questions called GoodSecurityQuestions.com. Some of the questions seem to be quite good, others fail some of the tests described above, in particular the "easy to find" test.

Let me show you how security questions are implemented in PayPal and, in particular, how much effort the site puts into identification. We saw the process start page (with CAPTCHA) above, and here we show what happens after you enter your email address and solve the CAPTCHA:

Everything you ever wanted to know about secure password reset. Part 1
As a result, the user receives the following email:

Everything you ever wanted to know about secure password reset. Part 1
So far so normal, but here's what's behind this reset URL:

Everything you ever wanted to know about secure password reset. Part 1
So, secret questions come into play. In fact, PayPal also allows you to reset your password by verifying your credit card number, so there is an additional channel that many sites don't have access to. I just can't change my password without answering both secret question (or not knowing the card number). Even if someone hijacks my email, they won't be able to reset their PayPal account password unless they know a little more personal information about me. What information? Here are the options for security questions offered by PayPal:

Everything you ever wanted to know about secure password reset. Part 1
The school and hospital question might be a little iffy in terms of ease of searching, but the others aren't that bad. However, to improve security, PayPal requires additional identification for changes answers to security questions:

Everything you ever wanted to know about secure password reset. Part 1
PayPal is a rather utopian example of a secure password reset: it implements a CAPTCHA to reduce the risk of brute force, requires two security questions, and then requires yet another kind of completely different identity just to change the answers - and that's after the user has already signed in. Of course, this is exactly what we expected would be from PayPal; it is a financial institution dealing with large sums of money. This doesn't mean that every password reset has to follow these steps - it's overkill in most cases - but it's a good example for cases where security is serious business.

The convenience of the security question system is that if you did not implement it right away, then you can add it later if the level of protection of the resource requires it. A good example of this is Apple, which has only recently implemented this mechanism. [article written in 2012]. Once I started to update the application on the iPad, I saw the following request:

Everything you ever wanted to know about secure password reset. Part 1
Then I saw a screen where I could select multiple pairs of security questions and answers, as well as a rescue email address:

Everything you ever wanted to know about secure password reset. Part 1
As for PayPal, the questions are preselected and some of them are actually quite good:

Everything you ever wanted to know about secure password reset. Part 1
Each of the three pairs of questions and answers represents a different set of possible questions, so there are plenty of ways to configure an account.

Another aspect to consider regarding the answer to the security question is storage. Plain text in the DB poses almost the same threats as in the case of a password, namely, exposing the database instantly reveals the value and puts not only the application at risk, but potentially completely different applications using the same security questions (this is again acai berry question). One option is secure hashing (a strong algorithm and a cryptographically random salt), but unlike most password storage cases, there may be a good reason for the response to appear as plain text. A typical scenario is identity verification by a live telephone operator. Of course, hashing is also applicable in this case (the operator can simply enter the answer named by the client), but in the worst case, the secret answer must be at some level of cryptographic storage, even if it is just symmetric encryption. Summarize: treat secrets like secrets!

And the last aspect of secret questions and answers is that they are more vulnerable to social engineering. Trying to directly solicit the password to someone else's account is one thing, but striking up a conversation about his education (a popular secret question) is completely different. In fact, it is quite possible for you to communicate with someone about many aspects of their life that may constitute a secret question, and without arousing suspicion. Of course, the very essence of a secret question is that it is related to someone's life experience, so it is remembered, and this is where the problem lies - people love to talk about their life experiences! There isn't much you can do about this unless you choose security question options that lesser likely to be pulled out by social engineering.

[To be continued.]

As advertising

VDSina offers reliable servers with daily payment, each server is connected to an Internet channel of 500 Mbps and is protected from DDoS attacks for free!

Everything you ever wanted to know about secure password reset. Part 1

Source: habr.com