Passwords are Dead, Long Live Passwords
Anyone that's been around web applications (or really any applications) that need to protect data or restrict access to only a certain group of users has experience with passwords. They're a de-factor standard when it comes to protecting your application. Along with usernames (or email addresses, depending on the system) they're used to identify the end user and verify they are who they claim. Unfortunately, there's a lot of things wrong with them that make them one of the worst options in application protection. There's whole industries about removing or reinforcing passwords in applications and yet they're still a huge part of the security of most services out there. I'm getting ahead of myself though. First off a little history of where passwords came from.
Where did passwords come from anyway?
The concept of a "password" or "passphrase" has been around about as long as there has been secrets to protect. Way back in history this "something you know" was used for everything from sharing information between groups to allowing access to certain physical areas not open to everyone. Fast forward to more recent history and there's no shortage of movies and books out there that where spies use them to identify each other or messages are protected with a password only the intended recipient should know.
They were first introduced into the world of computers in the early 1960s though. A group at MIT in Massachusetts decided that they needed a way to segregate out the time that people had to spend on the shared computing systems the university owned. It was used in their Compatible Time-Sharing System (CTSS). They even had the notion of protecting this password and not echoing it back out to the user as they typed. Incidentally, many Unix-based systems still do this while most web applications use a "password" type form field that, though masking it, still give an indication of how long the password is visually.
Move forward another 10 years or so and another password improvement came along in the form of hashed passwords. Robert Morris added this functionality into the origins of the operating systems we know as Unix that used a simpler version of the standard crypt() functionality to protect the password contents. Even then they realized that having just a plain-text, human readable password somewhere wasn't the best or most secure method for protecting those valuable resources.
Since then password storage methods and usage have evolved but the heart of the usage is still the same. They're still a single point of failure that's usually combined with a much more public piece of information, a username, to restrict access to portions of applications. This is the real key to the problem - they only offer a single point of protection that is all too often easily compromised, leaving the system wide open to attack.
Common Password Problems
I've already mentioned on of the major problems with passwords, the single point of failure they provide, but there's a few others that contribute to most of the password-centric vulnerabilities out there.
Password Reuse
We've all done it before. If you say you haven't you're probably fibbing just a bit. There's so many services out there and we're constantly signing up for more and more every day. With almost all of them using the same basic methods for authentication (again, the infamous username+password combo) it's very easy to slip into reusing the same password across multiple services.
Why is this a bad thing? Well, imagine you signed up for SuperAwesomeHosting.com with an email address for the username and a password that just happens to be the same as the one on your email account. the hosting company assures you that security is a top priority with their customers and that your information is 100% safe in their systems. One day an attacker stumbles over a development copy of the site, unprotected, with a SQL injection vulnerability and harvests all of the live user data - including your credentials. He now has not only the credentials for your SuperAwesomeHosting.com account but also your email account. Think of everything they could do if they made the jump and tried to log in to your email.
As a developer it's almost impossible to prevent this from happening unfortunately. The only thing you can do is try to enforce good password policies and hope users don't shoot themselves in the foot.
Bad Passwords
When I give presentations about security at conferences and online training, there's one thing I say every single time: "People are terrible at passwords". As humans there's a built in desire to make things as simple as possible. This is the same kind of thing that leads to password reuse. Unfortunately it also makes us lazy about the passwords we come up with. We use things like our pet's name, the date we got married or words right from the dictionary. Take a quick look through anyone's social media pages and you can find answers to most of these and just start guessing. Even worse, when it comes time to reset your password, most people will just tack on a "1" or "!" and call it good.
This is where password policies come in. These policies help guide users into creating good passwords that will effectively protect not only their own account but also your service. There's one key thing to remember when setting up your policies, the phrase "at least". The real key to effective policies is setting it up so that you define minimum requirements and let the user go wild from there. Sure, this can still lead to some pretty bad passwords, but there's also plenty of tools out there that will measure the entropy of the password to ensure it's strong enough.
Bad Password storage
I wanted to touch on one last topic that's a bit more developer focused than the others in this (non-exhaustive) list. Users put their trust in your to keep their private information safe, including the passwords they provide. They perceive this as one of the keys to you having a secure system so it makes sense that you'd be protecting this information accordingly. Unfortunately you hear of service after service that was either storing their users' passwords in plain text or, while making an effort to "encrypt" them only thought that an md5 of the password value was enough.
If you're doing either if these, stop right now and go fix your application. There's a lot of reasons people give out there for storing passwords poorly but they're all invalid.
Passwords should always be one-way hashed with a strong method prior to being stored. Any company that can send you a plain-text version of your password or that can read it back to you during a support call is without a doubt doing it wrong. There's no need for anyone other than the user themselves to know their password.
So, how can I do this effectively in my application? Fortunately, it's been made super simple since PHP 5.5 with the password hashing functions. It's literally a two line process to hash what the user gives you and to verify if it's correct:
<?php
// To hash the password
$storeMe = password_hash($_POST['userInput'], PASSWORD_DEFAULT);
// To verify the password
if (password_verify($_POST['userPassword'], $storeMe) === true) { echo 'yay!'; }
?>
This method currently uses an algorithm called bcrypt that rehashes the string provided a number of times based on the "cost" value. PHP's default cost is 10 unless you define it as an option.
And Finally
Passwords are flawed, there's no doubt about that. I mentioned tools and services that have come up around the password ecosystem that want to help remediate some of the risk associated with using them: two-factor authentication and federated identity being two of the more popular options. These can do a lot to help improve the overall security stance of the application and prevent other problems from happening but with a password at the core of it all, there's still going to be a lot of risk involved.
If the only protection between your application and the outside word is a simple user-defined string of text it might be time to rethink and reinforce your systems. Trust me, a password just won't cut it.