In ColdFusion, What is the best best of doing a user login password comparison with the database that will encrypt the password between the client and server?
I noticed there's a javascript version at http://pajhome.org.uk/crypt/md5/index.html
but what can be done for users without javascript enabled?
These points are not specific to coldfusion, but I feel I must state them:
Do the hash server-side.
The point of hashing is to make it really hard to figure out what to send the server in order to produce the string it matches with the DB. If you just match the string given by the client with the DB entry, you're defeating the purpose.
Don't use MD5.
It's broken. There are ways to defeat it. Don't use it.
If you're worried about the password being exposed on the way to the server, use TLS.
TLS is designed for making communications between a client and a server opaque to anyone else. The biggest problem with it is the recent BEAST attack, which won't work if you implement it right.
Use a secure hash like SHA-256.
As far as we know, SHA-256 is pretty damn secure. The best known attack on it reduces the time complexity by 2 bits, which doesn't make an attack practical.
Use a random salt, unique to each user.
A precomputed rainbow table for 2^50-bit space would take 256 petabytes of storage, and one for 2^256 space would take an enormous amount more. However, due to the Birthday Problem, it's conceivable that some of your users' accounts could be compromised if you do not salt their hashes.
Hash multiple times. On the order of thousands of times.
If your DB is compromised, a hash might mean that your average user's password is found in years. If you has thousands of times, that would mean thousands of years.
Some additional points, to address misconceptions it looks like you have:
A cryptographic hash is one-way. You can't decrypt it. If you find a practical way to decrypt it, then you will become rich and (in)famous.
Standard HTTP is not secure. Anyone can eavesdrop and intercept your password that is being POSTed in plaintext, or hashed. If your server doesn't demand an encrypted connection for sensitive data, you're asking for a replay attack (http://en.wikipedia.org/wiki/Replay_attack).
You can make your own SSL certificate. If you're worried about your users seeing "this SSL Cert is self signed! Oh noes!" and being scared off, either do without and take the risk, or cough up the cash.
Related
I am using encryptByKey() for SSN and Account Number encryption in Yii2. The problem is that it generates different encrypted data for the same Account Number when I try to re-generate it.
I can't match it in the database like the following:
Customers::findOne(['account_number'=> Yii::$app->getSecurity()->encryptByKey($account_number, "someKeyHere")]);
Is there any encryption method available to generate same encrypted data every time I encrypt it?
Thanks,
Generally, that's the way encryption is supposed to work. It is sometimes called "ciphertext indistinguishability." Yielding the same ciphertext every time a given plaintext is encrypted undermines security by allowing attackers to analyze collections of ciphertext for patterns.
In this case, it looks like you only store one instance of the encrypted account number; you could argue that because the "message" is never repeated, cipher text indistinguishability is moot. That could lead you to justify the use of ECB mode (if your API offered it) or a HMAC (message authentication code, offered by the hashData() method) to compute a lookup key. If an attacker gets access to your database, there will only be one instance of each key, and nothing is revealed.
However, this is still insecure if an attacker can provide account numbers that your system encrypts. For example, an attacker could pose a legitimate user and provide a SSN during registration. If they choose a duplicate number, and then look in the database, their maliciously chosen encrypted value will match a legitimate record. Or, if the system rejects their account number because it is a duplicate, the attacker will know that it is a number in use by a legitimate user. This is called an oracle attack.
If you use an HMAC (or ECB mode encryption), you would have to design your application very carefully to prevent chosen plaintext and oracle attacks. And, candidly, if you are now encountering these ideas for the first time, there are probably many other gaps in your knowledge that will lead to easily exploited vulnerabilities in your application.
The site I'm working on right now uses a third-party billing company that handles user sign-ups, so all user names and passwords are entered in the biller's site, then the biller writes the username and the user's now encrypted password to a 'members' database on our server.
The problem is that the biller (and many of them, from what I gather) encrypts the passwords with MD5 which I have read over and over is NOT secure. But, as the encryption is handled at the biller's end, and they are only offering MD5, I wanted to know if there was anything I could do on my end to make the passwords more secure?
As I'm writing this, I'm thinking that, 'If the biller is encrypting the passwords, there's probably no way for me to add more security' because part of the biller's job is to handle member issues such as lost passwords and other issues.
So...is there a way to add more security to the passwords the biller stores in our DB or do we just take our chances with what we all know is an unsafe standard? We're stuck with this biller for the short term, and what's worse, I contacted another biller who is very well known and they use MD5 as well.
Many thanks in advance!
Unfortunately, there's not a lot you can do about the biller at this stage. It's difficult to know what threats you're trying to mitigate against. If you're worried about the communication between the biller and your machines being monitored then SSL or SSH should help with that. If you're worried about an attacker breaking into your database and stealing passwords, then using a different scheme to store the passwords in will help.
You can either stick with MD5 and add a salt. Please check that your biller is salting their passwords, if they're not you really need to get rid of them. They're database will be vulnerable to rainbow table lookups.
A rainbow table is a precomputed table for reversing cryptographic hash functions, usually for cracking password hashes
You could take the MD5s you receive and use a better password hashing algorithm (assuming you don't need to keep the original MD5). One example is bcrypt. Note that SHA1, SHA-256, etc. whilst better hashing algorithms are not that great at password hashing. The reason is that SHA is designed to be fast. You want password hashing to be relatively slow. For legitimate users, waiting 20ms for a correct password validation is no time at all, but for an attacker it drastically reduces their ability to brute force a password.
bcrypt is a key derivation function for passwords designed by Niels Provos and David Mazières, based on the Blowfish cipher, and presented at USENIX in 1999.[1] 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.
Essentially, bcrypt has a good hashing algorithm, requires a salt and lets you specify the number of times the hashing algorithm is run on it. You could, for example, start off with 100 rounds. In two years time when computing power has increased you can then increase that to 150.
Md5 is technically a hasing algorithm, not an encryption algorithm. The difference being that you cannot unhash a a hashed string (in theory, md5 is weak because this was proven false). You can undo encrypting if you have the appropriate key.
What is your biggest concern? Are you worried about someone intercepting the passwords as they travel between you and the biller or are you worried about someone opening the database?
If you are worried about someone breaking into your database and getting your table with passwords, then you can definitely improve the security. You could encrypt the entries before you persist them using a modern algorithm with your own private key. Don't store the key with the server and unencrypt when pulling out of the database before using the md5 value.
You could also, just hash the md5 value they give you (and use a salt) with some modern strong hashing algorithm. This means that if anyone gets your table, they will have to unhash your hash, then unhash the md5. Presumably you would use a strong hash and the first step would be impossible. As always, be careful with security as you most certainly should write something yourself, you will have bugs!
So I would like to modify a PHP / MySQL application in order to store credit card but not cvv and bank account info securely. PCI DSS require 1024 RSA/DSA. A small number of users will be given private key in order to decrypt the batch file of account info for submission to payment processors monthly. I'm unclear if it is possible to have a system that would allow the users who have signed in with normal 8 digit passwords to modify their own account info securely. It seems that this is not possible, and the encryption should be one-way (ie each user -> admins; never allowing user to decrypt their own info again), with account info never exposed back to users even over SSL connections. Or is there a proper and easy way to do this that I'm unaware of that is PCI DSS compliant?
PCI DSS does not require 1024 bit RSA to encrypt. Older versions of the specification mentioned AES and 3DES by name, but I believe newer versions just specify strong encryption. Most people are using AES 256.
Encrypting data at-rest with an asymmetric algorithm doesn't really work. Symmetric algorithms work best. This allows the application to access the card data when it needs to. This doesn't mean you have to show the data to the user ever again, it just means the data is there when you need to get to it. If you're storing credit card authorization information, you'll usually need the card number for settlement. (It really depends on the features your processor has. Some of the small-business level processors store the card for you, but this is infeasible for large scale processors like Paymentech and FDMS.)
The problem is that you will have to rotate your encryption keys periodically. This is usually what screws everyone up. If you roll your own encryption, you need to make sure that you can specify n number of keys that are accessible for as long as there is data encrypted with those keys. At any point in time, only one of those keys should be used for encryption. Unless you have a deep understanding of crypto and key management in terms of PCI, you might want to go with a commercial offering. Yes, these are expensive, but you have to determine the best course with a build or buy decision making process.
Ingrian (now SafeNet) has a decent offering for a network HSM. It will manage the keys for you and do the cryptographic operations. It may also be possible to use their DB level encryption integration so that you don't have to change your application at all. (Though DB level encryption is dubiously secure in my opinion.)
This is a very deep subject; I've done a lot with PCI and suggest you hire someone to guide you through doing it properly. You'll spend a lot of money on false starts and redoing work, so get an auditor involved early to at least asses what you need and tell you how to implement the security properly.
You may have an easier time if you differentiate between data storage, access, and transmission.
Storage requires strong reversible encryption; the data is not useful unless you can retrieve it.
Access requires a user or process to authenticate itself before it is permitted to decrypt the data. Here's an example of a mechanism that would accomplish this:
Store the data with a secret key that is never directly exposed to any user. Of course, you'll need to store that key somewhere, and you must be able to retrieve it.
When each user chooses a password, use the password to encrypt a personal copy of the private key for that user. (Note: even though you're encrypting each copy of the key, security issues may arise from maintaining multiple copies of the same information.)
Do not store the user's password. Instead, hash it according to standard best practices (with salt, etc.) and store the hash.
When a user provides a password to log in, hash it and compare to your stored value. If they match, use the (plainitext) password to decrypt the key, which is then used to decrypt the actual data.
Transmit the data through a secure connection, such as SSL. It's reasonable (perhaps required) to allow users to access (and modify) their own data, as long as you continue to follow best practices.
Comments:
An 8-digit password implies a key space of 108 ~ 227 = 27 bits, which by today's standards is fairly terrible. If you can't encourage longer (or alphanumeric) passwords, you may want to consider additional layers.
One advantage to the multiple-layer strategy (user provides a password that is used to encrypt the "actual" key) is that you can change the encryption key transparently to the user, thereby satisfying any key-rotation requirements..
The standard admonition whenever you're designing a security solution is to remember that DIY security, even when following standards, is risky at best. You're almost always better off using an off-the-shelf package by a reputable vendor, or at least having a trained, certified security professional audit both your strategy and your implementation.
Good luck!
My coworker and I are having a fist-fight civilized discussion over password security. Please help us resolve our differences.
One of us takes the viewpoint that:
Storing passwords encrypted using a public key in addition to a one-way hashed version is OK and might be useful for integration with other authentication systems in the future in case of a merger or acquisition.
Only the CEO/CTO would have access to the private key, and it would only be used when necessary. Regular login validation would still occur via the hashed password.
I have/he has done this before in previous companies and there are many sites out there that do this and have survived security audits from Fortune 500 companies before.
This is a common, and accepted practice, even for financial institutions, thus there is no need to explicitly state this in the privacy policy.
Sites like Mint.com do this.
The other one of us takes the following viewpoint:
Storing passwords, even in encrypted form, is an unnecessary security risk and it's better to avoid exposure to this risk in the first place.
If the private key falls into the wrong hands, users that use the same password across multiple sites would risk having all of their logins compromised.
This is a breach of trust of our users, and if this practice is implemented, they should be explicitly informed of this.
This is not an industry-wide practice and no big name sites (Google, Yahoo, Amazon, etc.) implement this. Mint.com is a special case because they need to authenticate with other sites on your behalf. Additionally, they only store the passwords to your financial institutions, not your password to Mint.com itself.
This is a red flag in audits.
Thoughts? Comments? Have you worked at an organization that implemented this practice?
The first practice of storing recoverable version of passwords is plain wrong. Regardless of the fact that big sites do this. It is wrong. They are wrong.
I automatically distrust any site that stores my password unhashed. Who knows what would happen if the employees of that big company decide to have fun? There was a case some guy from Yahoo stole and sold user emails. What if someone steals/sells the whole database with my emails and passwords?
There is no need whatsoever for you to know my original password to perform authentication. Even if you decide later to split the system, add a new one or integrate with a third party, you still will be fine with just a hash of the password.
Why should CEOs be more reliable / trustworthy than other people? There are example of high-ranking government people who have lost confidential data.
There's no reason a regular site has to store a password, not a single one.
What happens if in the future those private keys can be broken? What if the key used is a weak key, as has happened just recently in Debian.
The bottom line is: Why would one take such great risks for little to no benefit. Most companies aren't ever going to need an encrypted password.
Hash Passwords
Storing passwords in a reversible form is unnecessary and risky.
In my opinion, a security breach seems much more likely than the need to merge password tables. Furthermore, the cost of a security breach seems far higher than the cost of implementing a migration strategy. I believe it would be much safer to hash passwords irreversibly.
Migration Strategy
In case of a company merger, the original algorithm used to hash passwords can be noted in a combined password table, and different routines called to verify the passwords of different users, determined by this identifier. If desired, the stored hash (and its identifier) can be updated at this time too, since the user's clear-text password will be available during the login operation. This would allow a gradual migration to a single hash algorithm. Note that passwords should expire after some time anyway, so this would be upper bound on the time migration would require.
Threats
There are a couple of avenues to attack encrypted passwords:
The decryption key custodian could be corrupt. They could decrypt the passwords and steal them. A custodian might do this on his own, or he could be bribed or blackmailed by someone else. An executive without special training is especially susceptible to social engineering too.
An attack can also be made on the public key used for encryption. By substituting the real public key with one of their own, any of the application administrators would be able to collect passwords. And if only the CEO has the real decryption key, this is unlikely to be discovered for a long time.
Mitigation
Supposing this battle is lost, and the passwords are encrypted, rather than hashed, I'd fight on for a couple of concessions:
At the very least, the decryption key should require the cooperation of multiple people for recover. A key sharing technique like Shamir's secret sharing algorithm would be useful.
Measures to protect the integrity of the encryption key are required too. Storage on a tamper-proof hardware token, or using a password-based MAC may help.
and might be useful for integration
with other authentication systems in
the future
If there is no immediate need to store the password in a reversable encrypted format, don't.
I'm working in a financial institution and here the deal is: no one should ever know user's password, so the default and implemented policy used everywhere is: one way hashed passwords with a strong hashing algorithm.
I for once stand in favor of this option: you do not want to go into the trouble of handling the situation where you have lost your two-way encryption password or someone stole it and could read the stored passwords.
If somebody loses their password you just change it and give it to them.
If a company needs to merge, they HAVE to keep hashed passwords the way they are: security is above everything else.
Think about it this way: would you store your home keys in a box that has a lock with a key you have, or would you better prefer to keep them with you everytime?
In the first case: everybody could access your home keys, given the proper key or power to break the box, in the second case to have your keys a potential home-breaker should threaten you or take them from you in some way... same with passwords, if they are hashed on a locked DB it is like nobody has a copy of them, therefore no one can access your data.
I have had to move user accounts between sites (as might happen in a merger or acquisition) when the passwords were one-way hashed and it was not a problem. So I do not understand this argument.
Even if the two applications used different hashing algorithms, there will be a simple way to handle the situation.
The argument in favor of storing them seems to be that it might simplify integration in the case of a merger or acquisition. Every other statement in that side of the argument is no more than a justification: either "this is why it's not so bad" or "other people are doing it".
How much is it worth to be able to do automatic conversions that a client may not want done in event of merger or acquisition? How often do you anticipate mergers and/or acquisitions? Why would it be all that difficult to use the hashed passwords as they are, or to ask your customers to explicitly go along with the changes?
It looks like a very thin reason to me.
On the other side, when you store passwords in recoverable form there's always a danger that they'll get out. If you don't, there isn't; you can't reveal what you don't know. This is a serious risk. The CEO/CTO might be careless or dishonest. There might be a flaw in the encryption. There would certainly be a backup of the private key somewhere, and that could get out.
In short, in order to even consider storing passwords in recoverable form, I'd want a good reason. I don't think potential convenience in implementing a conversion that might or might not be required by a possible business maneuver qualifies.
Or, to put it in a form that software people might understand, YAGNI.
I would agree that the safest way remains the one-way hash (but with a salt of course!). I'd only resort to encryption when I'd need to for integrating with other systems.
Even when you have a built system that is going to need integration with other systems, it's best to ask your users for that password before integrating. That way the user feels 'in control' of his own data. The other way around, starting with encrypted passwords while the use is not clear to the end-user, will raise a lot of questions when you start integrating at some point in time.
So I will definitely go with one-way hash, unless there is a clear reason (clear development-wise and clear to the end-user!) that the unencrypted password is immediately needed.
edit:
Even when integration with other systems is needed, storing recoverable passwords still isn't the best way. But that of course, depends on the system to integrate with.
Okay first of all, giving the CEO/CTO access to plaintext passwords is just plain stupid. If you are doing things right, there is no need for this. If a hacker break your site, what's stopping him from attacking the CEO next?
Both methods are wrong.
Comparing the hash of a received password against a stored hash means the user sends his plaintext password on every login, a backdoor in your webapp will obtain this. If the hacker does not have sufficient privileges to plant a backdoor, he will just break the hashes with his 10K GPU botnet. If the hashes cannot be broken, it means they have collisions, which means you have a weak hash, augmenting a blind brute force attack by magnitudes. I am not exaggerating, this happens every day, on sites with millions of users.
Letting users use plaintext passwords to login to your site means letting them user the same password on every site. This is what 99% of all public sites do today, it is a pathetic, malicious, anti-evolutionary practice.
The ideal solution is to use a combination of both SSL client certificates and server certificates. If you do this correctly, it will render the common MITM/Phishing attack impossible; an attack of such could not be used against the credentials OR the session. Furthermore, users are able to store their client certificates on cryptographic hardware such as smart cards, allowing them to login on any computer without the risk of losing their credentials (although they'd still be vulnerable to session hijacking).
You make think I'm being unreasonable, but SSL client certificates were invented for a reason...
Every time I have anything to do with passwords they are one way hashed, with a changing salt i.e. hash(userId + clearPassword). I am most happy when no one at our company can access passwords in the clear.
If you're a fringe case, like mint.com, yes, do it. Mint stores your passwords to several other sites (your bank, credit card, 401k, etc), and when you login to Mint, it goes to all of those other sites, logs in via script as you, and pulls back your updated financial data into one easy-to-see centralized site. Is it tinfoil-hat secure? Probably not. Do I love it? Yes.
If you're not a fringe case, lord no, you shouldn't ever be doing this. I work for a large financial institution, and this is certainly not at all an accepted practice. This would probably get me fired.
I have an ASP.Net web application where I would like to implement cryptography for password security. I am not using SSL.
For that i studied and pick CRAM-MD5 algorithm for password authentication. I have implement javascript cram-md5 algorthim available at http://pajhome.org.uk/crypt/md5/
Here i would like to know that is there anyone used it and face that CRAM-MD5 authentication is decoded by hackers?
What are the possiblities of decoding CRAM-MD5 authentication?
MD5 is no longer considered secure, see MD5 vulnerabilities. For a more secure implementation, choose a different hash algorithm (such as SHA-256 or better).
For sure MD5 is no longer considered secure but the cryptanalysis vulnerabilities affecting him does not affect HMAC-MD5. It's a whole different beast.
I do agree that CRAM-MD5 would not be the best recommendation but it really has nothing to do with the insecurity of MD5.
Learn what's the difference.
See http://www.openauthentication.org/pdfs/Attacks%20on%20SHA-1.pdf, https://www.rfc-editor.org/rfc/rfc6151 and http://cseweb.ucsd.edu/~mihir/papers/hmac-new.html
Contrary to what others are saying, CRAM-MD5 is standard and safe to use. It's widely used in SASL for IMAP/SMTP authentication. You might be reading your EMail using CRAM-MD5. The other standard hashing algorithms are HTTP Digest Authentication and CHAP used in PPP but they all uses MD5 due to historical reasons. You can choose more secure SHA1-based hash but you will have to roll your own challenge schemes.
Because it uses challenge/response scheme, it's less vulnerable to the weakness of the MD5 hash. Unless you have special security requirements, stay with one of the standard algorithms.
Don't self implement your hashing algorithm. There are well tested implementations in System.Security. As stated don't use MD5.
In addition you should salt your hashes. For example if you have a user table with a password field you can add a salt field that is simply an integer, or a guid, or even a timestamp, but something unique. The salt ensures you will not have hash collisions within your database. Here is a discussion on salting.
Implementing your own cryptography is generally seen as a bad idea.
Cryptographic algorithms have a lot of very specific demands, and if even one of them isn't met (and that usually happens when people do their own), it usually won't be all too much more secure than no crypto at all.
If you're not convinced, this Google Tech Talk should help.
From Wiki:
Protocol Weaknesses
- No mutual authentication; client does not verify server.
- Offline dictionary attack to recover password feasible after capturing a successful CRAM-MD5 protocol exchange.
- Use of MD5 insufficient.
- Carries server requirement for storage of reversibly encrypted passwords.
I'd be scared to use md5 hashing algorithm, as getting back the original password from hash can be done in few seconds, if password wasn't long enough (actually, you can google for md5 rainbow table, there are sites that will decode such hash in few seconds and give back the result ;) ).
As others have advised; don't use MD5, ever, for anything.
But as to an actual answer, how badly is it broken:
Well, with any one-hash it's, well, one-way, so you can't 'decode' it in that sense. What you can do, however, is generate collisions much faster than is acceptable. This allows the attackers to force matches in things that wouldn't otherwise match. It makes any validation of inference of the type 'md5(this) = md5(that) so this = that' wrong. This breaks digital signatures, and all sorts of other things.
Stay away from MD5, in any form.
-- Edit
Oh, and just a note, that hashing the password is no replacement for SSL. SSL is used to ensure, to the client, that the site they are browsing is yours, and to protect general sending of data.
Hashing is about protecting your database from a possible compromise. (And you always need to hash with a salt; you store the salt right next to the username in the db).