Would it be beneficial to use SSL on a CMS backend? The only sensitive data I can think of is the password. The password, as it is now, is encrypted with MCRYPT_RIJNDAEL_256 and a key.
Any comments are appreciated :)
Yes you absolutely should. While you use a good encryption, unless you're adding a SALT to the password, it is likely easily looked up in a pre-computed hash table (rainbow table) and you can probably find it online within a matter of seconds.
CMS is something you definitely want to be secure about since it potentially gives someone complete access to the content of your website to maliciously alter as they wish, or possibly exploit from there to gain access to the server or disable your login.
Https doesn't really add any overhead, but it's very simple to add. I'd recommend it, even though it's not going to provide perfect security, some is better than none!
Related
So, let's assume I have read every article/post about appropriately salting and hashing passwords in order to secure user credentials.
This means I am not wondering what hashing algorithm to use (SHA1 vs. SHA2 vs. PDKBF2), how to generate the salt, how to store the salt, how to append the salt, or whether I should be writing the code myself vs. leveraging well-established libraries like bcrypt. Please, avoid rambling about these issues here as I have read 50+ other pages of that already.
Just assume the following is my approach (also note I understand this is not flawless or likely sufficient for applications like financial service, I am really just wondering if this is an acceptable min bar to claim that I "do the right thing").
User comes to my amazing website (www.myamazingwebsite.com) and logs in with email and pass.
I pull her salt and hash from my database. Assume the salt is lengthy enough, unique per-user, and created using a CSPRNG upon user registration.
I prepend the salt to her input password, hash it using SHA-512, run 1,000 iterations, then compare it to the hashed value pulled from the db:
var hash = sha512(salt + password);
for (i = 0; i < 1000; i++) {
hash = sha512(salt + password + hash);
}
If they match, the user is authenticated. Otherwise, they are not.
Now, my question is how secure is my above approach. The questions I would like help answering:
Do I need to change the salt periodically? For example, perhaps I could re-compute and store a new hash using a newly created random salt after every successful login. This seems like it would be more secure but I am not sure what standard practice is here.
The request to the server will be done via https. Does that mean I can assume that I can process all of the hashing and validation logic server side? Would most folks consider this sufficient, or do I need to consider some hybrid both on client and server side?
Anything else I am overlooking or need to consider?
Thanks in advance, I appreciate the help.
1) Assuming you've done the right thing and do not store their password, you can't change the salt unless they are logging in. I suppose you could change their salt every time they do log in, but it doesn't really help (and might hurt).
Here's why: Having a unique salt on everyone simply makes it harder for an attacker that has access to your database from attempting to guess the passwords. If you've done things correctly, he would have to use a different salt for each person. He can't just start guessing passwords using a site-wide salt and see if it matches anyone. As long as you have a unique salt for each user, you are doing the best you can.
In fact, changing the salt does nothing but give an attacker with access to your database over time MORE information. Now he knows what their password looks like salted two different ways. That could (theoretically) help crack it. For this reason, it would actually be ill advised to change the salt.
2) Https is sufficient. If someone can compromise https, then any additional client side hashing or such will not help. The clients computer is compromised.
3) I think you have a fair understanding of best password practices. Don't overlook other security issues like sql-injection and cross-site scripting.
Do I need to change the salt periodically?
No. The salt is a per-user public parameter that servers two purposes. First, it ensures that an attacker cannot build an offline dictionary of passwords to hashes. Second, it ensures two users with the same password have different hashed password entries in the database.
See the Secure Password Storage Cheat Sheet and Secure Password Storage paper by John Steven of OWASP. It takes you through the entire threat model, and explains why things are done in particular ways.
The request to the server will be done via https. Does that mean I can assume that I can process all of the hashing and validation logic server side?
This is standard practice, but its a bad idea. Its a bad idea because of all the problems with SSL/TLS and PKI in practice. Though this is common, here's how it fails: the SSL/TLS channel is setup with any server that presents a certificate. The web application then puts the {username, password} on the wire in the plain text using a basic_auth scheme. Now the bad guy has the username and password.
There's lots of other problems with doing things this way. Peter Gutmann talks about this problem (and more) in his Engineering Security book. He's got a witty sense of humor, so the book is cleverly funny at times, too even though its a technical book.
Would most folks consider this sufficient, or do I need to consider some hybrid both on client and server side?
If possible, use TLS-PSK (Preshared Key) or TLS-SRP (Secure Remote Password). Both overcome the problems of basic_auth schemes, both properly bind the channel, and both provide mutual authentication. There are 80 cipher suites available for TLS-PSK and TLS-SRP, so there's no shortage of algorithms.
Anything else I am overlooking or need to consider?
Cracking is not the only threat here. More than likely, the guy trying to break into your organization is going to be using one of the top passwords from the millions of passwords gathered from the Adobe breach, the LinkedIn breach, the Last.fm breach, the <favorite here> breach.... For example:
25 most-used passwords revealed: Is yours one of them?
The 30 Most Popular Passwords Stolen From LinkedIn
Top 100 Adobe Passwords with Count
Why bother brute forcing when you have a list of thousands of top rated passwords to use?
So your FIRST best defense is to use a word list that filters a user's bad password choices. That is, don't allow user's to pick weak or known passwords in the first place.
If someone gets away with your password database, then he or she is going to use those same password lists to try and guess your user's passwords. He or she is probably not even going to bother brute forcing because he or she will have recovered so many passwords using a password list.
As I understand it, these word lists are quite small when implemented as a Bloom Filter. They are only KB in size even though there are millions of passwords. See Peter Gutmann's Engineering Security for an in depth discussion.
I want to make a user login system for the purpose of learning. I have several questions.
I did some research and found that the proper way of implementing a user login system is to store the user name/id and the encrypted/hashed version of the password in the database. When a user logs in, the password is encrypted client side (MD5, SHA-1 etc.) and sent to the server where it is compared with the one in database. If they match, the user log in successfully.
This implementation prevents DBAs or programmers seeing the cleartext of the password in the database. It can also prevent hackers intercepting the real password in transit.
Here is where I'm confused:
What if the hackers know the hash/encrypted version of password (by hacking the database) or DBAs, programmers get the hashed version of the password by just simply reading the text in the database. They could then easily make a program that sends this hashed version of the password to the server allowing them to successfully log in. If they can do that, encrypting the password doesn't seem very useful. I think I misunderstanding something here.
Is this (the way I described above) the most popular way to implement user login functionality? Does it follow current best practices? Do I have to do everything manually or does some database have the built-in ability to do the same thing? Is there a most common way/method of doing this for a website or a web app? If so, please provide me with details.
My former company used couchDB to store user login info including passwords. They did not do too much with the encryption side of things. They said couchDB will automatically encrypt the password and store it in the documents. I am not sure if this is a safe way. If so, then it is pretty convenient for programmers because it saves lots of work.
Is this way (point 3) secure enough for normal use? Do other database system such as mySQL have this kind of ability that can do the same thing? If so, does it mean that using mySQL built-in method is secure enough?
I am not looking for a very super secure way of implementing user login functionality. I am rather looking for a way that is popular, easy-to-implement, proper, secure enough for most web applications. Please give me some advice. Details provided will be really appreciated.
When a user login, client side code will encrypt the password by MD5 or SHA-1 or something like that, and then send this encrypted password to server side and then compare it with the one in database. If they are matched, the user log in successfully.
No, no, the client needs to send the unhashed password over. If you hash the password on the client side then that hash is effectively the password. This would nullify the security of the cryptographic hashing. The hashing has to be done on the server side.
To secure the plaintext password in transit it needs to be sent over a secure channel, such as an encrypted TLS (SSL) connection.
Passwords should be salted with a piece of extra data that is different for each account. Salting inhibits rainbow table attacks by eliminating the direct correlation between plaintext and hash. Salts do not need to be secret, nor do they need to be extremely large. Even 4 random bytes of salt will increase the complexity of a rainbow table attack by a factor of 4 billion.
The industry gold standard right now is Bcrypt. In addition to salting, bcrypt adds further security by designing in a slowdown factor.
Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.... Cryptotheoretically, this is no stronger than the standard Blowfish key schedule, but the number of rekeying rounds is configurable; this process can therefore be made arbitrarily slow, which helps deter brute-force attacks upon the hash or salt.
A few clarifications:
Don't use MD5. It's considered broken. Use SHA but I'd recommend something a little better than SHA1. - https://en.wikipedia.org/wiki/MD5
You don't mention anything about salting the password. This is essential to protect against Rainbow tables. - https://en.wikipedia.org/wiki/Rainbow_tables
The idea of salting/hashing passwords isn't really to protect your own application. It's because most users have a few passwords that they use for a multitude of sites. Hashing/salting prevents anyone who gains access to your database from learning what these passwords are and using them to log into their banking application or something similar. Once someone gains direct access to the database your application's security has already been fully compromised. - http://nakedsecurity.sophos.com/2013/04/23/users-same-password-most-websites/
Don't use the database's built in security to handle your logins. It's hacky and gives them way more application access than they should have. Use a table.
You don't mention anything about SSL. Even a well designed authentication system is useless if the passwords are sent across the wire in plain text. There are other approaches like Challenge/Response but unfortunately the password still has to be sent in plain text to the server when the user registers or changes their password. SSL is the best way to prevent this.
I'm about to start setting up an employees-only Rails application at our company for working with sensitive information. There will be a firewall, physical security measures, etc. My concern right now is the login process for the application.
I'd like to use Devise for authentication. What is the most secure possible configuration for Devise?
I'm thinking I wil do the following:
Lock accounts after a small number of failed login attempts
Use config.paranoid so an attacker can't tell if they've guessed a valid email address
Maybe disable password resets by email?
Some of the specific things I'm unsure of, with quotes from devise.rb in italics:
Peppers. Devise has an option to "Setup a pepper to generate the encrypted password." My understanding is that this is a single, app-specific value that transforms a stupid password like "password123" into something like "password123K#(!#akdlwekdf" or "*%!kd39gpassword123" or whatever before hashing. This is meant to thwart rainbow table attacks, but my understanding from this article is that it's not as good as a per-password unique salt. Then again, this article and this paper say that bcrypt has salts built in. Does using a pepper with bcrypt really add anything? Can I, and is there any need to, also have a salt column?
Stretches. "For bcrypt, this is the cost for hashing the password and defaults to 10." Based on this question, I'm thinking of using a work factor of 12. Does that seem reasonable?
Password length. A longer password seems more secure in general, but I don't want it to be so hard that the user writes it on a piece of paper somewhere. Does password length matter much if we're using bcrypt?
SSL cookies. For public apps with SSL enabled, marking cookies as "this can only be transmitted over HTTPS" protects against Firesheep-style attacks. But I'm not sure how much sense it makes to have a security certificate for an internal app. Is that silly?
What else am I missing?
Peppers: yes you are correct. There is not much additional security achieved with a pepper if you are using salt.
Stretches: 12 is reasonable, however bcrypt only ensures a constant time. You should consider using the newer scrypt as it allows you to specify both a constant time and the amount of memory to use. Cryptyograhpically bcrypt and scrypt are about the same but scrypt makes brute forcing harder.
Password length: forcing any sort of password rules reduces the entropy of passwords. The only restriction should be a minimum length and numerous studies have suggested at least 8 characters.
SSL Cookies: use them if you can. Security should always be built from the start and not added later. You can never be sure who might be sniffing you internal network. Just because you assume no outsiders can sniff data, does not mean inside employees wouldn't for one reason or another. You have a responsibility to protect your employees from each other as well as external threats.
For passwords, you can checkout https://github.com/bitzesty/devise_zxcvbn which rejects passwords with weak entropy, and checks against known cracked passwords.
Lets say I have "admin" folder in my public_html and I don't want anyone except me to be able to access it. What if instead of password protecting it (using apache htaccess) I just rename it to "admin-7815696ecbf1c96e6894b779456d330e" and leave it open (with disabled folder indexes of course)?
People usually freak out from such "solution" as it seems extremely vulnerable. But is it really any worse than password protecting? I can't think about any major security risks comparing to password protecting. Would anyone be ever able to find out a name of this folder?
For a personal site, it's probably OK - but only you know the value of what you are protecting. One thing to be wary of is if you have webpages in that directory that link to external sources - by clicking a link to one of those external URLs you will (probably) pass on your "secret" url in the HTTP Referrer header. Also, it only takes on link back to your "secret" url and robots and spiders could be all over it and then you'll find it in Google. So, be very careful!
Bad idea - It's basically security by obscurity.
This is the sort of thing you'd use to protect a phpbb /install/ folder during an install, but not as a permanent solution.
Yes its a bad idea.
If you don't use a password, other systems won't treat it as such.
For example, your browser will now cache that url in its history. It won't do that automatically for passwords (at least not Firefox)
What about the list permission? What about internet hops, they'll see your URL.
If you start going around the security system, the security system won't know you want to be secure.
EDIT
Another way to think about it is, when software sees a password it goes, "This is an security issue and I will treat it as such." But for URLs, it goes "Meh, another piece of data"
Contrary to what others have said, this is not security through obscurity, and depending on how the random folder name is assigned, and how that name is protected, this can be a very secure solution.
First, choose the folder name from a large "space". Due to the size of the number in the question, it looks like that has been done. Personally, I'd choose a number randomly in a range up to between 2112 or 2128, then encode it to text using hexadecimal (base-64 would work in some contexts, but it's not handy for directory names).
The random component should be chosen from a cryptographic quality random number generator.
Then, protect the random name by transmitting and storing it only on secure media. This means, for example, only accessing the contents of the directory over HTTPS. Without SSL, an man-in-the-middle would learn the secret directory name and have unrestricted access.
If this is done by an administrator for their own use only, it's a quick and easy solution. If multiple parties need access to the directory, user names and passwords (which must also be transmitted only over a secure channel) quickly become more convenient because rights can be granted only by an administrator and can be revoked without affecting other users.
As Pyrolistical was saying, a randomized URL isn't protected with the same degree of care as a password would be. There's a lot of security research that goes into the systems that store and transmit passwords, and if you just use a randomized URL instead, you get none of that. (Well, you can force HTTPS for the URL, that gives you some benefit) But if you just want to deter casual snoopers, it's probably good enough. I've used that technique in the past when I wanted to share a URL with a few people, given that the data stored at the URL wasn't especially sensitive.
As for whether the randomized URL approach is appropriate for you, it depends - what web pages can you access from it? Typically "admin" means things like system control apps or database interfaces (phpMyAdmin and the like), and those sorts of things I wouldn't trust to a randomized URL scheme. Basically, if the web pages you're trying to protect are things that allow you to make changes to the system, go with password protection. But if they're read-only monitoring apps, like server statistics (and if there is no sensitive or personally identifying information involved), a randomized URL might be fine.
Honestly, though, why wouldn't you just set up password authentication, given how easy it is?
This is a form of security through obscurity - and it's bad security.
I use a random folder name with htaccess password and an SSL certificate. The password is a simple fallback, just in case someone clever (say the dude running the IT at the coffee shop) is able to get between your computer and the internet. The SSL encryption is necessary since htaccess passwords are not encrypted.
Whatever you do, make sure you don't have a link anywhere to your page.
I'd say it takes less effort to say, just kick on HTTP authentication in apache than it is to remember some 32+ character gibberish domain name.
Right now I'm building a personal site/blog and have pretty much got it they way I want except I'm in two minds about how to add posts to it.
It's just me who'll be adding posts and to me having a user / name password to log in seems rather passé ;).
I'm looking in to alternatives to play around and experiment with and one idea I have is this:
Generate an asymmetric key, I personally keep the private and the site has the public key. When I try to add a post or modify any content the site will generate a random string, encrypt it with the public key and display it. I decrypt this using a little app I could whip together and pass the unencrypted string back to the site which will allow the modification to continue.
I'm just wondering about any caveats I should be on the look out for, or if anyone thinks this is a bad idea, perhaps an alternative I could try?
Why not just have a user name and password and either have your web browser remember the login, or send an authentication cookie back that doesn't expire. Use a self signed SSL cert to secure the communications channel. If you want to use public/private key crypto just setup an SSH tunnel and post from localhost on your server. Trust me, it's better to re-use known good crypto/security than to try to roll your own.
Why not go one stage further from your suggestion and put the encrypted string in to the URL?
For example, turn the current date and time into a string - eg. 0904240905 - encrypt it with your private key and add this to a URL, e.g. http://yoursite.com/admin/dksjfh4d392s where dksjfh4d392s is the encrypted string. You site then has a servlet which extracts the encrypted string from the URL, verifies that it decrypts to a recent time and then gives you a session cookie while allows you to perform admin tasks.
I think the asymmetric key is an elegant solution - but a username/password is almost certainly going to be easier to implement.
If you're building your own site then you are just doing it for kicks (otherwise you'd be using WordPress, Drupal, Django, etc.) so why not do things differently?
You might find that having to carry around your keymat app might get a little restrictive, if you find yourself wanting to blog but without the means to identify yourself.
But, that said, #Kurt has the right idea for crypto - DIY is almost certainly going to be worse than using something already tried and tested.
One of the wisest statements I ever heard about security was "don't try and re-invent it".
Online security has been through so many iterations that it's highly likely that any bright idea you come up with has some flaw that has previously been found, considered and fixed.
If you want "casual" security, secure your site with a user name and password. If you want "strong" security, stick an SSL certificate on top of it. If you want "bank" security, add in anti-keystroke security.
SSL client certificates do this anyway. Why not just use one of those?
The main reason more people don't use SSL client certificates is that they're an administrative nightmare - you have to get end-users to create keys, then sign their certificates, then make sure the end-users don't lose their keys (when they lose their laptop, upgrade to a new OS etc), which they usually do, so you have to sign YET MORE certificates when the end-users lose their private keys.