How do I make passwords more secure, my current code is:
<?php
if(!empty($_POST['userPass']))
#secure pass
$newRequesterPass = mysql_real_escape_string($_POST['userPass']);
$static_salt = 'M0AaE|}{<}|{&*#^AhEQ';
$dynamic_salt = mt_rand();
$newRequesterPass = sha1($dynamic_salt . $newRequesterPass . $static_salt);
?>
Is there a way to make this more secure, without sacrificing a ton of resources?
Like through SHA512, or another method?
You can change the algorithm to use SHA512 or Blowfish.
See http://php.net/manual/en/function.crypt.php
You could also look at generating a unique salt per user when they create their account (or update their password), which would limit the risk to a single account if the salt is discovered.
Using hash_hmac is better than plain hashing (md5/sha etc).
http://php.net/manual/en/function.hash-hmac.php
Although I dont understand your use of $dynamic_salt. If you generate a new salt each time, how is it going to match up with the password in the database.
..
Ok, so if the dynamic salt is stored per user....
$newRequesterPass = hash_hmac('sha256', $newRequesterPass, $dynamic_salt.$static_salt);
In addition to the excellent suggestion to use a stronger hash, secure password management involves management code that does more than store the password in salted+hashed form. How much of this you do depends on the business needs of your application, but consider the following:
Password validation -- you may want to enforce certain characters (e.g. letter + number, upper + lower case, etc.
Multiple hashes -- e.g. hash the password 1000 times -- OK this may violate your "not a lot of resources" condition :)
Expiration -- Passwords should be set to expire at some time (e.g. 1 year), so that you want to warn your users to change their password before then (e.g. 10 months) right after they successfully login.
Channel handling -- obviously the password should be sent via an SSL channel and not in the clear. Do not rely on client javascript to secure the password. But you should do more than just POST the password via https, the entire login sequence needs to be conducted in https.
Forgot password policy. Do not send them the password in the clear via email. Send them a link to reset their password and use an offline confirmation channel (e.g. send a follow up email notifying them that their password has been changed).
Take a look here https://www.owasp.org/index.php/Forgot_Password_Cheat_Sheet
UPDATE: Just to be clear, don't try to roll your own tools for session management or password hashing. Use the standard tools unless you are a real expert.
What you've goth there, is just "security by obscurity" - a very complicated way of creating a password hash.
If you are at all bothered about people compromising your database and cracking the hashes, you should use bcrypt.
If you're not, then use something standard (md5 is popular) - this provides only superficial protection against cracking.
Note that someone would need to compromise your database to be able to do dictionary or brute-force attacks in this way.
I strongly recommend that you don't "invent" cryptographic algorithms yourself, it is very difficult to get them right (or at least, make them secure).
md5() - Calculate the md5 hash of a string
hash() - Generate a hash value (message digest)
uniqid() - Generate a unique ID
Added :
sha1() — Calculate the sha1 hash of a string
Just see http://php.net/manual/en/function.crypt.php
Related
I have read in many articles that we should combine an unique salt to each passwords before hashing and store the salt in database for verification but How about using the password itself as an salt ?
Doing this will benefit as the salt will be unique for each as well as it will be hidden as it will be stored no where.
An simple example I can give for above is:
$hashToStore=sha1(strrev($password).$password);
Above I am just reversing the password and using it as an salt (I will be doing something more complex then just reversing it in development.)
Is This an better way for storing passwords or will be a bad practice.
PS:I am completely aware of php latest inbuilt functions such as crypt() and use it in real world, but yet wanted an review for above.
A common mistake is to use the same salt in each hash. Either the salt is hard-coded into the program, or is generated randomly once. This is ineffective because if two users have the same password, they'll still have the same hash. An attacker can still use a reverse lookup table attack to run a dictionary attack on every hash at the same time. They just have to apply the salt to each password guess before they hash it. If the salt is hard-coded into a popular product, lookup tables and rainbow tables can be built for that salt, to make it easier to crack hashes generated by the product.
A new random salt must be generated each time a user creates an account or changes their password.
[…] It's easy to get carried away and try to combine different hash functions, hoping that the result will be more secure. In practice, though, there is very little benefit to doing it. All it does is create interoperability problems, and can sometimes even make the hashes less secure. Never try to invent your own crypto, always use a standard that has been designed by experts. Some will argue that using multiple hash functions makes the process of computing the hash slower, so cracking is slower, but there's a better way to make the cracking process slower as we'll see later.
Here are some examples of poor wacky hash functions I've seen suggested in forums on the internet.
md5(sha1(password))
md5(md5(salt) + md5(password))
sha1(sha1(password))
sha1(str_rot13(password + salt))
md5(sha1(md5(md5(password) + sha1(password)) + md5(password)))
Do not use any of these.
Salt should be generated using a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). CSPRNGs are very different than ordinary pseudo-random number generators, like the "C" language's rand() function. As the name suggests, CSPRNGs are designed to be cryptographically secure, meaning they provide a high level of randomness and are completely unpredictable. We don't want our salts to be predictable, so we must use a CSPRNG. The following table lists some CSPRNGs that exist for some popular programming platforms. (PHP: mcrypt_create_iv, openssl_random_pseudo_bytes)
The salt needs to be unique per-user per-password. Every time a user creates an account or changes their password, the password should be hashed using a new random salt. Never reuse a salt. The salt also needs to be long, so that there are many possible salts. As a rule of thumb, make your salt is at least as long as the hash function's output. The salt should be stored in the user account table alongside the hash.
To Store a Password
Generate a long random salt using a CSPRNG.
Prepend the salt to the password and hash it with a standard cryptographic hash function such as SHA256.
Save both the salt and the hash in the user's database record.
To Validate a Password
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same hash function.
Compare the hash of the given password with the hash from the database. If they match, the password is correct. Otherwise, the password is incorrect.
At the bottom of this page, there are implementations of salted password hashing in PHP, C#, Java, and Ruby.
In a Web Application, always hash on the server
If you are writing a web application, you might wonder where to hash. Should the password be hashed in the user's browser with JavaScript, or should it be sent to the server "in the clear" and hashed there?
Even if you are hashing the user's passwords in JavaScript, you still have to hash the hashes on the server. Consider a website that hashes users' passwords in the user's browser without hashing the hashes on the server. To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not.
The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password! So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords.
This isn't to say that you shouldn't hash in the browser, but if you do, you absolutely have to hash on the server too. Hashing in the browser is certainly a good idea, but consider the following points for your implementation:
Client-side password hashing is not a substitute for HTTPS (SSL/TLS). If the connection between the browser and the server is insecure, a man-in-the-middle can modify the JavaScript code as it is downloaded to remove the hashing functionality and get the user's password.
Some web browsers don't support JavaScript, and some users disable JavaScript in their browser. So for maximum compatibility, your app should detect whether or not the browser supports JavaScript and emulate the client-side hash on the server if it doesn't.
You need to salt the client-side hashes too. The obvious solution is to make the client-side script ask the server for the user's salt. Don't do that, because it lets the bad guys check if a username is valid without knowing the password. Since you're hashing and salting (with a good salt) on the server too, it's OK to use the username (or email) concatenated with a site-specific string (e.g. domain name) as the client-side salt.
source: https://crackstation.net/hashing-security.htm
So, to answer your question, bad idea, very bad idea.
Please, don't ever do this. The whole point of salting is that every persons password hash will be unique which removed the issues of rainbow tables and giving away who has the same password.
Why does that matter? Look at the LinkedIn hack where they had "password hints". People has hints like "rhymes with assword" which gave away what their password, and also their hash was. It also gave away EVERYONE ELSE who was using the same password.
I'm knowing this site http://www.openwall.com/phpass/, but idea is on salt on mainly system.
Example, ZEND use system('uname -a') and it's hashed to md5() for using ROW LEVEL user SALT encryption. This is combination of user password, user login name/email address and server name as sha1/md5/...
But, my idea is generate DYNAMIC SALT instead STATIC SALT such as system('uname -a'). Example, every time when user is logged in, SALT has been changed but not user password.
For more security reasons, i'm needing dynamicaly changes salt on database or external file on daily basis or using third-party such as checking data from another server for salting?
What are best method for securing user sensible data on users database table and currents login. Cookie also is very bad secure options for me. It's must works such as PayPal API Tokenize and user id...
I'm using current:
salt from every user
salt from system hashed
hashed combination of user password, user salt and system salt
SHA-512 crypt() or bcrpyt() class
dynamically salt ? idea?
You are doing it wrong.
I think you are missing a key fact about re-hashing the password. To do it, you would have to store it in a recoverable form. Thus, creating even greater security risk, if system is compromised.
Here is what i would do:
make passwords expire in 60 days (or, you can choose some other number, just not too often).
each time user sets new password, you generate a random salt
build hash with crypt(), using CRYPT_SHA512 or CRYPT_BLOWFISH hashing algorithms
set a bit higher amount of rounds .. 20'000 should be enough
store the whole result that crypt() returns in the hash field in db.
Also you might benefit for reading: Properly Salting Passwords, The Case Against Pepper.
Changing the salt doesn't improve anything.
The point is: you always need to store salt and hash together somewhere because when you compare the password input with the hash you need to hash the input - obvious, right?
So this is the point: even if you change the salt after every login and do some weird re-hashing of the password it changes nothing because as soon as an attacker gets the database he has both hash and salt (if it's stored there together, which is necessary if you always use a different salt for each user which is something you should do).
A far more better way is extending the hashing by using 1000-10000 rounds of hashing as well as a long salt (you can easy use 512 bytes for the salt). These are better tip's than doing some re-hashing.
But anyway: if you really want to improve your PHP application you should focus on avoiding security issues like SQL injection, XSS, CSRF, RFI, LFI, file disclosure, RCE, etc - if an attacker gets access to the server he can simply backdoor the login script to send him an e-mail containing the plaintext credentials every time someone tries to login. (Well, you can also avoid this if you use a challenge-response authentication implemented in javascript like CRAM-MD5 http://en.wikipedia.org/wiki/Challenge-response_authentication or using RSA (also implemented in JS) to securely send login data).
Salt is only used to prevent against precomputation attacks, such as Rainbow Tables. Thus if someone wants to bruteforce the hashes, they actually have to compute them one at a time at runtime. (and not merely do a lookup in a database of pre-computed hashed values)
It's not really clear what the problem is that you're trying to solve. You just say:
"For more security reasons, i'm needing dynamicaly changes salt"
If that problem is precomputation attacks, then just have a normal salt. If it is not a precomputation attack, then salt is almost surely the wrong solution.
I have some doubts about the best way to do a database with passwords. I need encryption in the passwords, but if i use MD5 i can't recover the pass, isn't it?
And the base64 encoder ? it is secure? with this encryption the recover isn't more a problem.
Suggestions? what is the best way? e prefer a solution that permit to remember the old pass, and not define a new one password.
Thanks!!!
If anybody know a good tutorial about secure passwords in a database i really appreciate that
if i use MD5 i can't recover the pass,
isn't it?
Indeed, if you hash your password using md5 or sha1 (adding a salt is a good idea, btw), you will not be able to recover the password ; and that's the goal of doing so !
The idea is if anyone is able to take a look at your database (be it some evil doer, or one of your employees -- who can be an evil-doer), he will not be able to find any usefull password.
what is the best way? e prefer a solution that permit to
remember the old pass, and not define
a new one password.
The best way is to do the opposite of what you want : not allow one to get his old password -- and develop some way of generating a new password.
This way, you will ensure that no-one is able to get a dump of your logins and corresponding password ; which will make your service safer for your users (especially considering that many people use the same login/password couple of several websites).
MD5 is not used for encryption (which implies that it can be decrypted) but rather for message digestion/hashing. Base64 is also not encryption but rather encoding, which can be decoded with no effort.
There is usually little point in storing encrypted passwords in a database if they can be easily decrypted.
The secure approach is to store only hashes and compare submitted passwords to stored hashes after hashing them on the fly.
You should be doing something along the lines of:
$salt = 'some2%string!!here1';
$hash = sha1( $salt . $_POST['password'] );
to create a hash of the password. You store that hash in the database. When a user wants to log in, you take his submitted function, hash it using the same process, and compare to the hash in the database. If they match, the password is correct.
First off, there's a Significant Difference Between Hashing and Encryption. I suggest that you give that a read before going on...
Now, as to your exact question, there are a few ways to go about it.
Encrypt your passwords with a strong cipher so that you can decrypt them when necessary. A solution such as the one in this post may work for that. However, please note that this isn't a great idea, since if your system is ever compromised, all the passwords will be leaked (never a good idea). There are very few use-cases where it makes sense to store them encrypted, but if you absolutely must, please use a strong cryptographic encryption routine to do it...
Store your passwords using a strong one-way hashing method. No, md5($password) is not good enough. But neither is sha1($salt . $password). The first is trivial to lookup most passwords, and the second can be brute-forced in a reasonable amount of time by simple trial and error. Instead, stretch your passwords iteratively. The best way is to use the standard PBKDF2 function to generate a strong one-way key from the password.
As far as how to recover if the user forgets a password, don't worry about it. If the user forgets his password, create a new one and give that one to the user. It's the industry standard way of dealing with forgotten passwords (Heck, both Windows and Mac do it that way). You may think that you're doing your users a favor by sending it to them, but all you're doing is turning off anyone who has a clue about security from every using your application (and making a lot of people mad if you get compromised).
base64 isn't "encryption". It's intended to convert binary data into a format that's safe for transmission through potentially "broken" email systems that can't process 8-bit binary data properly. It's a best the equivalent of a cereal box decoder ring.
If you want encryption, there's AES, DES, and various other functions available. Problem is, if your code can decrypt the password, the it's trivial for an attacker to figure out how you do it, and/or subvert your code to do it for them.
Passwords should never be stored in a format where the plaintext can be retrieved. If a user forgets their password, you wipe out the old one, generate a new temporary one, and force them to change this temporary password to something else on first login.
You should not ever need to remember the user's password - to do so is a violation of their trust and presents a security hole.
Normally you will hash the password with MD5 (these days it's better to use SHA-2), and when the user submits their password to try and log in, hash that password as well, and see if the hashes are a match.
For added security, you can create a "salt" column to the database and generate a random salt when the password is first submitted. Add the salt to the beginning of the password, and then hash it. Store the hash of the salt+password, and the salt together. Now when the user submits his password to log in, you would combine it with the salt, hash it, and check if the hash is a match.
The salt ensures that if multiple users have the same password (chances are they do), their password hashes will not be identical.
If the user forgets their password they will have to provide a new one, simply storing their password and sending it back to them when they forget is bad practice and a sign to the user that you aren't handling their privacy very well.
As mentioned, use a hash instead of encryption when saving passwords. I generally don't use a random salt since this means an extra field in the DB so that you can authenticate the user. The simplest solution is to use the password as the salt as shown below. Easy to use and easy to authenticate.
$salt = $_POST['password'];
$hash = sha1( $salt . $_POST['password'] );
Stop now and read this. Then go find an open source library to do user authentication. I'm not a PHP dev, so I can't refer you to one, but I'm sure they exist. They'll have had the security holes found already.
Also, for passwords, you should be looking at bcrypt or similarly slow hash functions for passwords anyways, instead of using a fast hash algorithm like MD5 or SHA.
I have a list of students that are being added via a form inside the admin area. I'm trying to come up with a password generating solution for each addition that will be both secure and viewable from the admin panel (like below).
I need it to be viewable so that the admin will be able to print out the passwords and hand them out to the parents. But I also want them to be secure in case there's a database breach. Any ideas?
If you want the passwords to be viewable, they can never be really secure in case of a breach.
You may be interested in checking out the following Stack Overflow posts for further reading:
Difference between Hashing a Password and Encrypting it
How should I ethically approach user password storage for later plaintext retrieval?
Store passwords in 2 forms:
1) MF5/SHA1 hash for secure validation
2) AES encripted with master password. I.e. in order to view passwords you enter master password and bingo. In case of theft attacker would not get passwords that easy (but can bruteforce).
This is one of the few times I would say the software shouldn't be adjusted to the user(s). You're talking a major security risk here.
I would advice making some kind report generator to print passwords that creates (generates / salts and hashes and saves) them on the fly for printing. With this, you could generate the letters to be send as well. Makes the process mostly automated and a person would only have to send them to the printer (if that's even necessary).
Good luck.
You should not do this.
Generate a one-time password that can be used (and could also be stored in clear text) to set a new password via web.
As soon as the passwords are printed, they can be easily accessed by others, so it does not matter at all if you store them encrypted or not.
You can have one XOR the other.
If the passwords are to be secure, you mustn't store them in the database (store some_hash(per_user_salt + password) and compare that on login (as #Daniel Vassallo says)
If the passwords are to be viewable, then you must provide some way to get to the passwords - and if there is one, it can be abused (e.g. passwords stolen). If you decide that you absolutely, positively need to do this, encrypt the passwords in your application before storing them to the database. This won't shield you from all threats, but at least the passwords won't be readable if someone "only" steals your database.
Others have had the right idea, but were missing an essential step. You should use asymmetric encryption and store a public-key encrypted form of the password + salt.
To verify a password, take the proffered password, combine it with the salt, use the public key to encrypt the combination, and compare it with the stored value.
To retrieve the password, use the private key (kept secure, i.e. on another isolated machine) to decrypt the password + salt and throw away the salt.
Cons: asymmetric encryption can be expensive, computationally, but passwords tend to be short.
You could combine this with other ideas above (i.e. also store a salted hash), and you should pad the password so that the length of the encrypted text doesn't leak the password length.
For a login system in php would this be a suitable outline of how it would work:
users types in username and password, clicks login button.
Checks if user exists in database,
if it does, then retrieve the salt
for that user
hash the password and
salt (would this be done on the
client or server side? I think
client side would be better, but php
is server side so how would you do
this?)
check value against value in
database,
if the values match then
user has typed in correct password
and they are logged in.
Checks if user exists in database, if it does then retrieve the salt for that user hash the password and salt
No. This means you are hitting your database twice.
hash the password and salt (would this be done on the client or server side? I think client side would be better
No. The point of hashing the password is so that if someone compromises your database, they can't (easily) find out what they need to send to your system (or other systems) to log in as that user.
If you hash the password before sending it to the server, then the attacker can bypass the JS and send the prehashed password read from the database to your system.
User submits username and password
Password is hashed with the standard salt for the system
SELECT some,cols FROM your_users WHERE username=? and password=?
Count the number of rows returned from the database.
Checks if user exists in database, if it does then retrieve the salt for that user hash the password and salt (would this be done on the client or server side? I think client side would be better, but php is server side so how would you do this?)
The important thing to remember is that you never ever trust the user which means where authentication is concerned you should do as much as possible on the server side. Give the user as little information as possible and don't trust them with anything.
In regards to your question, the obvious point is that there is far more data transfer involved if you let the user precompute the hash. Rather than the single request and response there are 3 requests and responses required. It also increases the requirements from a browser to a browser with JavaScript enabled. Depending on your audience a lot of users can have JavaScript disabled (usually via the NoScript plugin).
Regarding security, while allowing the the user to see the salt wouldn't effect the defense against rainbow tables, showing them how you combine the salt and the password does.
Brute force attempts through the web interface are not that much of an issue anyway as hopefully you would only allow 5 (or so) login attempts per username per hour. Knowing the salt and hashing algorithm doesn't help at all (It just reduces your sever load ;) ). However if they have the database and know how to combine the salt and the hash it becomes that much easier to do a brute force attack.
While security through obscurity is no real defence, it does make your system that much harder to break, so I would reccomend that you don't attempt to do hashing on the client side.
It has to be Server Side
You are on the right track, but let me help you improve your system.
Generate a strong random key and store it in a file above your document root:
/home/username/key
/home/username/public_html/login.php
The file should contain (pseudo) random binary data with as much strength as possible. 512-bits of random data should be quite okay.
Then generate a unique salt for each user in your system. This salt does not have to be stronger than 16-bits of random binary data.
Finally, the password hashes should be something like:
hash('sha256', $password . $salt . $key);
where the hash algorithm matters a lot. Do not use MD5 or SHA-1. Use the SHA-2 family, typically SHA-256 or SHA-512. Also, Whirlpool is a good choice.
If you want to improve your system even more, you could iteratively hash again and again like:
public static function hash($algorithm, $data, $iterations = 1, $rawOutput = false)
{
if ($iterations < 1)
throw new Exception('There must be at least one iteration.');
while ($iterations--)
{
$data = hash($algorithm, $data, true);
}
return ($rawOutput ? (binary) $data : bin2hex($data));
}
Why such many moves?
Check if user exists in database, with given salted hashed password
if it does, then retrieve the user information
that's all
If you're talking of secure password transfer from client to the server - that's another story, you can refer to the HTTP digest authorization description for the schema. In short, it's client-side password hashing using random one-time token stored on the server side. OR SSL, of course
Most, if not all the form validation should be done on the server side. The users will be able to look at all client-side code and having any verification across a database done on the client-side will have massive security issues.
There might be different ways of approaching what you are trying to do. Here is what I would do:
Start a session if you want the user to be redirected somewhere and you need the username for that page
The general syntax for hashing in PHP is hash('nameOfHashFunction', $pswrd . $salt); you can cross verify this with the hash you have stored for the particular user.
The latest member of the SHA family is SHA-3, it was released in 2015. You can read more about it on its Wikipedia page. If there is a new member to the SHA family when you are reading this, I'd highly recommend you give it a light read and use that instead.
https://en.wikipedia.org/wiki/SHA-2
https://en.wikipedia.org/wiki/SHA-3