Software Integrity


Password strategy: What makes your users’ passwords exploitable

Passwords are the gatekeepers to our most sensitive information. They serve as the first line of defense against a potential intruder, but they are not bullet-proof. As users, we’re tempted to create passwords that are easy to remember, using birth dates or anniversaries and even writing them down. As developers, we’re tempted to put as little time into our password strategy as we can.

Unfortunately, these passwords are very weak and guessable and leave us wide open for an attack. Worst of all, the systems that we trust to store this critical information face plenty of security challenges too. Hackers have identified password databases as ripe and easy targets for theft, and concerted attackers can almost always defeat the schemes by which those database are protected.

Let’s look at some common errors that companies make with their password strategy.

Your password strategy hasn’t changed in 10 years


Once an attacker steals a cache of stored passwords, they begin reverse-engineering its protection scheme. Password storage mechanisms are simply a barrier to an attacker — one that slows them down, but does not stop them.


When you store passwords, you can and should implement further protections to serve as barriers. Think of them as speed bumps, but set the speed bump too high, and you run the risk of annoying your user — and overtaxing your server.

OWASP offers a solution to loading and using new protection schemes:

  1. Load a new, stronger credential protection scheme
  2. Include version information stored with form
  3. Set ‘tainted’/‘compromised’ bit until user resets credentials
  4. Rotate any keys and/or adjust protection function parameters such as work factor or salt
  5. Increment scheme version number

Remember: No matter how high you build your barrier, an attacker will ultimately be able to overcome it. The ongoing challenge here is to design your password storage to slow down attackers while also balancing the needs and satisfaction of your users.

You’ve limited the number or variety of characters users can use


Brute-force attacks occur when an attacker attempts to discover a password by systematically trying every possible combination of letters, numbers, and symbols until they uncover the correct combination that works. When users choose guessable passwords (‘password1’ anyone?), it makes a hacker’s job easy.

To further simplify the process, hackers use tools that utilize wordlists and smart rulesets to intelligently and automatically guess user passwords. Some organizations restrict the type of special characters and the length of credentials accepted by systems because of their inability to prevent SQL Injection, cross-site scripting, command-injection and other forms of injection attacks. These restrictions, while well-intentioned, facilitate brute-force attacks.


Do not allow short or no-length passwords and do not apply character set or encoding restrictions on the entry or storage of credentials. Continue applying encoding, escaping, masking, outright omission, and other best practices to eliminate injection risks.

You’re storing passwords in clear text


Storing passwords in a database in cleartext opens you up a variety of risk factors that can compromise an application. There are several ways an attacker might be able to gain access to the database through SQL injection, exploits, or stealing the backup disk. If the attacker succeeds, they can access all user accounts and read all of the user passwords that are in cleartext.


Cryptographic hashes like those in the SHA family slow down those attacks. But they are not indefensible. Attackers equipped with fast hardware can still easily “crack” these passwords.

A rainbow table is basically a pre-computed set of plaintext strings and their corresponding hashes. They are “optimized lookup tables” that are publicly available can be used to reverse-engineer one-way hash functions. Attackers can use one of these tables to retrieve cleartext data that has been hashed.

This image shows how rainbow tables have to be crafted with inherent limitations of size and valid-character space. Most of the tables are 99% accurate, which means that not all passwords can be cracked with the table.

You’re using hashes that produce collisions


Hashes enhance the security of password storage, but they are not a fail-safe. Hash algorithms can suffer from several different kinds of cryptographic attacks, such as collisions. Good hash algorithms are designed to be collision-resistant, but they are impossible to eliminate completely. MD5 and SHA-1 have been proven to contain known collisions, meaning they produce the same hash value from different passwords.

Example: Shows how three different hashing algorithms take the same credential — “password1” — and produce different hashes or enciphered text.

Password Strategy - Simple Hashes

MD5. Message Digest 5; the fifth revision of a message digest algorithm devised by R.L. Rivest of RSA Laboratories. MD5 produces 128-bit hashes.

SHA1. Secure Hash Algorithm 1; the first revision of a hash algorithm developed by the National Security Agency. It produces 160-bit hashes.

SHA-256. Variation of SHA1 that produces longer hashes. It produces 256-bit hashes.


Use SHA-256 to produce longer hashes that avoid known collisions.

You’re not salting your passwords


In any password system, it is possible that two users may use the same password. An attacker who identifies the duplicate passwords can use the known password to authenticate as any user whose hash matches, or can use that information to crack the system using dictionary chosen-plaintext attacks.


Salts prevent collisions by adding random data to each plaintext password. Use salting to make two previously identical plaintext passwords differentiated in their enciphered text form, so that duplicates cannot be detected. Random salts also add entropy to input space, and make lookup tables larger.

To properly implement credential-specific salts, follow these steps:

  • Generate a unique salt upon creation of each stored credential (not just per user or system wide).
  • Use cryptographically-strong random data, such as those generated by Java SecureRandom(). The longer the salt, the harder it becomes for an attacker to create a lookup table to account for every salt.
  • As storage permits, use a 64 byte salt (actual size dependent on protection function).
  • Scheme security does not depend on hiding, splitting, or otherwise obscuring the salt.

Conclusion: Design for failure

While there is no fail-safe way to store passwords, it is important to design your password storage with thought that it will eventually be compromised. Add these alternative credential validation workflows to your password strategy for an added layer of security:

Protect the user’s account

  1. Invalidate authentication ‘shortcuts’ by disallowing login without second factors, secret questions or some other form of strong authentication.
  2. Disallow changes to user accounts such as editing secret questions and changing account multi-factor configuration settings.
  3. Support dual authentication with apps such as Duo.

Load and use new protection scheme

  1. Load a new, stronger credential protection scheme.
  2. Include version information stored with form.
  3. Set ‘tainted’/‘compromised’ bit until user resets credentials.
  4. Rotate any keys and/or adjust protection function parameters such as work factor or salt.
  5. Increment scheme version number.

When user logs in:

  1. Validate credentials based on stored version (old or new); if older compromised version is still active for user, demand 2nd factor or secret answers until the new method is implemented or activated for that user.
  2. Prompt user for credential change, apologize, & conduct out-of-band confirmation.
  3. Convert stored credentials to new scheme as user successfully log in.