How to store passwords (of your website’s users), you wonder? There has never been a simpler question in website security, with such a straight forward answer:
Never-ever store passwords
Store hashes of your users’ passwords, never the passwords themselves. I don’t care if you plan on storing passwords in a file or in a database table, whether in plain-text (…yes, there have been cases, some notorious) or two-way encrypted. Forget all that. Just use good password hashes, always. Hashing is one-way encryption, meaning the result (hashed string) cannot ever be used to directly retrieve the original text, as opposed to two-way encryption, where the string can be decrypted back to the original, using the encryption key.
Your mighty user authentication mechanism, which you’ve spent countless hours developing and testing, and is now, theoretically, full-proof, will be rendered useless if you or your users choose to use weak passwords. Hence the need to enforce strong passwords.
Without going into to much explaining, what makes a weak password?
- password is short: the shorter the string, the easier to guess it, and the inherent drop in potential complexity only helps guessing: boob2 is a weak password.
- password contains common words: “dog”, “bread”, “bacon”, “concupiscence”, you name it. If the word can be found in a dictionary, it is a common word. Avoid l33t speak, too.
- password contains special words: the very user name, the name of the website/system where the password is being used
- one (upper or lower) case letters only: this automatically halves the potential complexity of the password string.
- no digits: there are no digits (0-9) in the password string.
- no special characters: there are no special characters (e.g., *^&£:]’) in the password string.
There are two main ways to implement security in a system. They should always be used together, for reasons that will become obvious.
Security through obscurity
This means keeping critical parts of the system you’re designing a secret. Keeping your code closed source, not disclosing the structure of your system, etc.. The extreme example would be keeping the domain name of your website a secret…
Dr. Bimal Chhajer in his book “Heart Attack” writes about a diabetic male patient, 55 years old, who noticed some breathlessness on the way to his office. After consulting his physician and routinely passing the ECG exam, it showed that he was just experiencing a silent heart attack. In such moments every second counts, so he was rushed in the emergency room immediately.
With the USA being on the third place in the world in the top countries of patients with diabetes, there’s no doubt that a specific attitude must be approached when we speak about the silent myocardial infarctions in these patients. The chances of experiencing a heart attack in a diabetic sufferer increases with the age, because of the capillary damage, and The chances of it developping without any symptoms increases as the nerves become damaged, too.
Where do I store my database credentials?
There comes a point, in security matters, when developers run into the age-old question: “Who was first? The chicken or the egg? Or the hen? Perhaps the fowl?”
You (your scripts) need an user name and password to access the database server. Where to securely store these? Yes, in a database table! What an elegant, secure solution! Oh, wait… You need an user name and password to access the database server in order to retrieve the user name and password required to access the database server.
The (generically titled) “system” directory of your website or web application should be the one containing all the scripts required for system administration, completely separated by all other files. To achieve maximum security in this regard, here are some important guideliness:
System directory name
- do not name the “system” directory “system”, or “admin”, or “root”, etc.. Instead, choose an unusual and cryptic name, and use a global variable in your code to hold this name. This way, the default “system” directory can me renamed and moved deeper into the file system, provided the global variable is hard-coded with the same value (eventually including the relative path). If you’re building a system that get’s deployed to others, teach the (future) admin to do this before going live.
- URL rewriting to access the “system” directory should only be used on top of the action described above.
- “system” directory name should not be made apparent to any visitor or registered user, except system administrators, who would get a link taking them to the admin interface located in this directory
- scripts running in the “system” directory (say, example.com/system_dir_name/some_settings.php) should display no direct outbound links (to other websites)! Reason being, the HTTP Referer header will contain the URL, compromising the secrecy of the “system” directory name.
You may be developing a simple, straight forward personal website, containing information that’s both public, and easy to back-up, and so implementing proper security measures doesn’t present much interest. However, no matter how simple or low-value your system is, it is definitely not your intention to have it defaced by hackers. Failing to secure your website guarantees that, sooner or late, it will be defaced, if only for the lulz. Happened to me? Oh, yes.
Stuff you have no excuses for, no matter what you may come up with. I know, you’re so above and beyond this, but simple things are often the easiest to overlook, and when they go wrong they tend to do the greatest damage. Before pondering on which encryption cipher to use, make sure you’ve got these covered.
- sticking your FTP/website admin credentials on a post-it on your monitor
- keeping any admin credentials in a plain-text file on your webserver, which, when accessed, will not undergo any server-side processing (such as happens to a PHP script), but will be simply displayed in browsers
- letting your sensitive directories (containing sensitive administrative data) be accessed from the web, including as indexes
- diluting security of your admin credentials by holding them in potentially insecure online storage, such as your own email inbox, in plain-text
- using poor admin credentials, such as an easily guessable admin user name (“admin”, “administrator”, “webmaster”, “root”, etc.) and a weak password (i.e. short and lower case letters only)
This was the singlemost effective tactic Kevin Mitnik used, according to himself. The name sounds cool, but it really is about getting people to spill the beans and give the attacker security sensitive information in the old fashion way, that only requires people skills (as opposed to advanced computer hacking skills).
Allegedly, this is still the most effective way of breaching security, as it relies on the weakest link in the security chain: the human.
Some of de most basic and useful general principles of programming must be applied when approaching security matters in your code.
Stay DRY (Do not Repeat Yourself)
More than unproductive, repeating yourself when implementing security is dangerous. Bugs have more room to spread and remain undetected (slipping between a copy and a paste or two .hg commits ). Attackers get more chances to see your code.