Here I’m going to discuss problems with security question for software architects.
What is the way for hackers to access data of user’s account. It’s easy nowadays to let users use only cryptosecure passwords. You can use this password meter if you want to tell them that their password is insecure and use the same code on server side to not to let user to set it. So let us assume that user’s password is already secure. But you probably want user to have a chance to reset her/his password if she/he has forgotten it. And here comes most of the issues. In my experience your security question either assume insecure answer or hard to use for users since they could have more than one correct answer for the security question. In any case this answer is far less cryptosecure then regular password, which makes it a security hole if used directly for show/change password. In my understanding show password is never should be used, for the following reasons:
- It makes you as a developer store it (even encrypted) in your storage (usually database). This approach is VERY bad since if some hacker will get access to the database she/he will get all password for all users. It is similar issue as storing credit card in your database and could be even worse, since users tend to use the same password everywhere. Best practice here is to store only hash of the password and check hash on login;
- It provides password for user as a text, so user could save it somewhere, or someone could see it on user’s monitor.
There are recommendations for users how to use security question in more secure way, but I doubt many follows it. Change the password will not show hacker old password but still it is easy way to get to the system.
One more huge issue is that answer for security question is stored in database as text or slightly encripted text (instead of hash). This opens up the same issue as discussed earlier.
Ideally, if you can afford yourself not to use security question at all it could be a solution (although, I don’t think it is possible nowadays) . Since even the following solution will be limited by security of user’s email account.
The only you could do here is the following:
- Use more than one security question and use them either randomly and/or more than one at the same time;
- Or after security question(s) send the link to change password to user’s email (but not to show this email to user). In this case you will depend on security of user’s email. But if you don’t send link by email and just let user to change password this means that you providing access to user’s account secured only by secure questions which are far less cryptosecure. Alternatevely you can just show user’s hint for password, not the password itself.
- This change password link should expire and contain some random token to check you don’t allow anyone else to use the same link to change password, and this token should expire immediately after password is changed and surely should be specific to the user (but should not be generated using any user’s information). The link itself must also not contain any information about the user;
- Attempts to access user’s account with incorrect password or incorrect security question answer should be limited (say to 5 a day or some other way);
- Each attempt to access security question and change password must be used along with captcha;
- All communications with security question and changing password must be done over SSL (HTTPS);
- Always notify user about failed attempts to access her/his account and about password change on the account. Attempt must be considered as failed here even if only captcha test fails;
- Treat answers to security questions as alternative passwords and work with them the same way, i.e. use password input to enter an answer first time and to input it from the user on password reset process. Store only HASH of the answer not the answer itself. This is, possibly, not very convenient for the user, but will help to keep her/his secret is you database is compromised, so I would call it understandable inconvenience.
Pay attention to 5 which is usually forgotten. Captcha here, I would say playing not only it’s primary role, but also makes path to change password this way uncomfortable for user, which make her/him to use password security versus security question access. It is, I would say, administrative way of making users not to use this way. I would also do a multi-step change password procedure.
Note on password change process
The procedure of password change should be the following:
- After user answered security questions correctly and passed captcha test, some token should be generated using (ideally completely) random information and stored in database in users table or some other 1:1 table pointing to user along with date and time when it was generated, mark user’s account as being updated (you can treat not null token as this flag). Link to change account should be generated like this: https://yoursite.com/secure/passupdt?t=<NEWLY_GENERATED_TOKEN> For example it could be https://yoursite.com/secure/passupdt?t=dh678sHGs8Kjhksdflkj69387Ljhdfkjh&899872320870HKJjhsfjhlsdf This link should be sent to user’s email along with instruction how to copy/paste it in browser’s address line;
- When user follows the link your code should read token, find user’s account based on this token. Make sure token is not expired (you can, for example, check that it was generated not earlier than 24 hours ago). Here you can show a link to password change form of the form itself (don’t forget about captcha on the form);
- After user passed captcha test and provided new password you must check token, flag and expiration time again and only then update the user’s password hash in your system, and remove the token and flag that account is being updated and send user an email notification that password was updated (this notification must not contain neither old nor new password itself and even should not contain information about the user).
There is a possibility that user will try to access her/his account regular way (with regular password) after step 1 or step 2. There two possibilities: if this attempt was successful or not.
- If it was successful (means that user remind her/his password and successfully login) you must immediately clear token and token flag in login action and notify user that there was an attempt to change account’s password;
- If it was not successful I don’t see anything you can do for change password process (except regular login limitations and captcha starting form second failed attempt). Just notify user about one more failed attempt.
There is one more thing here. If user selects to change password link but he always had successful login before – this means that this activity should be considered as suspicious and user should be asked for her/his password before proceeding. If password was correct then user should be logged in and redirected to regular first-after-login page, if password was incorrect then user should be notified (by email/SMS) and only then proceed to security questions. It is clear that hackers more likely will attempt to attack security questions and not password. One other way for you to avoid it could be not to provide access to forget_password link before user try to access account regular way and fail.
Again as an alternative instead of a link with token to change a password you can send temporary password to the user, who will have to change it on first login.