It has become very common for almost all websites to have a login functionality for their users. A user sign up with an email or username and a password without thinking twice, as it has become easier to visit the website back again with the help of browser's or plugin's caching and third-party authentication services.
Unfortunately, the security threats are also on the rise and it has become easier for hackers to sell the credentials on the dark web or publish breached data on paste sites, hijack social media accounts for click baiting or fund transactions.
We will look into how the authentication works, how attackers compromise an account and how to defend against such attacks.
Authentication, how does it work ?
Authentication framework is provided by HTTP, which is used by a server to challenge a client request with a 401
status code (meaning Unauthorised) and provides information on how to authorise with a WWW-Authenticate
response header. The client that wants to authenticate itself with the server has to include Authorization
request header with credentials.
The most common type of Authentication is a Basic
, included in the Authorization
header as below:
//syntax
Authorization: <type> <credentials>
//example
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
Other authentication types can be found at the IANA registry of Authentication schemes.
In a basic
authentication, the client obtains username and password from user, constructs the user-pass by concatenating the username, a single colon (":") character, and the password (generating the string username:password
). It then encodes the user-pass into octet sequence, and finally encodes the octet sequence using Base64 into a sequence of US-ASCII characters.
If the user agent wishes to send the username "Aladdin" and password "open sesame", it would use the following header field:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
As the username and password are passed over the network as clear text (it is base64 encoded, but base64 is a reversible encoding), the basic authentication scheme is not secure. HTTPS/TLS should be used with basic authentication.
For more information refer RFC 7617.
Types of Attacks
The following are the common types of automated attacks that attackers use:
Brute-Force Attack
Hackers attempt to get past the authentication against a single account by guessing passwords. These attempts have higher chance of success by using scripts which try numerous commonly used passwords from a dictionary and from millions of leaked passwords obtained from previous data breaches.
Credential stuffing
This type of attack is made by testing username and password pairs obtained from the breach of another website. Check whether your email, phone or password is in a data breach in the website haveibeenpwned.com.
Password Spraying
In this type of attack a single weak password is tested against a large number of different accounts.
Defence mechanisms
Lets look at the various ways of protecting against such attacks
#1 Third-party authentication that require no password
It is now common to use social media account like Facebook or Google account to authenticate a user in a website. This is more convenient as the user does not have to use or remember a password. It is not considered safe to allow third-party apps to store username/password combo. For this and other use cases authentication protocols can be used to protect the user's data. Examples include OAuth, OpenId, SAML and FIDO.
OAuth or OpenID requires users to usually use their personal email addresses as usernames. For business users, consider using Single sign-on (SSO)
identity providers like Okta, OneLogin, wherein they use their business email to login.
#2 Securing own Authentication system
Not all users have Facebook or Gmail or other social media accounts to login. That means websites still needs the usual way of sign-up, login & logout using personal email or username of choice and password apart from third-party authentication. There are many considerations to be taken before implementing your own authentication system:
Username or User IDs
- It should be case-insensitive, i.e, a username "Bob" and "bob" should be the same user.
- It should be unique.
- Use a separate display name, when a user has a public profile & avoid use of email address as display name as it invites spam.
- Validate and verify email addresses, by checking for valid characters and by sending a verification link with token, only then send further transactional emails.
- Ban disposable emails generated by services like 10 Minute Mail or Mailinator.
- Do not allow login with sensitive accounts (eg. internal accounts used for DB) to any frontend user interface.
- Do NOT use the same authentication solution (e.g. IDP / AD) used internally for unsecured access (e.g. public access / DMZ)
Passwords
- Minimum length of the password is enforced by the application and less than 8 characters is considered to be weak,
- Maximum password length should not be set too low, as it will prevent users from creating passphrase. Some set it to 64 characters due to limitations in hashing algorithms, check out more in OWASP Password Storage Cheat Sheet
- Maximum password length should be set in order to prevent long password denial of service attack.
- Do not truncate password if the password set by user exceeds the limit, use pre-hashing algorithm like the PBKDF2.
- Allow usage of all characters including unicode and whitespace.
- Allow credential rotation (change/resetting password) when password is compromised. Password-reset links should expire after user uses them or after 30 minutes to prevent an attacker from abusing stale reset links. To know about password resetting mechanisms, read OWASP Forgot Password Cheat Sheet.
- Use a library for calculating the strength of the password, be careful while choosing, check for less dependencies and maintainability status.
- Use Pwned Passwords API to check the password entered is in the list of previously breached passwords.
- For revalidating the users when they login again, the passwords should be stored in the database securely using a cryptographic technique, detailed well in OWASP Password Storage Cheat Sheet.
The passwords are not stored as is but as hashes, for this a good hashing algorithm should be chosen, so that even if the attacker gets the hashed password it would take forever to crack (it is not possible to decrypt hashes back to original password).
These are the steps which the attacker uses to crack the password from hashes.
- Select a password you think the victim has chosen
- Calculate the hash
- Compare the hash you calculated to the hash of the victim. If they match, you have correctly "cracked" the hash and now know the plaintext value of their password.
Read password security requirements to know more on Password security considerations.
#3 Using Multi-factor Authentication (MFA), or Two-Factor Authentication (2FA)
It is best to have an additional layer of security with Multi-factor Authentication over secure password storage, to be effective against attacks like Brute-force, credential stuffing and password spraying. Microsoft suggests that it would have prevented 99.9% password compromises with MFA. It requires a returning user to provide evidence about their identity with at least two of the following four categories of information: something they know, something they have, something they are and their location.
Many use authentication mobile apps like Google authenticator and Microsoft authenticator that can be synced with a website during sign-up, and later can be used to generate random pins for logging in successfully.
To get guidance on implementing MFA, read OWASP Multi-Factor Authentication Cheat Sheet.
#4 Implementing CAPTCHA
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart), asks users to perform various image recognition tasks that are trivial for humans but tricky for computers. It can help to prevent automated login attempts and user enumerated attacks (testing each username from a list to see whether it exists on your website).
CAPTCHAs are not perfect and can be defeated by attackers using machine learning techniques, or by paying human users to complete a task, but it still prevents most common hacking attempts.
Make sure that CAPTCHAs are user friendly for regular users by only requiring a CAPTCHA to be solved after a small number of failed login attempts, rather than requiring it from the very first login and make it less complex 🙂.
#5 Secure Logout
It is equally important to have a secure logout functionality for your users, to prevent from session hijacking attacks.
Logout function should clear the session cookie in the browser, and invalidate the session identifier if you are storing it on the server side. This protects against attackers who attempt to intercept session cookies and attempt to reestablish a session using a stolen cookie. The session cookie is cleared by sending back an HTTP response containing a Set-Cookie
header with a blank value and set the Expires
(or Max-Age) attribute to a date from the past (in case a persistent cookie is being used): Set-Cookie: id=; Expires=Friday, 17-May-03 18:45:00 GMT
.
Other defences
The other ways of protecting against attacks include using Password Managers and re-authentication.
As attackers find ways to security loopholes, one has to find better ways of protecting against it, and by enabling logging and monitoring of authentication one can detect attacks/failures on a real-time basis.
Top comments (4)
Two things that are missing: first, to protect against brute-force attack it is good to institute a negligible at first delay in the authentication process, increasing the delay after several failed attempts (perhaps only for give IP).
Second, if a password complexity rule prevents the user from using a password manager, it is not a good rule.
It might be worth mentioning that most password strength libraries tend to follow the same rules that actually produce less secure passwords because of human nature. Typically these libraries request a mix of mixed case letters, some numbers, and the "special characters" (which is a misnomer, as often it's limited to basic punctuation). With these kinds of limits, we're enforcing situations where a user actually has more difficulty creating a memorable password, and then needs to rely on other systems to help. At best this would be a password manager, but at worst this is a passwords.txt file on the desktop.
Randall Munroe, (NASA scientist, mathematician, artist) has a great comic to help users select good passwords, as he recognises the problem with current password strength algorithms, and what they're effectively training users to do.
People are great at remembering things that evoke an image or emotion in their mind, but terrible at a string of nonsensical characters. So if forced by poor rules, they choose passwords that fit the rule, but create poor passwords, like "Password123!" (I'd bet money on this being somewhere in a leaked password list online)
Agree, how to create a memorable password is upto your imagination, like the first letter of every word of a song or a sentence for example. It is also important to use an api like I mentioned above to check if the user created is in the list of breached data or a commonly used one.
Yeah, I use the old horse-battery-staple technique for my passwords. It does mean they're very long, but much harder to crack than a "Pa$$w0rd" which is what a lot of APIs determine is a "strong" password.