I'm currently planning the development of a PHP application that shall require user passwords for external services to be stored so that they can be logged into simultaneously when the user logs into my application.
I shall need to store passwords in a secure, i.e. not plain text, and not base64 encoded but that shall also need to be accessible as plain text by the application, one way or another.
I've only been able to think of something like the following:
When a user adds their credentials for the external service to their account, they re-enter their password for my application and that (in an encrypted form) is used to 'encrypt' the password for the external service somehow, but in a way that makes it accessible still.
Does anyone have any thoughts on if this is possible, or a potential solution?
Thanks
Also: it's worth noting that it will be an SSL connection that the data is sent over.
Out of curiosity: Say for example; Google Mail, you can add email accounts to your Google Mail account so that all of them are checked. Does anyone have any thoughts on how Google store the passwords for the accounts you add?
The problem with this in general, is if your system is every compromised, the attacker can get all the passwords for all the systems, because they are encrypted and not hashed. There is no way around this, since you want to be able to get the plain-text passwords.
If you must do this, you can use something well trusted like OpenSSL to encrypt the passwords.
From a securities stand point, you really should never store a password anywhere. I would have the user enter their password md5 their password and store that. So when he authenticates its authenticated vs the md5. As for the externals. You could take the external password and XOR the external password with the stored md5. That way you could undo it to pass it to the external source. Or the better way would be to ask for the password every time for the externals. This is a choice of risk vs convenience.
Well, you may encrypt the passwords by user's own password (not storing it anywhere), and just ask for it every time the communication is being made, this way the passwords are probably safe.
GAH... I wish everyone would just standardise on keys:
<?php
$connection = ssh2_connect('shell.example.com', 22, array('hostkey'=>'ssh-rsa'));
$sth = $dbh->prepare('select keyLoc from auth where username = :user');
$sth->bind_param('user', 'username');
$key = $sth->fetch(PDO::FETCH_ASSOC);
if (ssh2_auth_pubkey_file($connection, 'username',
$key,
'/home/username/.ssh/id_rsa', 'secret')) {
echo "Public Key Authentication Successful\n";
} else {
die('Public Key Authentication Failed');
}
?>
It would make life so much easier. Just copy your public key everywhere and keep your private key on you.
What you should do instead is to use Oauth - safer and also much more user friendly when it's implemented correctly.
Zend oauht client
You can use php mcrypt, see relevant question here. Or if you prefer to encrypt/decrypt server side mySQL has a AES encrypt function.
You might use something like PKIF (specifically PKIFCRYPTO) and NSS or MS-CAPI. It's not for the faint of heart, but you'll want to demonstrate a certain degree of competence to the users who decide to trust you with their credentials.
Related
As the title says I'm trying to use PHP's password_hash function but I know that it is one way hashing so if I use it the password will be unable to be unhashed.
That being said, I want to be able to have an eye next to a password box (like LastPass) within the system that I'm working with that can display the password for admin users of the site but I'm not sure how to do this. Is there a function within PHP or some library that will allow for secure hashing or encryption so that this is possible? Is there another way to do this securely?
I've been looking around stack overflow for a while now just trying to find an answer to this but have to find anything that is close to what I'm wanting to do.
For a quick frame of reference for this. The users of the site can allow for 3rd party companies to login to retrieve files that are being shared with them. The users create the password and share it with the 3rd party. I want to make sure that when the passwords are secured but still allow the users of the site to go back and lookup the password for the 3rd party companies should they forget their password.
... that will allow for secure hashing or encryption so that [displaying the password for admin users] is possible?
You keep using that word. I do not think it means what you think it means. :-)
Password hashing can either be secure or it can be reversible.
The whole point of password hashing is to be non-reversible. If you want the original password, you're going to have to store it (keeping in mind how insecure this actually is).
At a bare minimum, you'd want the plaintext password somewhere totally separate from, and inaccessible to, the outside world. But the ground is littered from the corpses of password files that companies thought were secure from the general public, so my advice is to steer well clear of this.
No, you cannot get the original plaintext password from a hash. That's the entire point. The plaintext password is a secret that only the user is supposed to know. The secrecy of their password is the only security measure they have. If the password is "publicly" known then the security is out of their hands. And if anyone besides them knows the password, even if it's just your server, it becomes harder and harder to control who knows the password and it's only a matter of time until it leaks entirely.
That is why you don't want even your server to know the actual password, and to only store an irreversible hash of it.
If you want to store the password in a way that is reversible, at the very least you should store it such that even the server itself could not see the plaintext. Meaning, even if you encrypt it, encrypt it in a way that the server itself cannot decrypt it. Because if your server can decrypt it, so can anyone with access to that server. For instance, use entirely client-side encryption within the browser and require the user to enter their password in some way which will decrypt the stored password. Of course, this limits who will be able to see the password, which is the entire point.
If you need concrete encryption schemes to design this, it's best to ask at http://security.stackexchange.com or perhaps https://crypto.stackexchange.com.
I make API for PHP website and I need to send a login and user password in encrypted form. I chose the following method to decrypt:
$decrypted = openssl_decrypt($user_login, 'bf-ecb', $client_id);
Where $user_login is a string like a 'login:password'. The $client_id know my site and client application. Client is likely to be an application on iPhone. Are normal encryption algorithm I chose, and will not be any problems on the client side with the encoding of user name and password?
Are normal encryption algorithm I chose, and will not be any problems on the client side with the encoding of user name and password?
You will probably need to use something like WebCrypto to ensure accepted and implemented encryption algorithms are available at the client. You may need to polyfill it.
In the bigger picture, you have two problems to contend with. First is the web security model. In the web security model, interception is a valid use case. Second is a breach of server security and the password list.
Interception
The first problem is due to the W3C's philosophy, and there's nothing you can do about the broken vision. The web security model's fundamental defects became acutely clear with Public Key Pinning with Overrides. The overrides accommodate the interception, and the web folks tried hard to downplay and coverup the behavior.
Your immediate defense is to place additional security controls like you are doing. That is, use encryption so the username and plain text password is not available to the interlopers. WebCrypto should help you so you don't need to polyfill it.
There's a latent problem, though. The interceptor can allow the encrypted username and password to pass, and then capture the cookie or token when its returned to the client. So you will need to guard the cookie too.
And the username, password and cookie will need to be protected from replay attacks. You don't want an attacker to grab the encrypted username and password, and then replay it at a later time to obtain an authenticated session. So it sounds like its going to need a salt or nonce, too.
Data Breach
The second problem can be remediated by following best practices of server side storage of passwords. For that, see OWASP's Password Storage Cheat Sheet and Secure Password Storage Threat Model
I am currently building a web/desktop application. The user can create an account online and login either online or via the desktop client.
The client will be built in Python and exported to exe.
I want to encrypt the password before it is sent online as the site has no https connection.
What is the best way to do this so the hashed password will be the same in python and php? Or is their a better way or should I just invest in https?
I have tried using simple hashing but php md5("Hello") will return something different to python's hashlib.md5("Hello").hexdigest()
Forget this idea. Hashing the password on the client, sending the hash to the server and then compare it to the stored hash is equivalent to storing plain passwords in the database, because the hash becomes the password.
Or should I just invest in https?
Yes!
Can you share a code example to reproduce this, along with the two different outputs ?
They should, and do, create the same output.
You should also either use HTTPS or look use a challenge response mechanism ( here's an example that many mail servers use : http://en.wikipedia.org/wiki/CRAM-MD5 )
Encrypting the password has no security effect - anyone can intercept the password and re-use it. The password remains secret, but anyone can still login as if they know it.
I have a server with mysql information stored on it. Now i need my Iphone application to be able to log in to a account and update information stored in the the database. So i was wondering, what would be the best way to go about this?
Shall i just use POST to send data to a PHP script and then echo a response for wether the user can login or not(The username and password match) ?
It's just this seems unsecure, also do i need to create some kind of session once the log in stage has been completed?
I have never done this before, so would be really grateful of any help!
Thanks very much
You described the common way to do it. You need some sort of a webserivce you can "talk" with. It's done in the way you post the data to the webserivce, the webserivce (e.g. written in PHP) opens a connection to the database and returns wether the request/login was successful.
If you just send the password in clear text, than it's unsecure you are right. I use two things to make the communication more secure.
SSL: If possible make a secure connections. But it's possible that you do not have the option to connect through ssl.
Password hashing: You can at least hash the password. In a normal case the username is public in an application, but the password isn't. A hashing function is function that returns a string that looks a little bit random to humans. Hash functions are one way functions. There's no way to go back to the original string (if you don't have a few super computers and a few hundred years of time). So once you retrieved a hashed password within your webservice, just hash the password in the database too and compare them. A string always returns the same hash if you use the same hash function. Common hash functions are: MD5 or the SHA familiy
I hope my answer helps you any further. Perhaps my approach is not the most secure, but until know no one told me anything better. ;-)
For phone apps, desktop app and some web apps this is a common issue.
Sandro Meier (above) said correctly that if you have SSL access then this is best way to send via a HTTP POST a username and password so anyone else on the network cannot sniff these details.
If you cannot use HTTPS, then I would recommend from your iPhone app.
1. post username + password to the PHP from the iPhone.
2. ON the server in PHP code, check these details, if correct generate some random token eg (KHnkjhasldjfoi&*) you can do this by using the MD5 hash function in PHP.
3. Save this hash in the db so you know which user you sent it back to.
4. Now for all other requests from the app to the PHP include this token with the request (in PHP you will need to check this token and if it is valid, then fetch or update data).
5. This way if someone is trying to sniff the connection they dont have access to the users password, they can only steal the token.
If you want to be 99% secure you need to use a HTTPS connection (but HTTPS can be faked, I wrote about this in Computer World).
The pervious person mentioned using a MD5 hash to send the username password, but this also can be hacked (a user could download you app, find the salt to the MD5 hash and that way they could still steal any password). I think the W3C said that they do not recommend encrypting web forms and password pages as it gives a false sense of security because pretty much anything can be decrypted (I think a Quantum computer can even decrypt HTTPs), they recommend using HTTPs as it provides the most security for sending sensitive data.
W3C Passwords in the clear.
http://www.w3.org/2001/tag/doc/passwordsInTheClear-52
How can I allow a change of password with md5 in mind. When the accounts are being created the passwords are being entered in md5. So now when i display the password field of course they are in md5 (don't worry for testing purposes i am showing the password in the field instead of displaying hashes or dashes).
So how do i go about changing the passwords then? When they are changed they also need to be in md5.
Don't display anything in the password field. Have 3 fields. One for the original password (for security), and 2 for the new password (one for verification).
When submitted, check the old password, if it's right, md5 the new one and save it.
In the database you overwrite the old MD5 hash with the new MD5 hash. Or are you asking a user interface question?
The MD5 hash is a one-way hash that cannot be decrypted, so there's no need to display it. Changing the passwords updates the database with a new MD5 hash.
So how do i go about changing the passwords then?
I think you should read You're Probably Storing Passwords Incorrectly
(Article from author stackoverflow.com):
We learned that in a password hashing
scheme, speed is the enemy. We learned
that MD5 was designed for speed. So,
we learned that MD5 is the enemy.
If you must store your passwords(Please also read below for more tips) use phpass to store your passwords securely. I advice you to read the article on the site explaining How to manage a PHP application's users and passwords. It will teach you how to do it securely using email verification tokens.
Just for the fun of it I also created a library(please also read below) which does this for you using the excellent phpass. It is hosted at github and you can take a look at it if you like. Especially you should have a look at Authentication Class together with AuthenticationTest.
OpenID
Furthermore I would like to point out you should use something like OpenID, Facebook Connect, Google Friend Connect instead. You should not be storing your passwords because it is risky business like The Dirty Truth About Web Passwords explains.
Jeff Atwood:
I'm not here to criticize Gawker. On
the contrary, I'd like to thank them
for illustrating in broad, bold relief
the dirty truth about website
passwords: we're all better off
without them. If you'd like to see a
future web free of Gawker style
password compromises -- stop trusting
every random internet site with a
unique username and password! Demand
that they allow you to use your
internet driver's license -- that is,
your existing Twitter, Facebook,
Google, or OpenID credentials -- to
log into their website.
I also have a nice OpenID library available at github which uses LightOpenID with openid-selector. You can see a demo up and running at my shared hosting provider: http://westerveld.name/php-openid/