Difference between revisions of "Password Storage Cheat Sheet"

From OWASP
Jump to: navigation, search
m
Line 1: Line 1:
 
= Introduction =
 
= Introduction =
  
This article is focused on providing guidance to storing a password in order to help prevent password theft. Too often passwords are stored as clear text. Thus the password can be read directly by the database's administrator, super users or via data theft by SQL Injection. Database backup media is also vulnerable to password theft via password storage. It is recommended that you avoid storing the clear text password or an encrypted version of the password.
+
This article provides guidance on how to properly store passwords in order to help prevent password theft. Passwords are usually stored for one of two reasons:
 +
 
 +
# to authenticate someone to this system, or
 +
# to authenticate this system or user to a target system.
 +
 
 +
This article provides recommendations on how to safely store passwords in situation 1. In situation 2, the passwords should be encrypted wherever they are stored, but this cheat sheet does not address that particular situation.
 +
 
 +
Passwords are frequently stored as clear text. Sometimes they are encrypted when they should instead be hashed. In either case, such passwords can be read directly by the database's administrator, super users or via data theft by SQL Injection. If encrypted, these same techniques may also allow the attacker to gain access to the decryption key as well. Database backup media is also vulnerable to password theft if these passwords are included on the backup. It is recommended that you avoid storing the clear text password or an encrypted version of the password. Instead they should be strongly hashed as described below.
  
 
= Password Storage Rules =
 
= Password Storage Rules =
  
Passwords are secrets. There is no reason to decrypt them under any circumstances. It is crucial that passwords are stored in a way that they can be verified but not reversed in any way, even by insiders.   
+
Passwords are secrets that only the account owner should know. For the system that uses these passwords to authenticate its users, there is no reason to decrypt them under any circumstances. It is crucial that passwords are stored in a way that allows them to be verified but not reversed in any way, even by insiders.   
 +
 
 +
== Rule 1: Use a Modern Hash Algorithm ==
 +
 
 +
Hash algorithms have the ability to transform data from one format (plaintext) to another (hash value) in a manner such that this process is not algorithmically reversible. This means that you can hash something, but there is no unhash. The only way to unhash something is randomly guess values, hash it, and hope it matches. This is perfect for password storage since we wish to verify but not uncover the original value of the password. Currently, we recommend using a relatively strong hash algorithm like SHA-256 or stronger. If you are currently using a weak hash algorithm, like MD5 or SHA-1, we recommend updating your algorithm to something far stronger. If you haven't implemented anything yet, we'd recommend you use the strongest algorithm currently available to you, such as SHA-512.
 +
 
 +
== Rule 2: Use a Long Cryptographically Random Salt ==
  
=== Use a Modern Hash Algorithm ===
+
If each password is simply hashed, identical passwords will have the same hash. There are two drawbacks to hashing only the password:
  
Hashing or Digest algorithms are using the verify the integrity of data. These class of algorithms do not provide the ability to reverse the hash value to the original form. This is perfect for password storage since we wish to verify but not uncover the hashed value of password.
+
# Due to the birthday paradox (http://en.wikipedia.org/wiki/Birthday_paradox), the attacker can find a password very quickly, especially if the number of passwords in the database is large.
 +
# An attacker can use a list of precomputed hashed values (http://en.wikipedia.org/wiki/Rainbow_table) to break passwords in seconds.  
  
=== Use a Long Cryptographically Random Salt ===
+
In order to avoid this weakness, a per user account salt must be introduced into the hashing process.  Such a salt is appended to either the beginning or the end of the user supplied password before the combined value is hashed. The salt needs to be unique per user account. Ideally, the salt would be a large cryptographically random number of a fixed length. Since we've seen rainbow tables in the wild for all passwords of up to 24 characters in size, a salt of at least 24 bytes is the recommended minimum length. Salts also have the advantage that they can include unprintable characters which most precomputed rainbow tables wouldn't include.
  
If each password is simply hashed, identical passwords will have the same hash. There are two drawbacks to choosing to only storing the password’s hash:
+
=== Recommendations: Make it hard to steal the entire salt ===
  
# Due to the birthday paradox (http://en.wikipedia.org/wiki/Birthday_paradox), the attacker can find a password very quickly especially if the number of passwords the database is large.
+
There are a number of addition enhancements to the basic salting mechanism we also recommend you consider:
# An attacker can use a list of precomputed hashed (http://en.wikipedia.org/wiki/Rainbow_table) to break passwords in seconds.  
+
* Have an additional 'system' salt that is a fixed value for the entire system. This should be stored in a configuration file somewhere. This fixed value would not have to be included every backup, making it even harder for an attacker to compromise all elements required to calculate the hash value properly.
 +
* Embedding a portion of the system salt in the source code. This wouldn't be that helpful for open source code, but for custom applications, having part of your system salt in the code would be yet one more item required by an attacker to calculate the hash value properly.
 +
* Generating a new salt for an account each time that user's password is changed.
  
In order to solve these problems, a salt must be concatenated in front of the password before the digest operation. A salt is a cryptographically random number of a fixed length. This salt must be different for each stored entry. Since rainbow tables are already passing 24 characters, a salt of 24 bytes or longer is the recommended minimum length.
+
If you are retrofitting an existing system, and don't have the ability to create and store a cryptographically random salt per account, then at least introduce something that is unique, and fixed, per account to the password hashing process, such as the account name and/or account ID. The more random the value the better so you can combine multiple short items together to generate a longer per account salt. For example, if the date of last password change is stored in the account, you could include that date/time as part of the user account salt since that value is fixed until the user changes his/her password again.
  
=== Iterate the hash ===
+
=== Recommendation: Salt Isolation ===
  
To slow down the computation it is recommended to iterate the hash operation many times. While hashing the password many times does slow down hashing for both attackers and typical users, typical users don't really notice it being that hashing is such a small percentage of their total time interacting with the system. On the other hand, an attacker trying to crack passwords spends nearly 100% of their time hashing so hashing many times gives the appearance of slowing the attacker down by a factor of n while not noticeably affecting the typical user. A minimum of 1000 operations is recommended in RSA PKCS5 standard in 2000, a value that should be doubled every 2 years.
+
An additional password storage defense mechanism involves storing the salt in a different location than the password hash. Use of the server's filesystem is one commonly used mechanism for salt isolation, assuming the password hashes are stored in a database somewhere. This defense mechanism reduces the risk of password theft when the database file is stolen, since the salts will not be included with the database data. Be careful to ensure that both the password hashes and the salts are backed up together because one is not useful without the other.
  
=== Salt Isolation ===
+
=== Recommendation: Iterate the hash ===
  
One additional password storage defense mechanism involves storing the salt in a different location as the password hash. Use of the servers filesystem is one commonly used mechanism for salt isolation. This defense mechanism reduces the risk of password theft when a database backup file is stolen, since the salts will not be includes with the database data, which includes the password hash.
+
If a password database is ever compromised, one of the primary things defending the hashed passwords from being broken is the computational time required to guess password values. As such, we recommend slowing down the hash computation by iterating the hash operation many times. While hashing the password many times does slow down hashing for both attackers and typical users, typical users don't really notice it being that hashing is such a small percentage of their total time interacting with the system. On the other hand, an attacker trying to crack passwords spends nearly 100% of their time hashing, so hashing many times can slow down an attacker by a factor of N (# of iterations) while not noticeably affecting the typical user. A minimum of 1000 operations was recommended in the RSA PKCS5 standard in 2000, a value that should be doubled every 2 years. Therefore, in 2012, it is recommended that 64,000 iterations be considered. You should measure the time required and make sure that its as large as possible without providing a significantly noticeable delay when your users authenticate.
  
== References ==
+
= References =
  
 
# Cryptographic framework for password hashing is described in [http://www.rsa.com/rsalabs/node.asp?id=2127 PKCS #5 v2.1: Password-Based Cryptography Standard].
 
# Cryptographic framework for password hashing is described in [http://www.rsa.com/rsalabs/node.asp?id=2127 PKCS #5 v2.1: Password-Based Cryptography Standard].
 
# Specific secure password hashing algorithms exist such as [http://www.usenix.org/events/usenix99/provos/provos_html/node1.html bcrypt], [http://www.tarsnap.com/scrypt/scrypt.pdf scrypt].  
 
# Specific secure password hashing algorithms exist such as [http://www.usenix.org/events/usenix99/provos/provos_html/node1.html bcrypt], [http://www.tarsnap.com/scrypt/scrypt.pdf scrypt].  
# Implementations of secure password hashing exist for PHP ([http://www.openwall.com/phpass/ phpass]), ASP.NET ([http://msdn.microsoft.com/en-us/library/ms998372.aspx#pagpractices0001_sensitivedata ASP.NET 2.0 Security Practices]), Java ([http://www.owasp.org/index.php/Hashing_Java OWASP Hashing Java]).
+
# Implementations of secure password hashing exist for PHP ([http://www.openwall.com/phpass/ phpass]), ASP.NET ([http://msdn.microsoft.com/en-us/library/ms998372.aspx#pagpractices0001_sensitivedata ASP.NET 2.0 Security Practices]), Java ([[Hashing Java|Hashing in Java]]).
# Much of this article came from the original password storage article here: [Hashing Java]].
+
# Much of this article came from the original OWASP [[Hashing Java|Hashing in Java]] article.
  
 
{{Cheatsheet_Navigation}}
 
{{Cheatsheet_Navigation}}
  
 
[[Category:Cheatsheets]]
 
[[Category:Cheatsheets]]

Revision as of 18:09, 25 November 2011

Contents

Introduction

This article provides guidance on how to properly store passwords in order to help prevent password theft. Passwords are usually stored for one of two reasons:

  1. to authenticate someone to this system, or
  2. to authenticate this system or user to a target system.

This article provides recommendations on how to safely store passwords in situation 1. In situation 2, the passwords should be encrypted wherever they are stored, but this cheat sheet does not address that particular situation.

Passwords are frequently stored as clear text. Sometimes they are encrypted when they should instead be hashed. In either case, such passwords can be read directly by the database's administrator, super users or via data theft by SQL Injection. If encrypted, these same techniques may also allow the attacker to gain access to the decryption key as well. Database backup media is also vulnerable to password theft if these passwords are included on the backup. It is recommended that you avoid storing the clear text password or an encrypted version of the password. Instead they should be strongly hashed as described below.

Password Storage Rules

Passwords are secrets that only the account owner should know. For the system that uses these passwords to authenticate its users, there is no reason to decrypt them under any circumstances. It is crucial that passwords are stored in a way that allows them to be verified but not reversed in any way, even by insiders.

Rule 1: Use a Modern Hash Algorithm

Hash algorithms have the ability to transform data from one format (plaintext) to another (hash value) in a manner such that this process is not algorithmically reversible. This means that you can hash something, but there is no unhash. The only way to unhash something is randomly guess values, hash it, and hope it matches. This is perfect for password storage since we wish to verify but not uncover the original value of the password. Currently, we recommend using a relatively strong hash algorithm like SHA-256 or stronger. If you are currently using a weak hash algorithm, like MD5 or SHA-1, we recommend updating your algorithm to something far stronger. If you haven't implemented anything yet, we'd recommend you use the strongest algorithm currently available to you, such as SHA-512.

Rule 2: Use a Long Cryptographically Random Salt

If each password is simply hashed, identical passwords will have the same hash. There are two drawbacks to hashing only the password:

  1. Due to the birthday paradox (http://en.wikipedia.org/wiki/Birthday_paradox), the attacker can find a password very quickly, especially if the number of passwords in the database is large.
  2. An attacker can use a list of precomputed hashed values (http://en.wikipedia.org/wiki/Rainbow_table) to break passwords in seconds.

In order to avoid this weakness, a per user account salt must be introduced into the hashing process. Such a salt is appended to either the beginning or the end of the user supplied password before the combined value is hashed. The salt needs to be unique per user account. Ideally, the salt would be a large cryptographically random number of a fixed length. Since we've seen rainbow tables in the wild for all passwords of up to 24 characters in size, a salt of at least 24 bytes is the recommended minimum length. Salts also have the advantage that they can include unprintable characters which most precomputed rainbow tables wouldn't include.

Recommendations: Make it hard to steal the entire salt

There are a number of addition enhancements to the basic salting mechanism we also recommend you consider:

  • Have an additional 'system' salt that is a fixed value for the entire system. This should be stored in a configuration file somewhere. This fixed value would not have to be included every backup, making it even harder for an attacker to compromise all elements required to calculate the hash value properly.
  • Embedding a portion of the system salt in the source code. This wouldn't be that helpful for open source code, but for custom applications, having part of your system salt in the code would be yet one more item required by an attacker to calculate the hash value properly.
  • Generating a new salt for an account each time that user's password is changed.

If you are retrofitting an existing system, and don't have the ability to create and store a cryptographically random salt per account, then at least introduce something that is unique, and fixed, per account to the password hashing process, such as the account name and/or account ID. The more random the value the better so you can combine multiple short items together to generate a longer per account salt. For example, if the date of last password change is stored in the account, you could include that date/time as part of the user account salt since that value is fixed until the user changes his/her password again.

Recommendation: Salt Isolation

An additional password storage defense mechanism involves storing the salt in a different location than the password hash. Use of the server's filesystem is one commonly used mechanism for salt isolation, assuming the password hashes are stored in a database somewhere. This defense mechanism reduces the risk of password theft when the database file is stolen, since the salts will not be included with the database data. Be careful to ensure that both the password hashes and the salts are backed up together because one is not useful without the other.

Recommendation: Iterate the hash

If a password database is ever compromised, one of the primary things defending the hashed passwords from being broken is the computational time required to guess password values. As such, we recommend slowing down the hash computation by iterating the hash operation many times. While hashing the password many times does slow down hashing for both attackers and typical users, typical users don't really notice it being that hashing is such a small percentage of their total time interacting with the system. On the other hand, an attacker trying to crack passwords spends nearly 100% of their time hashing, so hashing many times can slow down an attacker by a factor of N (# of iterations) while not noticeably affecting the typical user. A minimum of 1000 operations was recommended in the RSA PKCS5 standard in 2000, a value that should be doubled every 2 years. Therefore, in 2012, it is recommended that 64,000 iterations be considered. You should measure the time required and make sure that its as large as possible without providing a significantly noticeable delay when your users authenticate.

References

  1. Cryptographic framework for password hashing is described in PKCS #5 v2.1: Password-Based Cryptography Standard.
  2. Specific secure password hashing algorithms exist such as bcrypt, scrypt.
  3. Implementations of secure password hashing exist for PHP (phpass), ASP.NET (ASP.NET 2.0 Security Practices), Java (Hashing in Java).
  4. Much of this article came from the original OWASP Hashing in Java article.

OWASP Cheat Sheets Project Homepage

Developer Cheat Sheets (Builder)

Assessment Cheat Sheets (Breaker)

Mobile Cheat Sheets

OpSec Cheat Sheets (Defender)

Draft Cheat Sheets