Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

Hash Storage: Make Attackers Work

So you hash your passwords? Good. Do you salt? That’s good. Do you use a strong hashing algorithm (PBKDF2/bcrypt/scrypt)? Great! But how do you store the hashes? What happens when you get hit with a SQL injection attack?

I’m a big believer in defense in-depth – not that marketing garbage about stacking layers of blinky-light boxes, but using techniques to add extra work for an attacker. You might not be able to stop every attack, but the more work they have to do, the better the odds they won’t get everything they want.

So, let me describe a scenario:

$company stores passwords as SHA1(password + salt) hashes (terrible, I know – but still common). They install a new web application that connects to their main database – this new application has a previously undisclosed flaw, SQL injection.

$evil_hacker finds this flaw and looks for companies that use the application; finds $company, exploits, dumps their user table and posts the hashes on PasteBin. Having both the hash and salt, those hashes will fall_quickly_.

We’ve all seen it before – far too many times.

Now, let me modify the scenario slightly: instead of SHA1(password + salt), make it AES128(salt : SHA1(password + salt), key) – where key is an application secret.

Now, we have a different story – as long as the application secret remains secret, the hashes are safe. Stored in the clear, they will fall quickly – encrypted, they are safe as long as the secret remains safe.

In the case of many SQL injection attacks, the attacker is able to access the data, but doesn’t have access to the application source code. In these cases, you can add a few extra milliseconds to processing time and as a result stop attackers from using stolen data from an entire class of attacks. There’s nothing new about this idea – but I don’t see it used nearly often enough.

Obviously this doesn’t help if the attacker is able to retrieve the source code, so you still need to use a strong hashing algorithm. Encrypting a strong hash buys you extra protection against certain attacks, and maintains a strong baseline against others – at a very small performance cost.

In case of a breach, I would still assume that the attacker knows the encryption key, and reset passwords accordingly. Seeing as it takes time to find out the extent of the breach, it’s safest to act as if the attacker has everything and limit the damage as quickly as possible. In reality though, the odds of the passwords being exposed as a result of a SQL injection attack is reduced significantly thanks to the added encryption layer.

Storing the data like this keeps everything secure, and in a single field (and makes it easy to integrate into existing applications):

<IV>:AES128(<salt>:HASH(<password><salt>))

This way all of the material needed is encrypted; though it could be argued that just encrypting the hash or the salt would be sufficient (assuming the salt is at least 16 bytes and generated by a CSPRNG). The core idea here is to deny the attacker of as much information as possible; making it as difficult as possible to find passwords.

There are no silver bullets, but we can take advantage of the tools we have to make attackers work harder to get our secrets.

Adam Caudill


Related Posts

  • When Hashing isn’t Hashing

    Anyone working in application security has found themselves saying something like this a thousand times: “always hash passwords with a secure password hashing function.” I’ve said this phrase at nearly all of the developer events I’ve spoken at, it’s become a mantra of sorts for many of us that try to improve the security of applications. We tell developers to hash passwords, then we have to qualify it to explain that it isn’t normal hashing.

  • PL/SQL Developer: Nonexistent Encryption

    (See here for another issue discovered during this research; Updates over HTTP & Command Execution.) PL/SQL Developer by Allround Automations has an option to store the user’s logon history with passwords – the passwords are encrypted with a proprietary algorithm. At this point, you should know how this is going to go. For those that don’t know, PL/SQL Developer is a tool for developers and database administrators to access Oracle – an essential tool in many enterprise environments.

  • On NSA-Proof Security

    @KimZetter We need to distinguish between "proof against NSA dragnet", "proof against NSA PRISM", and "proof against NSA TAO". @runasand — zooko (@zooko) September 17, 2014 For a long time, “military grade encryption” has been a red flag for snake oil, over-hyped, under-performing garbage, so much so that it’s become a punchline. Anytime that phrase is seen, it’s assumed that the product is a joke – quite possibly doing more harm than good.

  • Password Hashing: No Silver Bullets

    In the dark days of the web, if a service hashed your password instead of storing it in plain text, they were doing good. As sites were hacked, and credentials stolen, a silver bullet emerged: always hash and salt passwords when storing them. Many, many services were built with this design – LivingSocial is a great example. SHA1 hashing with a 40 byte salt – once upon a time, that was considered reasonable protection.

  • 1Password, PBKDF2, & Implementation Flaws

    …or “Crypto Is Hard, Vol. 479” Earlier today a tweet about a new feature for oclHashcat-plus started a truly interesting debate on Twitter over the implications. The new feature is the ability to crack 1Password keychain files – at an impressive 3 million passwords per second. Support added to crack 1Password to oclHashcat-plus, 100% computed on GPU! Plus I found an exploitable design flaw http://t.co/53ZtWggsDz — hashcat (@hashcat) April 16, 2013 To achieve this speed, two optimizations were used – the first is in precomputing ipad and opad for SHA1-HMAC, this effectively cuts the number of SHA1 calls in half.