LinkedIn’s massive data breach of 2012 continues to be a source of agony for the organization and its users. According to LinkedIn’s official blog, in 2012 the company was the victim of an unauthorized access that resulted in the disclosure of members’ passwords. Although, at that time, LinkedIn’s immediate response included a mandatory password reset for all accounts which they believed were compromised, in May 2016 LinkedIn was again notified that during the same 2012 theft, email and hashed password combinations of more than 100 million LinkedIn members were compromised. LinkedIn subsequently proceeded to invalidate passwords for all accounts created prior to 2012.

LinkedIn stored passwords with an hashing algorithm but with no salt or other advanced security measures in place. Security experts do not consider this approach to be secure. These old algorithms use plain hashes which can be easily cracked within minutes using a multitude of tools available on the internet.

The Cloud Encryption Handbook

Download to learn about different encryption schemes and their relative strengths and weaknesses

Download Now

How does password hashing work?

When a user creates an account on a website for the very first time, the user’s password is hashed and stored in an internal file system in an encrypted form. When the user logs in to the website subsequently, the password hash entered by the user is matched against the password hash stored in the internal system. If the hash matches, the user is granted access. If the hash verification fails, the user is prevented from logging into the website.

Since these hash tables are designed to be fast but not necessarily secure, any hacker can use varied tools available on the internet to recover passwords from these plain hashes swiftly. Currently, there exists many varied ways to crack password hashes – namely, dictionary attacks, brute force attacks, lookup tables, reverse lookup tables, and rainbow tables. In a backend system, plain hashed passwords would appear as follows –

hash (“letmein”) = 0xf73bo1230k35n72nj523dtg9l4n2k6n24nv7i73gf36hf4ow9d4k4c2nm6m
hash (“12345678”) = 4h5g2c9d0a34lk1k3n0sd8sdl4h54nm9g76dsj3n5ksb38j5ls93md0l3hz9d2
hash (“baseball”) = 3n52k5kcn5kv9cma83ja83d430dm9c83m6n20cj67gb7ksnf8dgsmg056vm
hash (“letmein”) = 0xf73bo1230k35n72nj523dtg9l4n2k6n24nv7i73gf36hf4ow9d4k4c2nm6m

Note that in the above example, the hash values for the two users with the password “letmein” are identical.

What is a salt?

All the above mentioned mechanisms to crack a hash are possible because each time a plaintext string is hashed, it generates the exact same hashed value. For example, if an attacker hashes the value “letmein” it will generate the same value as the one stored in the backend system for another user with the password “letmein”. Attackers use pre-computed tables generated by powerful computers that enter all possible values into a hashing algorithm. These tables can also be purchased. Using these tables, an attacker can cross reference a stolen hashed value (such as a password) and perform a reverse lookup to determine the original value.

In order to add an additional layer of security, randomness needs to be added to the original plaintext value before hashing so that it will not generate the same hashed value each time. Randomizing these hashes by appending or prepending a random string, known as a salt, can make it significantly more challenging for an attacker to use lookup tables or rainbow tables to crack these passwords by increasing the possible hashed values each password can have. If each user has a unique salt, that makes the password immune against reverse lookups too. An internal file system which has hashed passwords with a salt would look as follows –

hash (“letmein” + “F34564R8”) = 8f3k9j3hdk98jk30lsvn9al30lfb48slhbtwe9uka903bwj380dsfj3v2nf930nk3
hash (“letmein” + “Y456f3q9”) = ber5jg0qhekgl8dkjhl52309uwlkmcbkuw385b9smqnv9c234calq95nf34flql
hash (“letmein” + “56hwF3h8”) = w2lkg034fmwprm80n59fdmal40djwbel46n32ldn2la9702nd772ha95lg06j

Now, for each user with the password “letmein” there is a different hashed value.

How to make the most of hashing using a salt

  • Ensure that the salt is unique for every user and for every password. Using ten different salts increases the security of hashed passwords by increasing the computational power required to generate lookup tables by a factor of ten. If the salt is stored separately from a password, it also makes it challenging for an attacker to reverse engineer a password. However, for the highest level of protection, use a unique salt generated for the same user each time she changes her password.
  • Every salt should ideally have a long salt value of at least the same length as the output of the hash. If the output of the hash function used is 256 bits or 32 bytes, the length of the salt value should at least be 32 bytes. Along with long passwords with specialized characters, this approach should provide required security to user passwords.
  • Do not use usernames as salt values. Since usernames are often predictable and reused by the user for various services, using usernames as the salt values is not as secure as using an unrelated value for the salt. Additionally, commonly used usernames like “admin” and “root” can easily be looked up and used to crack these hashes.
  • Use a cryptographically secure pseudo-random number generator to salt values used to hash passwords. These algorithms, as the name suggests, are cryptographically secure and generate random, unpredictable salt values.
  • Lastly, ensure that that there is a secret key added to the hash so that it is only if the secret key is known, can the password be validated. Also ensure that the key is stored in an external system, a physically separate server so that for a hacker to successfully hack the password he not only needs access to the internal file systems but also to the external key server.