The root issue on this matter is how can you help users better distinguish a legitimate email versus an illegitimate email. There is also a secondary issue of how to get the user to perform an action securely when they are told not to trust the link in an email.
For the first problem, here are some technical controls which could be implemented:
- Use encrypted/signed emails. Let's pretend that in the future we can easily setup users to obtain and use private/public keys. Then you can tell users to only trust actions if the email has been signed and they have verified the message using the trusted public/private key pair. There is a threat, of course, of the private-keys being stolen, so for a public-facing company such keys may need to have relatively short expirations and a good mechanism for revocation.
- Put codes in the email which would be hard to phish. Many banking websites have implemented security pictures/security keys. The known flaw with those methods is if you take enough time you can get those security keys and still fake our the user, because these images are shown before the password is provided in the email. So, we modify the concept a little bit and we allow users to specify a phrase and image combination that is instead included in all of their emails, and is never shown before logon. In this way, you have a relatively reasonable assurance that the email came from the intended source because if they could have gotten that image it means they likely already hacked the server or hacked into your email, and they can just reset your password through email while you are sleeping.
- A little less involved than the above, I receive some bank/credit card emails which include a truncated portion of an account number. This would be difficult to fake without already compromising the user or the computer, but most people probably don't recall their account numbers. If it was part of a credit card PAN, that would probably be much more likely for an attacker to find by hacking other websites.
- Have an active program to identify phishers through working with email providers, law enforcement, and end users. The more they report back to you phishing attempts, you can at least try to identify servers, email addresses, misspellings, patterns, etc. Hard to be ahead, but catch up.
- On the customer side or email provider side, they should implement controls like spam filters, heuristic phishing warnings, some type of whitelist for known email accounts that have the ability to send the reset link or other crucial information.
On the non-technical side, its mostly all about training and awareness, but also about making it easy for the end user to verify suspicion. To do this, you can provide links on your webpage showing how to spam phishing and how to check the authenticity, hopefully a few users will learn. Send out awareness in newsletters, other information in emails and in mailings. If you have an internal helpdesk or a customer support center, make it easy and convenient for users to contact the helpdesk to ask about these issues. They should have someone they can ask about legitimacy of any such mailings.
More specifically, about email resets. Let's not provide them with a link. If you operate
site.tld, then you can have them enter a form at
site.tld/reset. Ask for the email and the one-time token on the web page and make them visit it manually and type in the code manually.
If your testing or knowledge of the users indicate they are incapable of cutting and pasting, then you need to do a risk assessment to determine the cost of securing versus ease/profit of not securing. How many customers will you lose from making the process less point and click, but more secure. What is the cost and damage to both you the company and to the customer if the account is taken over? Can you detect and reverse any malicious actions, transfers, deletions, posts, etc?
If we are talking about a pure internal environment, skip the reset emails altogether. Have a self service portal users must use, or better yet require reset in face or by phone, and if by phone, require some information to validate the identity. In a corporate environment, you can do this by asking for their employee number and their start month/date, or some other combination of information.
Email reset links should only be used for low priority and low risk. If you are doing something with personal details, finance, health info, etc. consider your pricing model and look at the cost of not using email. Eliminate the threat of the evil link, and let your users know: "We will never send you a password reset link by mail, we will provide you a temporary code via phone or SMS that will be good for 10 minutes, which you can use to reset the link by manually visiting the following link...If you receive any type of email about a password reset, please forward it to firstname.lastname@example.org"
Lastly, the emphasis here has been on preventative controls, which are appropriate, but you can also implement detective controls to complement and in crease security. E.g., send the users an email anytime their password is changed or send them a SMS, etc. Maybe you can have heuristics looking at patterns, sources, and new password hashes coming in for password changes. If you see 10 different user's passwords being changed in 5 minutes, from the same ip, and the password hash comes out the same (would need to think about how to temporarily store the hash securely without salt), then you can stop investigate and freeze the affected users' accounts.