i wonder if there's a secure way to deliver a password with an URL (like ?p=mypassword)
how can i encrypt and decrypt such a password so it's secure.
i guess md5 is not working in my case because the password must still be readable. It's an FTP passwort which gets passes along to the ftp_connect. i think md5 doesn't work in this case because i have to query if a string matches the md5 hash. however i can't do that in my case.
any ideas?
Erm: Send via POST + SSL
SSL ensures that the password can not easily be read by third parties while in transit. Sending it via POST simply sends the variable to the server outside the URL and keeps it out of the server logs (hopefully). This will do an alright job hiding it from browser history or people sniffing HTTP.
But then, doesn't ftp_login() send this plaintext when using ftp_connect() making a mockery of the SSL in HTTP? Make sure you use ftp_ssl_connect() to your server afterwards. See the ftp_ssl_connect() PHP manual entry
If your site accepts an encrypted password in the query string, that encrypted string - though unreadable - is functionally no different than the password itself.
If my password to enter the CIA is "password", but they'll let me in if I say "5f4dcc3b5aa765d61d8327deb882cf99", both strings function as my password and both need to be protected.
Instead of using a one way hash (MD5, SHA1). I think you need an encrypt-decrypt function. Take a look at this http://www.php.net/manual/en/function.mcrypt-encrypt.php.
The above example, you can encrypt using the key and pass the password in the URL. Once the password is received by PHP, you can then decrypt the password and use it to connect FTP. The only limitation is that the key will have to be available on the PHP server and wherever you generate the URL. There are also limits on the size of the string but I think you will be within those limits generally.
Related
I am wanting to store the ftp connection password in the db so that members do not have to always type the information in when they update the plugin. However cPanel does not use hash on the ftp passwords. They must be sent clean. I just ran a test using password_hash() and the connection failed.
If i am seeing this right it means i have only a few choices.
A. use a two way encryption instead of a one way hash and decrypt it before it is sent.
B. dont use a hash at all and just use some kind of encoding like base64 that can easily be undone to send it.
Right now it is being stored in session which to me is not secure either but i don't control that end of it.
Do i have any other choices here ?
Thanks
For me, you must protect database from intrusions, the ftp password you can store in plain text without encoding or encryption. if you want to be secure, use secure protocol as SCP or SFTP.
I found many questions/answers here and many articles in other websites but I have still a few questions which I need to answer before I can start and I just can't find answers for them. I want to create restful api for mobile apps (and for some frontend).
I choose Basic Authentication via HTTPS because I guess it's enough for now and it looks easy to implement. So I should have username and hashed password saved in dabatase right? Then when user write username and password in app I hashed password and both encrypt by Base64 and add to HTTP header right? How can I decrypt this and check with database on server-side? How it would change with salt?
And after I check username and password with previous call then how can I save this session? Should I create some session-id/token (random string) and save it to column in users table and send it back to mobile app and then using it for other calls (with some timestamp for expiration)? Could it be via HTTP (no secure)? Like web.com/api?token=ASsF234Silkj&data=... Or I must always use HTTPS after authentication?
How will it change when I use some API key (private) in all apps which would use this API? I know I can hide key and don't send it via requests (use it just for encryption) but what if someone try to read .apk and get API key?
First off, base64 is not encryption
While it is possible to integrate basic http authentication with sessions it is not a trivial task. And it's very easy to end up with something which is insecure (especially judging from the level of skill evidenced in your question).
You seem to have planned out most of what you want to acheive - but you've got most of it wrong already.
Whether you should continue to use HTTPS after authentication depends if your service has any intrinsic value.
Similarly how you implement surrogate authentication tokens (including API keys) depeds on the security model. Stick to using HTTPS everywhere and you should not have to worry about changing / encrypting the API key.
So I should have username and hashed password saved in database right?
Yes, you should hash it, don't use MD5 or SHA1, they are now no more secured. Use SHA2 or SHA3.
Then when user write username and password in app I hashed password and both encrypt by Base64 and add to HTTP header right?
Base64 is not hash function, you can get original content from base64, it's just a encoding way.. Yes you have to put credentials to HTTP header. While sending user name and password (hash or plain), use HTTPS connection. Sending hash in HTTP connection is vulnerable to replay attack.
How can I decrypt this and check with database on server-side? How it would change with salt?
If you send Hash , you cannot decrypt it (that the sole purpose of Hash). I would recommend you following:
1) send user name and password to server via https
2) create hash at server and check with the existing hash in database.
And after I check username and password with previous call then how can I save this session?
depends on which langauge you are using
Should I create some session-id/token (random string) and save it to column in users table and send it back to mobile app and then using it for other calls (with some timestamp for expiration)? Could it be via HTTP (no secure)?
you can do that but use HTTPS, and do not use time stamp, it is very unsecure. Rather generate long random string
How will it change when I use some API key (private) in all apps which would use this API?
???
I know I can hide key and don't send it via requests (use it just for encryption) but what if someone try to read .apk and get API key?
Do not put key in APK, generate it locally if it is private key (if i got what you mean)
I am creating a program that communicates with a PHP script on a web server and to do so I need to be able to pass parameters from the program to the PHP script.
Now here is my question. At some point the user name and password needs to be passed to the script. Now this is not done in a way that is apparent to users (such as in an address bar) but I know with a little sniffing around someone that really wanted to could figure it out. So while my script is safe from injection, obviously variable tampering is an issue here.
This is an idea I have come up with so please help me wrap my head around it and see if this would work the way I THINK it will.
My thought was to encrypt the user password (or another unique key) variables on the client side before sending so you get a url like (obviously just made up) mypage.php?un=Oa348uty8&ps=op986hGTfreu Then when it gets to the PHP script decrypt it and encrypt it again with a different salt.
So when it leaves the application it would be encrypted but not the correct way, and then when it hits the PHP script server side decrypt it and re-encrypt it with the correct salt so it would correctly match the stored encrypted password.
This way, they user would not know what the encrypted version of their password is supposed to look like so without that they would not be able to tamper with the URL and try to insert fake values.
To put it in a nutshell, you are thinking of this:
On server side you have:
a database, with login/password matches.
a script that take 2 parameters (password and username) and check in the database if the couple exists
Your problem:
When your local application call the php script on server side, the 2 parameters are given in plain text. And you want to avoid tampering ( if your script are safe against injection i only see tampering used to bruteforce the auth <= keep in mind that i will keep this assumption in the whole post)
Your solution:
On client side, encrypt the 2 parameters
On server side, add a salt in your script to salt
Then decrypt the 2 parameters and encrypt with a salt
What I think:
This will not solve the tampering issue, someone can still forge requests.
The first encryption is useless because someone can retreive the key used by your client.
The second encryption is not safe enought because you use the same salt for all you users.
What I suggest:
Accept that tampering can't be avoided if you don't use a secure protocol like HTTPS (can either use SSL or TLS).
If you want an acceptable security without HTTPS the following is what i would implement:
A token system that you will check in order to see if the user can perform the login operation
A username that would not be encrypted
The password sha1 hashed stored in database
On client side, you call the script and provide the username as non encrypted and your password as a sha1 hash, rehashed with a random salt (sha1(sha1(pass)+salt) (the salt is stored in the user session on server side)
The script would then compared the provided hash with db password hash rehashed with session salt
The improvement is that the attacker must try to brute force two sha1 passwords consecutivaly and must provide a valid token to perform the login action. Plus if you use as salt a string using hex char of a variable even length, it will make the job harder for the attacker to recognised that the value bruteforced by the second hash is a sha1 hash, and even if he know it's an sha1 he will have to test multiple case to try to find the right portion of the value that correspond to the hash.
Because of variable salt, a same password won't be the same if hashed:
Imagine the attacker sniffed a hash and know which password was used then sniff another hash that was made with the same password as the other, the attacker won't be able to know that the 2 password where the same( a little overkill but still usefull).
It is safer to store the password as hashed value, because if the attacker manage to dump your user table, he won't be able to use the passwords right away, he would have to bruteforce each of then.
Finally sha1 hash are safer than md5 (i tell you that because you used the md5 tag in your post)
The downside of this method is that passwords can't be reversed, so you won't be able to given them back to your users if they lost it. You will have to make them set a new one.
An hardcore way (still without using HTTPS), would be to encrypt your password and username with a strong cypher (like AES or 3DES) and use a secure key echange algorythm (like the Diffie Hellman one) to exchange a random shared key.
This method won't block tampering, but will screw the attacker, because he won't be able to decrypt the value (assuming he only is sniffing the network). The key is random and never hardcoded in any of your application, so even if someone reverse your client, he won't be able to retreive a key.
I would still recommend to store your password value has hash.
An extreme way would be to merge the 2 methods but would be completly overkill.
Hope this will give you ideas
The problem with your approach isn't whether you are using encrpyted passwords and usernames in the URL or not. If the user authenticates by sending the encrpyted strings to you, then I as an attacker can still sniff out those hashes, pass them to your application and authenticate. This is unless then, that you do some public key/private key exchange before hand, but that is just reimplementing HTTPS, so you might as well just use HTTPS.
What you should do is to send the request using POST over HTTPS.
POST: So that the authentication details will not be in the URL and show up in logs and referrer URLs.
HTTPS so that the content of the whole request is fully encrypted and can only be decrypted by the client application and the server side.
encryption with Javascript from client to server only prevent from non SSL posting fails.
I think you must use sessions instead of this type encryption .
Update:
You could add your own secret key in both scripts.
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
Basically, I have an ajax form that carries login information, is there any way I can encrypt the password before it sends in ajax then decrypt it in php?
Or any other ways I should look at it?
Many thanks :)
There is no reason to do any encryption in JavaScript or PHP as the appropriate solution is to use SSL (HTTPS). Nowadays you can even get certificates which are trusted in all browsers for free so there's no reason for not using SSL.
If you cannot use SSL for some reason, you could get a JavaScript implementation of RSA so you can encrypt it locally but only your server is able to decrypt it again.
You could use RC4, since I know theres an implementation of it in PHP and Javascript. However, with any sort of encryption, you'd have to leave the key client side (so it can encrypt it), which means that anyone who has access to your page can get the key and decrypt it (thus defeating the point).
You might be better off either hashing it client-side (and then matching the hashes in PHP, if you don't need to know the password), or using Public-Private key encryption (like RSA), so that clients can encrypt, but not decrypt it.
For hashing, look at hash() and sha1 for Javascript.
And for RSA, check out this blog post http://www.sematopia.com/2008/10/rsa-encrypting-in-javascript-and-decrypting-in-php/
Use an SSL certificate and send the login over HTTPS from your AJAX form.
You can't in a secure manner. you should use https
You can do md5(password) in both JS and PHP, and then compare the encrypted passwords.
As username is not encrypted, you can use it to take the password from DB in PHP, and then encrypt it.
Best way to do that is:
generate a uniqid, save it in $_SESSION['crypt_key'], and send it as a hidden input on the ajax form;
encrypt in JS using md5(crypt_key + password) before sending it;
encrypt in PHP using md5($_SESSION['crypt_key'] . $password) and compare them. This way, every request will transfer an unpredictable crypted password.