Hacker News new | past | comments | ask | show | jobs | submit login
Coding Horror: You're Probably Storing Passwords Incorrectly (codinghorror.com)
32 points by luccastera on Sept 17, 2007 | hide | past | favorite | 50 comments

"most users tend to re-use the same passwords, probably because they can't remember the two dozen unique usernames and passwords they're forced to have. So if you obtain their forum password, it's likely you also have the password to something a lot more dangerous: their online banking and PayPal."

I admit to being somewhat guilty of this, but I'm astonished anyone would use the same password for throwaway email acconts as for financial stuff. I do use only like 2 different passwords for all my stupid little Internet forum accounts, though.

With the exception of the database or backup being 'stolen' wouldn't the addition of a 3rd variable, like a captcha code, solve brute force attacks?

I have been considering implementing something like a captcha code on my login forms (but haven't yet).

Services like CAPTCHA are intended to solve different problems, like protecting your web service against DoS or bot/spam attacks.

To brute force crack a password, you would really need direct access to the digest. We are talking around the order of 2^80 attempts before finding a collision with a algorithm like SHA-1. Checks need to happen very fast. Doing this through a web interface is already too slow to be feasible from a time perspective.

So really, cracking passwords is only a consideration when someone gets a hold of all your digests (eg. your database) and can crunch away on them locally for a long time.

I'm really not sure you're talking about the same thing as, well, anybody else doing password security. Brute force incremental crackers (read: almost every password cracker ever written) don't attack the algorithmic strength of SHA1. They attack the complexity of the underlying passwords, using dictionaries, mutation functions, and statistics.

SHA1 is strong (at least in this application). Passwords are very, very weak.

Password cracking is an offline attack. If you think the only way you're going to lose your password table is if someone steals a hard drive or a backup, or uses a zero-day to root your whole server, you are making an extemely bad assumption.

Assuming the webserver is not compromised, the sql server is on it's own local network, and the webserver is on both the local network and the Internet accessable network (2 network cards), how exactly does someone get direct access to the sql server to run an offline attack.

I have always assumed the database server is safe there alone on it's own network as long as someone doesn't break into a machine that is connected to that network.

Consult the Wikipedia on "SQL Injection" attacks.

I already parse everything from the querystring, form fields, (even) cookies (anything the user can manipulate) for malicious input (sql injection). That is standard fare, anyone who doesn't do that will find themselves in a world of hurt fast.

Tell me all the things you parse for, and I'll name something you missed. The catch: if I do, you have to change the front page of your application to this:


for at least 2 weeks.

After reading every comment on this thread, I have determined that all posts from Thomas are written using the same pattern.

"Several sentences of very informative information and background on the topic of security for those non-experts (vast majority of us).

One sentence calling the parent poster an embarrassing retard."

Seriously though, I appreciate the insight into the topic and enjoyed your reply post to the one at Coding Horror. Thanks to you I finally understand the reason a decent salt matters, and I'll be sure to ditch SHA1 for bcrypt when I get home. You can rest assured I'm not trying to design my own password system (for anything public)... I was just wondering, are there other systems that do authentication without actually sending the password over the wire besides the supposedly-hard-to-implement Stanford one that may or may not be patented? Bonus points if it's open source...

You are right, and this is a personal failing. Experience suggests I'm unlikely to overcome it. For the record, I don't think any of you are embarassing retards. But after reading comments here and elsewhere --- "that's OK, I'm making my salt 256 bits!" --- I fear that some of the password systems you will devise will be embarassingly retarded.

As for the parent comment: I just really like that picture.

Regarding challenge-response alternatives to SRP: I don't think these work well on the web.

Reason 1: on almost anything unencumbered by the Thomas Wu patent, you're going to have to store cleartext passwords on the server, which is probably worse than forcing clients to send passwords over the wire.

Reason 2: challenge-response only works if you feed the login page and Javascript dependencies over SSL (otherwise, the same attacker who can sniff passwords can hijack and man-in-the-middle logins). But if you trust SSL to feed the login page, why not trust it with the actual passwords?

No sir. I be using SHA256 hashes and per-password salts, ever since our site's launch.

Django's session/user framework uses a salted hash. Does anyone have any critiques of their method?

Great article, some good links, and a damned eye opener. I need to start salting my passwords...

If you have to reason through or alter what you're currently doing with passwords, it's irresponsible of you to be storing passwords at all. Like it or not, your users are using the same password for your web 2.0 recipe sharing program as they are for their bank account.

Lesson: use someone else's (good) password system.

Better yet, use OpenID and let somebody else worry about passwords.

(ok, this isn't an option for everybody yet)

Is there a list of these somewhere? Which ones would you recommend?

If you ship on Unix, use what your operating system ships with. Failing that, use bcrypt, or PHK's MD5 scheme. If you must DIY, iterate the hash function several thousand times.

> Lesson: use someone else's (good) password system.

Ok, what? I use Ruby on Rails, and I want something open source. What do you recommend?

Acts_as_authentable uses bcrypt.

If your bank only uses a username/password combo to confirm your identity online, you need a new bank.

If you use the same password for your web 2.0 recipe account as your bank, etc, etc, etc. We shouldn't rationalize this stuff. All I'm saying is, don't make mistakes with your password system; use someone else's (good) password scheme.

I need to start using a longer salt and/or a slower hash.

And I need to come up with a website worthy of someone breaking into.

So much to do, so little time.

Salt length and hash speed are orthogonal. Increasing the length of your nonces doesn't make your passwords less crackable. If this is news to you, don't design your own password scheme; use someone else's good one, so you aren't accidentally exposing people's bank accounts.

Increasing the length of the nonce definitely makes the password less crackable. Since brute force methods search the entire space, the more space, the better. It's still possible to crack in by finding a hash collision, but the longer your non-password trash, the harder it is to recover the password via brute force.

All due respect, but you shouldn't be designing password schemes. Modern password schemes are cracked using incremental crackers. This "rainbow table" stuff has totally confused the developer community. John the Ripper doesn't make a time/space tradeoff; it uses the (public) salt and the hash and iteratively recomputes hashes, and it is terrifyingly fast even on good password schemes.

That's one attack vector. Assuming someone does attempt to use a brute force method, longer salts do matter. I think that qualifies as non-orthogonal to "crackability," even if orthogonal in some cases.

Truthfully, this isn't even worth talking about. If your user's passwords are compromised, you've already lost the security battle. Hopefully you weren't actually storing something important.

That's horribly irresponsible. Using your logic, you might as well just store the passwords in plaintext. Most people don't use different passwords for different applications, and your web application is inevitably going to expose all your users passwords, like every other web app that has been SQL-injectable (ie, almost all of them).

As a person interested in security, you're well-familiar with the fact that nothing is 100% secure. Choosing a less secure option over a more secure one is not tantamount to choosing no security at all.

That said, I personally don't mind plaintext passwords if there's a good usability story that goes along with it and if the security tradeoff is negligible. I put the odds of my user database being exposed at approximately zero, so generally it's a fine design decision. When was the last time you heard of passwords being stolen en masse from a major site that didn't also include a hard drive being stolen?

As a person who spends 3-4 days a week assessing other people's web apps, I'm well-familiar with the fact that it's a very good bet that everyone's web app is SQL-injectable, whether they've tried to stop that attack or not. For example, do you know how internationalization works?

I have no idea why you think the public is told every time a a password table is dumped. In fact, change that "every" to "any".

Here, let me make this easier for you: if you ever plan to monetize your application, you will fail PCI audits for doing a crappy job with password storage. But I'll do you one better and give you a tip from the trenches: if some lame PCI auditor sees that you don't know what you are doing, his company is going to roll you for 8 billable weeks, laughing at you the whole time, before they give you the meaningless stamp of approval that lets your process credit cards.

So where's the best-practices security checklist?

I'm not a security expert. I write webapps. I'm open to learning new techniques and using other people's libraries. However, I need to balance that against the need to get something out the door. As mynameishere put it, I'd love to have a website that's even worth breaking in to.

If there's some sort of tutorial out there that says "For passwords, use this library. For SQL injection, escape your parameters with this procedure. Here's how to secure your server from being rooted. Add these lines to your mailserver's config to avoid being used as a spam vector", I'd love to read it.

We take requests! I'm working on this with my partners. Thanks for the suggestion.

reddit was - although it was a hard drive stolen.

Whether the attack is brute force or a time/space trade-off, longer salts increase addressable space which increases time or space required to achieve a collision. It doesn't matter how you're doing it, this is a simple fact.

A larger key is always more secure.

The salt is public. If you have the password table, you have the salt. The attacker doesn't have to guess the salt with an incremental password cracker (read: almost any password cracker).

The mistake you're making is your misuse of the word "key". Larger keys are more secure. A salt is a nonce, not a key.

Can I say again that people shouldn't be rolling their own password scheme? This is a problem that has been well-addressed for decades, but the majority of new applications still ship with code that is inferior to public domain code from 1976.

Are you saying that nobody uses hash dictionaries anymore and one need only worry about brute-forcing of individual passwords?

I'm not ready to stop thinking about hash dictionaries, and the 4-character salt I prepend to passwords before hashing is too short. A 4-character salt plus a 7-character password is a value that could be vulnerable to dictionaries roughly the size of the Rainbow tables.

But if you can cite a paper demonstrating that brute-force cracks of individual passwords are the only thing one need be concerned about, I'll look at it and see if it changes my mind.

Nobody is saying you don't need to use salted passwords. What we're saying is, if your password scheme is (user, nonce, SHA1(nonce, password)), don't bother; just store your passwords in plaintext. Your users passwords are so weak (dictionary word + number) that a 200 line incremental cracker is going to blaze through it in hours.

The answer to this is to use someone else's (good) password scheme. If you're shipping on Unix, your system undoubtedly comes with one. Use it.

If you mean to say that users should be forced to choose strong passwords, that's a different thing from saying longer salts don't make a set of passwords less crackable.

I don't understand why people are hyper-focusing on this one attack. Attackers have been cracking passwords, quite effectively, long before tools like Ophcrack were available. Any decent salt scheme beats Ophcrack; it doesn't take much to make hash chain storage infeasible. But you can make your salts longer than JSESSIONID's and they still won't be a speed bump to a "conventional" password cracker.

I'm not arguing that users should be forced to choose secure passwords. They should, of course, but we're talking about how you store them. If you store them using a single-iteration SHA1 hash, then no matter how you structure your nonces, your scheme is insecure and you should be embarassed.

When you say, "Increasing the length of your nonces doesn't make your passwords less crackable," you can expect that people will talk about the type of attack that a longer nonce helps deter. That isn't hyper-focusing; it's polite conversation. The impolite alternative would be to say you should be embarrassed for making a statement like that.

I'm not saying you should be embarassed for conversing about this subject. I'm saying that if you store real people's passwords in a publically accessible web application using a single-iteration SHA1 hash scheme, you're insecure, and should be embarassed that you were outdone by password schemes that came with your operating system and were largely refined during the 1970s.

I ask, what type of attack do you think lengthening the nonce deters? The attacker who is going to construct 4 billion rainbow tables?

I use a 4-character salt, which is prepended to the user's password before computing the hash. For users that choose a password of only 7 characters, that's only 11 characters hashed. The rainbow table covered a significant chunk of all 14-character strings. Even if I switch to a hash function that runs slower and produces longer values, I still think that 4 characters is too short a salt given the way things are going.

If I move to, say, a 16-character salt, after that I'll agree that making it longer is pointless.

Even if they're just the isprint characters, that's still 74MM variants on every hash. Stop thinking about rainbow tables. Nobody is going to rainbow table your weak salted password scheme. They don't have to, because you're using native SHA1 as your hash!

Even worse, I'm using md5 as my hash, just because it was built into postgresql. I should do more to protect users who choose weak passwords, as I feel they should be allowed to do so for my site. (They also have the option of never choosing a password and always logging in with a one-time link.) What tends to bother me more is the idea of someone choosing a reasonably strong password, one that isn't vulnerable to reasonably-expected brute-force attacks, and having some new dictionary attack crack it just because I was stingy with my salt. The other reason I worry about the cracking of strong passwords more is that it's more likely that a strong password would be shared with banks, etc.

Seriously, people store plain-text passwords? Come on guys, surely you know better than that!

Good thing I hash my passwords.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact