As a security consultant, I see examples all the time of applications that don’t implement defense-in-depth to reduce the risk of account compromises. One area where this is especially problematic is password policy.
Password policies can contribute to a strong application security strategy, or create a false sense of security while leaving user data and applications open to attack. Weak policies remind me of a collectible card I used to have as a kid in the ‘70s, from a series of black and white thriller movies. The card that comes to mind had a picture of the Creature from the Black Lagoon with the caption, “Come on in, the water’s fine!”
My experience shows that password polices are difficult to analyze with automated application security testing, so manually verifying password policy implementation is one of the first steps on the security testing itinerary. But this blog post is not for security consultants like myself. Rather, I want to explain to architects, developers and others how a “perfect storm” of bad password policy undermines crucial layers of a defense-in-depth application security strategy.
The concept of defense-in-depth essentially means having multiple layers of defense and no single point of failure. It’s applicable to many aspects of life: in the military, in business, in your personal life and more. In application security, implementing many different defenses can reduce risk and save an organization a lot of money, both by fixing vulnerable application implementations and avoiding the public relations nightmare of account compromises.
In our daily lives, we use defense-in-depth to protect ourselves and our belongings. We may need to compensate for cosmetic designs like a pretty front door and big windows with “compensating controls” – we generally don’t choose to have solid steel doors and door frames because of undesirable appearances or prohibitive costs. So we keep the front door locked, have a dog that will yap at signs of intrusion, and set up a modern alarm system that will go off if a door or window is opened. Each compensating control also has its own cost and effectiveness to take into consideration. In most cases, the more layers of defense, the better. Often, they are inexpensive. This is also the case in application design.
During a recent consultation with a customer I encountered a web application with what I considered to be a “perfect storm” of vulnerabilities in a weak password policy scenario.
The National Institute of Standards and Technology (NIST) measures risk using the Common Vulnerability Scoring System (CVSS), which rates vulnerabilities from zero to ten, where ten is the highest risk. Risk ratings depend on factors such as the sensitivity of the application, the role of the at-risk accounts, the value of the data we wish to protect, and other factors including the extent of a breach if a vulnerability is exploited.
Usually, scores related to weak password policy scenarios are typically in the 4.0-6.0 range. This perfect storm was rated an 8.5.
In this application, weak passwords like “Password1” were allowed for all accounts types. Here are some of the other vulnerabilities I encountered that made this situation much worse.
When the user signed into the application, the browser session was maintained by a persistent cookie rather than a session cookie. That means that when the browser was closed, the cookie that allows the session to remain valid is still on the user’s computer. When the browser re-opens and the application is addressed, the user is already authenticated.
The persistent cookie was valid for seven days for administrators. The regular user’s persistent session cookies were valid for 30 days. The use of this long-lived persistent cookie was not a choice for the user. There was no checkbox that let a user make this cookie last for a long time: it was automatic. Therefore, it was never safe to use this on a computer that another person would have access to and this increases the risk of compromise if the computer itself is either physically or remotely accessed by an attacker.
Use of a persistent cookie to implement a “keep me logged in” feature, particularly for an administrative role, is common, but rarely advisable.
The administrator could set the password for any account without re-authenticating or using any secondary form of authentication (two-factor authentication). Simple re-authentication could involve re-entering the account password. This can help if the attacker had only stolen the authentication cookie or accessed a computer that was still logged in, but it’s not a good defense if the attacker has guessed the password. Re-authenticating, or having a second form of authentication, is an added layer of defense.
This is a good place to point out that it’s important to understand the limitations of our compensating controls. Re-entering a simple password is helpful, but not a cure-all. Two-factor authentication, rather than just re-authentication could involve either an RSA token value being entered, or a text message code sent to an email address or phone. Two-factor authentication is a good defense against both compromised sessions and compromised passwords.
Moving on, I had general design concerns about the application’s handling of administrators. One concern was allowing an administrator to change the password of another administrator. In addition to setting the password for other administrators, the admin user could also delete regular users and administrator accounts. This is a challenging design topic that involves usability tradeoffs against application security. I won’t address the issue of administrators impacting each other here, because that design scenario is a complicated analysis all by itself. But, in general, allowing an administrator to change the password, force password resets, or lock accounts without some form of re-authentication, is a bad idea.
One additional topic I would like to see addressed more is the use of an email address as the identifier for administrator accounts. Using an email address is a giveaway to attackers probing for administrator accounts. The simple obfuscation of not using an email address as an administrative login name is a deterrent to an attacker who would otherwise try easily accessible email addresses to authenticate into a privileged account.
Lastly, the administrator role could log into the application from the internet, rather than having to be behind a firewall. There was no IP-whitelisting in place or virtual private network (VPN) requirements to access administrator functionality. The administrative interfaces were within the same application, rather than being packed up in a separate application deployment. When in this shared application environment, logging in as a privileged user did not involve two-factor authentication, such as a text message or emailed code.
On top of all this, both admin and regular users had no account lockout mechanism of any kind. You can add an additional layer of defense by locking out accounts after a number of failed attempts to log in, using various options: Captchas, time delays, and silent lockouts are examples. It’s important to get this right, because improper implementation can assist an attacker in account enumeration, denial of service, and more. But none of these account lockout options was used in the perfect storm I was testing.
To summarize, the vulnerabilities I observed included: weak passwords, absent two-factor authentication, use of a persistent cookie for session management, absent account lockout/delays, use of an email address as an identifier for sensitive accounts, and excessively long session timeouts. Whether or not your work involves security, point out weak layers of defense in applications. When you point out weak password policies, you become an additional layer of a defense-in-depth strategy.
Movie poster via Wikimedia Commons.