This is the second post in a series about the OWASP Top 10; the ten most prevalent vulnerability categories in modern web applications. Broken Authentication has taken the #2 position on the list since 2013.
What it is
Authentication is proving you’re who you say you are. Or more generally, it is one person (or computer) verifying its identity to another system. Most commonly this means usernames and passwords. But it also be accomplished via secret keys containing a long string of generated text, and/or additional factors such as a one-time password delivered via another device.
Tactics of Attackers
- Session Attacks
How does a web application tell one user from another? When you successfully log in, a cookie containing a unique identifier is stored on your browser. This is your “session ID”. If a malicious user is able to obtain or derive this information, they may be able to impersonate you!
- Abusing password reset functionality
Sometimes the developers do everything right when it comes to creating a secure logon process, but the added complexity of resetting the user’s password introduces vulnerabilities.
- Brute Force, Wordlist Attacks, Password Spraying or Credential Stuffing
Given enough time, any password can be defeated simply by trying every combination. The impracticality of doing that (with currently available computers) has made passwords the primary factor of authentication for a long time.
A wordlist is a long text file containing potentially millions of real passwords, typically found in previous data breaches. Because legitimate users likely have dozens of passwords to remember, the passwords are always not as complex as they ought to be. Trying each of the passwords on the wordlist, even if there are millions of them on the list, is a substantial shortcut in comparison to brute-forcing.
But modern systems have safeguards in place, and we’ll be talking about those best practices in the Mitigation section of this post. One of these is locking a user out after a certain number of failed login attempts. A malicious user armed with a list of the valid usernames or email addresses for a system can take a common password and try it against an entire company’s employee base, banking on the very good possibility that one of these users has chosen an insecure password. This is called Password Spraying, and because each user account is tried only once, the users don’t get locked out and the attack is less likely to be noticed.
Credential Stuffing is an automated attack that attempts entry using stolen credentials. Requiring your users to change their passwords on a set schedule shortens the window in which this breach data may be useful.
- Default Passwords
Some content management systems, open source, and vendor-provided applications come with a default administrator login (ie: Login: admin, Password: secret.) An attacker will certainly look up these default credentials to see if you’ve carelessly failed to change the password.
Not all of the following mitigations will be appropriate to your situation. Better security often comes at the expense of convenience, and your use of these mitigation strategies will depend in part upon the sensitivity of the data your application stores, as well as your relationship to your users. (For example, an employee must comply with company rules even if they’re inconvenient — but if your security policies frustrate a customer, they may just switch to one of your competitors.) So find that balance based on your threat model.
- Multi-Factor Authentication (2FA / MFA)
Where possible, avoid the use of SMS (Text Messaging) for sending 2FA login codes. (Mobile phones are vulnerable to SIM Jacking, in which an attacker uses social engineering to trick the carrier into transferring the phone number to the attacker’s phone.)
Mobile Apps such as Authy and Google Authenticator / Google Smart Lock are preferable to SMS, but SMS is better than no 2FA at all. An even more robust solution is the Yubikey, a small piece of physical hardware that plugs into your device, identifies it as a keyboard, and delivers a one-time password.
- Password Checking
In a business setting it can be a good practice to occasionally try the 10,000 most common passwords against your user base as a test. Employees whose passwords were easily guessed can be contacted to reset their password.
- Password Complexity Policies
As you’re aware, organizations are placing increasingly stringent rules on minimum password length, the presence of special characters, forbidding use of any of the last five passwords.
- User Lockout
To limit the effectiveness of automated attacks, a robust system should lock out any user who exceeds a set number of consecutive failed login attempts.
- Server-side session ID management
The OWASP Cheat Sheet on Session ID Management is a great starting point. But in short, session id’s should be randomly generated, unique, very hard to guess (or brute-force), and should not contain encoded data that can be decoded by an attacker to gain information about the user or manipulate the terms of a session (email, IP address, username, site privileges, session timeouts, etc.) The ID should be meaningless on its own, with the data relevant to that session id stored exclusively on the server.
- Web Application Firewall (WAF)
Sometimes called “reverse proxies”, a Web Application Firewall sits between the server and the open internet. It can come in the form of software, a piece of hardware, or a subscription service. The polices you set on the WAF can restrict traffic based on criteria you set. This can protect the server from several of the OWASP Top 10 attacks including Injection, Broken Auth, Sensitive Data Exposure, XXE, Broken Access Control, Security misconfigurations, XSS, and Insecure Deserialization.
- Ensuring that your cookies set the httpOnly and secure flags to true
When a user logs in successfully, the application’s server sends a success response. It is preceded by a number headers, one of which is “Set Cookie”. Here’s an example:
Set-Cookie: sessionId=b63d54j9t; Expires=Thu, 25 May 2021 03:07:00 GMT; Secure; HttpOnly (bold text mine)
If the Secure flag is set as shown above, the cookie will only be sent over HTTPS. Because HTTPS uses Transport Layer Security (TLS), the cookie will be sent from the browser to the server in an encrypted fashion so that it can’t be intercepted or viewed by a network-adjacent observer.
- Where possible, replace legacy custom apps with modern frameworks
Sometimes in a business setting you have no choice but to use a legacy system either to maintain backward compatibility or for budgetary reasons. But older apps and ones that are custom-coded are more likely to have hidden (or known) vulnerabilities (it’s a feature!), in comparison to modern open source applications which have hopefully been introspected by the developer community.
For applications designed to be extensible (such as WordPress, web browsers, frameworks, etc), be cognizant of plugins, add-ons and extensions. Since these likely have fewer users and are often produced by third-parties, extensions can introduce vulnerabilities (either accidentally or maliciously) that are not present in the core product. Use extensions sparingly. Avoid “nulled” products as well as products no longer being maintained.
- Use a modern hashing algorithm where possible
Background: Modern applications do not store user passwords in “plain text”. This would allow anyone who compromised the database to view users’ actual passwords. Instead, the user’s password is fed into a hashing algorithm. The output is stored in the database as the user’s password. Hashing is meant to be a one-way process; no one should be able to convert the hash back into the user’s password.
But there are two factors that downgrade the usefulness of a hashing algorithm over time. First, the older the algorithm, the more time has elapsed during which to discover vulnerabilities. Second, as computer processing speeds continually increase, the time it takes to calculate the hashes of the most common user passwords decrease.
The current recommendations are bcrypt and PBKDF2. Older algorithms such as SHA are no longer considered secure, and MD5 is now considered extremely insecure.
All of this is to say that if hackers do gain access to the database of hashed passwords, the damage is greatly reduced if they cannot reverse-engineer the original passwords.
- Avoid session IDs that are merely encoded, but not encrypted.
Encoding is transforming data into a transmissible format. Have you ever tried to view a file in a web browser, but the filename contains spaces? Or have you seen a search query passed as a parameter in the url? Since the URL can’t have spaces, they are converted to %20 or +. This is one basic form of encoding.
But encoding is NOT encryption. Some developers make the mistake of thinking that a jumble of characters means that a piece of data has been encrypted. But TXlTdXBlclNlY3JldFBhc3N3b3Jk can be easily decoded to “MySuperSecretPassword” using your command line or any online Base64 decoder.
Just know the difference, and know which encryption algorithms are still considered secure.
- Implement slower password hashing
When users submit their password to log in, the submission is hashed. The resulting hash is compared to the user’s hash stored in the database. If they match, the user is logged in. Whether the login is successful or not, this hashing algorithm runs.
When you use a more complex algorithm, it takes longer to complete. A legitimate user probably won’t mind an extra half-second during a login, but for a hacker running a brute-force or list-based attack, this could really slow them down. But this is a double-edged sword; the attacker can mount a Denial of Service (DoS) attack by sending a slew of login attempts at once, using up all available processing power on hashing the password attempts.
- Review your password reset process
Review OWASP’s “Forgot Password Cheat Sheet” for some solid guidelines.
- Prevent session fixation attacks by regenerating session id’s after login
Session Fixation is when an attacker is able to steal the session ID of a legitimate user to impersonate that user. Changing the user’s session ID when they log in and invalidating the old session ID can prevent this attack.
- Verify that tokens are properly invalidated server-side
It is not enough merely to delete a user’s session ID from a cookie or the browser’s Local Storage upon logout. The session must be invalidated on the server so that information cannot be later reused by a malicious user to obtain a session.
- Throttling logon attempts
Throttle the number of sign-on attempts that may come from a single IP address within a set time frame. Sure, this and other mitigations in this post can be bypassed. But what are the odds that an attacker will bypass ALL of the mitigations?
Further Reading and Viewing