I came across a table the other day on our enterprise system -- dba_users (oracle).
I was able to find a hashed password in this table for each employee, and also their username.
As far as I know (from googling) the username + password is concatenated, then hashed.
Question: knowing the "salt" (my own username), the "original value" (my own password), and also the hashed value...is there a danger here of being able to figure-out the hash?
Also -- googling oracle 10g hash -- seems like some folks think they've figured the hash algorythm out. And I've read about "rainbow tables" and "offline dictionary attacks"... And finally, I've googled oracle 11g, and one of the features in that version is they hide the hashed password in dba_users so end-users can't see it.
Anyway, I'm scratching my head over why I (i.e., end-users) have access to this table, and why the DBA dosen't seem too worried about it.
The whole point of hashing the password and then storing the hash to database is that if you do so you won't have to worry about who can see the password in the table.
To emphasize: a (properly calculated) hash value of a password which is stored in database is completely useless without the original.
As far as I know, for algorithms like md5, there isn't a way to reverse engineer the original password from hash whatsoever. That's why most services nowadays don't send you your password when you click 'I forgot' link - instead they offer to set a new one (as soon as you provide the old password and the service compares hashes).
Elaborating on what #Goran Jovic said, by concatenating (ie salting) each hashed password with the username.There is no danger in making this available. To make sense of this, you have to understand how a rainbow table work. The way a series of passwords is cracked with a rainbow table is by loading up a precomputed series of hashes from passwords into memory. Then, searching through the table of hashes associated unknown passwords to see if you can find a match in the rainbow table (of which you know the password corresponding with a specific hash). By salting the hashes with a unique identifier (ie a username), however, you defeat this attack because even a password that's already been seen will hash differently depending n the user associated with it. Therefore now, instead of a rainbow table having to handle the millions of different password combinations possible, it must now contain a hash of every possible password plus every possible username. The results space of this is simply too large to search and unless there was a quantum leap in computing technology impossible to beat using a bruteforce tactic.
Related
I have a user table with a password column that uses md5 hash. Over time, some of its hashes were changed to plain text (users asked for immediate password change, without using the method that would apply hash).
I have modest amount of data, i will do it by hand, but i want to know: there's something along the lines of
select * from TableName where Column is not hashed
or
update from TableName
set Column = md5(current value)
where Column is not hashed
or something like that?
As noted previously, the use of MD5 for hashing private credentials or otherwise use within the process of authentication and authorization is officially highly discouraged.
However, your best chance to detect whether a field stores an MD5 value or a non-hashed value and convert it on-the-fly is something like the following:
UPDATE TableName
SET Column = md5(Column)
WHERE Column !~ '^[a-f0-9]{32}$'
There might be remaining ones in case someone really clever guy generated an MD5 hash of something and used that directly as a password. That will not be detectable but authentication must fail on such a case as the stored value would not match the MD5 hash of the entered password at login.
You should also not think about transferring plain-text passwords down to the database for hashing and comparison as the attack surface really is pretty high already. Even if you use decent TLS for your database connections who guarantees you that an administrator or attacker hasn't enabled logging slow statements with parameters directly at the database?
Instead, the application should use a library to generate a salt and salt-hashed password directly and only transfer the salt and hash to the storage. The format specified by crypt is industry accepted (and therefore highly recommended), there are solid libraries for any programming language available and once a certain algorithm becomes deprecated, you can incrementally change it without a coordinated one-shot upgrade.
I have a database with roughly 4,000 members. I need to decrypt all their passwords so that I may re-encrypt them using MD5 and put into a new system. I have one account with before encryption and after encryption password strings so with this I assume I should be able to figure out a method and key range. I do not have access to the original source code or I would not be here.
I should mention that existing passwords vary dramatically.
User1 - qwDyP1db9iOPI
User2 - $1$.WXtDyLg$yxBPAWxzd.srEWJZfqZAY/
User3 - do8sLMoVVqxKQ
User4 - TKmnAlPe
How do I approach such a problem?
Typically, you can't decrypt the passwords, because the passwords are not stored. What you are seeing is hashes of the password - there's no efficient way to find a password that matches a particular hash.
You can either force everyone to change their password once you have the configuration changed to use MD5 hashing, or you can generate new temporary passwords for everyone to get all the hashes replaced at once, but then they should all change them again anyway.
Those look like they probably came from Linux (the one that starts with $1$ is already an MD5 hash, the others look like the older crypt() DES variant style).
That's not always the case when dealing with application passwords - for example, some databases use considerably weaker credential storage - but Unix/Linux flavors have not stored actual passwords for a very long time, if ever.
let's think. Suppose I can hack my way to your computer / DB (not an impossible task). So I have what you have - a list of all users' passwords, but encrypted. But most probably I can register to your system myself, and I know my own password. I can find its encrypted form in the DB, either by my username, or by the latest entry, so now I have the clear + encrypted pair! If I could do what you are asking, I'd have all passwords and full access to all accounts. Meaning that encrypting passwords, or data in general has virtually no additional security effect, and all I should care about is preventing unauthorized access to the data. But this is not true, so you can't :)
BTW, MD5 is not an encryption but a hash, or more correctly a digest.
Looks like twalberg is right for the most part, but I'd like to go a step further to give you some practical advice:
1) Look at http://www.openwall.com/john/ (John the Ripper) for help getting the original passwords out of the database you have. Note that the passwords generated may not be the original passwords (it is likely, but not certain).
Once you've gotten all of the passwords using this tool, think to yourself: Anyone could do this. Your users might use these passwords somewhere else. If someone broke into your site, they could expose the people who trust you. Your users could blame you if someone used this information to break into their other accounts. Having the cleartext passwords around is risky for you.
I recommend you take this opportunity to have your users change their passwords. Those that no longer use their accounts should probably have to go through a small verification step to regain access, so you can disable their accounts now.
2) When you generate the new password database, I recommend you at a minimum use a secure hash (E.g. SHA1 or SHA2) along with a per-user salt (random value prepended to the generated hash output in a standard way) to help secure the database from accidental exposure.
While this answer isn't efficient, it is probably practical for the most part for your current database if your actual password database has even approximately the proportions you represent.
If you're switching away from your current system don't switch to plain MD5 - there are "rainbow tables" to crack a lot of common passwords; instead use salted/double MD5 or SHA
Thanks all for your input. I will just have everyone change their passwords. I have no intention of keeping anyone's password. The goal was to not have all 4000 users have to change their passwords after migrating to the new system but it seems unavoidable. As davka pointed out, I have an account in this database and know my password and can see the encrypted version so thought that would be sufficient to develop a script that decrypts and renters the password into the new database. Thanks again.
I am having difficulty understanding how a salt which is appended to a hash helps improve the security when a database of passwords or other important information is compromised.
If the salt is, for example, "hello", and is appended to the password "password" then the salt and password are stored together, "hellopassword" and hashed to produce:
94e66f94517d606d5ad6d9191b980408952f2ed2 (sha1)
with the salt then appended:
hello$94e66f94517d606d5ad6d9191b980408952f2ed2
How is this more secure? The attacker knows the salt so can now compute the passwords with little extra difficulty... right? Or am I fundamentally misunderstanding something?
No, not with "little extra difficulty" - with potentially significantly more difficulty.
Imagine there are two billion common passwords. It's easy to hash all of those and store the results. Then if you have an unsalted password hash, you can just check which common passwords match the given hash.
Now compare that with a salted hash... now you have two billion common passwords, but also several billion possible salts. Computing all the possible salt/password combinations will take much, much longer - hopefully becoming infeasible.
Additionally, it means that even if two people have the same password, they are very likely to have different hashes - so carelessness of one user in revealing their password doesn't risk the security of the other.
See the Wikipedia entry (if you haven't already) for more on this.
salt helps in 2 ways:
1) When two (or more) people use the same password, without salt you can see who uses the same password (the hashes are all the same). So in theory, if that person knows one of those person's passwords he knows everyone's passwords with the same hash. This is a minor reason.
2) The main reason is to prevent attacks commonly called dictionary attacks or rainbow attacks. In these attacks someone uses a database of pre-calculated hashes for common passwords. Often times these databases are gigs in size. But it is very easy at that point to just do a lookup for the hashes you have (the hashed password) against the list of pre-calculated hashes and see what the associated password is.
By using a salt value (typically you want this to be a random number) the hash won't match the dictionary (the chance of them pre-calculating all passwords with all possible salt values is exponentially more difficult). So even if your user uses an easily attacked password, say "Password", which is pretty much guaranteed to be any in any password dictionary/rainbow table, by pre-pending your random salt value you make the hash pretty much guaranteed to be useless to the attacker. Meanwhile for you, since the salt is just stored in cleartext, it makes it very easy for you to add it to your cleartext for your comparison of the password the user entered.
The salt isn't appended to the hash, its appended to the password THEN hashed. This is more secure because hackers have to know the salt and the actual password, which you should both protect heavily. :D
In a web application written in Perl and using PostgreSQL the users have username and password. What would be the recommended way to store the passwords?
Encrypting them using the crypt() function of Perl and a random salt? That would limit the useful length of passswords to 8 characters and will require fetching the stored password in order to compare to the one given by the user when authenticating (to fetch the salt that was attached to it).
Is there a built-in way in PostgreSQL to do this?
Should I use Digest::MD5?
Don't use SHA1 or SHA256, as most other people are suggesting. Definitely don't use MD5.
SHA1/256 and MD5 are both designed to create checksums of files and strings (and other datatypes, if necessary). Because of this, they're designed to be as fast as possible, so that the checksum is quick to generate.
This fast speed makes it much easier to bruteforce passwords, as a well-written program easily can generate thousands of hashes every second.
Instead, use a slow algorithm that is specifically designed for passwords. They're designed to take a little bit longer to generate, with the upside being that bruteforce attacks become much harder. Because of this, the passwords will be much more secure.
You won't experience any significant performance disadvantages if you're only looking at encrypting individual passwords one at a time, which is the normal implementation of storing and checking passwords. It's only in bulk where the real difference is.
I personally like bcrypt. There should be a Perl version of it available, as a quick Google search yielded several possible matches.
MD5 is commonly used, but SHA1/SHA256 is better. Still not the best, but better.
The problem with all of these general-purpose hashing algorithms is that they're optimized to be fast. When you're hashing your passwords for storage, though, fast is just what you don't want - if you can hash the password in a microsecond, then that means an attacker can try a million passwords every second if they get their hands on your password database.
But you want to slow an attacker down as much as possible, don't you? Wouldn't it be better to use an algorithm which takes a tenth of a second to hash the password instead? A tenth of a second is still fast enough that users won't generally notice, but an attacker who has a copy of your database will only be able to make 10 attempts per second - it will take them 100,000 times longer to find a working set of login credentials. Every hour that it would take them at a microsecond per attempt becomes 11 years at a tenth of a second per attempt.
So, how do you accomplish this? Some folks fake it by running several rounds of MD5/SHA digesting, but the bcrypt algorithm is designed specifically to address this issue. I don't fully understand the math behind it, but I'm told that it's based on the creation of Blowfish frames, which is inherently slow (unlike MD5 operations which can be heavily streamlined on properly-configured hardware), and it has a tunable "cost" parameter so that, as Moore's Law advances, all you need to do is adjust that "cost" to keep your password hashing just as slow in ten years as it is today.
I like bcrypt the best, with SHA2(256) a close second. I've never seen MD5 used for passwords but maybe some apps/libraries use that. Keep in mind that you should always use a salt as well. The salt itself should be completely unique for each user and, in my opinion, as long as possible. I would never, ever use just a hash against a string without a salt added to it. Mainly because I'm a bit paranoid and also so that it's a little more future-proof.
Having a delay before a user can try again and auto-lockouts (with auto-admin notifications) is a good idea as well.
The pgcrypto module in PostgreSQL has builtin suppotr for password hashing, that is pretty smart about storage, generation, multi-algorithm etc. See http://www.postgresql.org/docs/current/static/pgcrypto.html, the section on Password Hashing Functions. You can also see the pgcrypto section of http://www.hagander.net/talks/hidden%20gems%20of%20postgresql.pdf.
Use SHA1 or SHA256 hashing with salting. Thats the way to go for storing passwords.
If you don't use a password recovery mechanism (Not password reset) I think using a hashing mechanism is better than trying to encrypt the password. You can just check the hashes without any security risk. Even you don't know the password of the user.
I would suggest storing it as a salted md5 hash.
INSERT INTO user (password) VALUES (md5('some_salt'||'the_password'));
You could calculate the md5 hash in perl if you wish, it doesn't make much difference unless you are micro-optimizing.
You could also use sha1 as an alternative, but I'm unsure if Postgres has a native implementation of this.
I usually discourage the use of a dynamic random salt, as it is yet another field that must be stored in the database. Plus, if your tables were ever compromised, the salt becomes useless.
I always go with a one-time randomly generated salt and store this in the application source, or a config file.
Another benefit of using a md5 or sha1 hash for the password is you can define the password column as a fixed width CHAR(32) or CHAR(40) for md5 and sha1 respectively.
Ok, I’m trying to understand the reason to use salt.
When a user registers I generate a unique salt for him/her that I store in DB. Then I hash it and the password with SHA1. And when he/she is logging in I re-hash it with sha1($salt.$password).
But if someone hacks my database he can see the hashed password AND the salt.
Is that harder to crack than just hashing the password with out salt? I don’t understand …
Sorry if I’m stupid …
If you don't use a salt then an attacker can precompute a password<->hash database offline even before they've broken into your server. Adding a salt massively increases the size of that database, making it harder to perform such an attack.
Also, once they've broken in they can guess a commonly used password, hash it, and then check all of the passwords in the database for a match. With a different salt for each user, they can only attack one password at a time.
There's an article at Wikipedia about salts in cryptography.
Another intention behind the use of a salt is to make sure two users with the same password won't end up having the same hash in the users table (assuming their salt are not the same). However, the combination of a salt and a password may lead to the same "string" or hash in the end and the hash will be exactly the same, so make sure to use a combination of salt and password where two different combination won't lead to the same hash.
If an attacker creates a giant table of hash values for plaintext passwords, using a salt prevents him from using the same table to crack more than one password. The attacker would have to generate a separate table for each salt. Note that for this to actually work propertly, your salt should be rather long. Otherwise the attacker's precomputed table is likely to contain the salt+password hash anyway.