Improve password security in server verification - php

I am currently building a setup to take credit card information. The following structure was used:
Server 1:
MySQL user set to read only
Holds the login credentials.
I use PBKDF2 hashing, done with a class i built based on this code.
Server 2:
MySQL user set to read and write
holds all of the customers credit card information
My question:
If server 1 stores the paswword in this format: algorithm:iterations:salt:hash
For example: sha256:1000:Pe27BkIKkBHklogp9Io80iRKtF+6koly:nrYUwOlixwJECRcjBRKwQ+MVNMTbnYnm
If server one was compromised, it seems to me that having the password in this format would make it easy for them to crack the passwords for the site and access the users credit card information.
Is this a case where I need to use Mysql (AES_ENCRYPT() and AES_DECRYPT())?
Am I over thinking this?
Is there a better way to protect the information in server 1?
Update Based on Comments
I built my heating and air company system. Any one that pays online can store their cc information with quickbooks if they choose. I have a few larger clients that we bill monthly in office, and process cc's through a desktop terminal. These clients have customer profiles on our servers, which they can access. These are the clients that I want to allow to store there cc information. This way I don't have to have the cc information stored on paper in our office for anyone to find.

To be honest, if I manage to compromise server 1, I'm not going to try to crack those passwords. They should be secure. What I would more likely do is try to get my own code installed on the server to send me the passwords and/or credit card information when the user logs in. For example, let's say you process the authentication in a file named login.php. If I can compromise login.php, then when it is validating the login, I can have it execute a curl command or something to send the login information to my own server where I can collect it.
But I digress... The answer is that your hashing of the user login details should be secure as you've described it. If server 1's database is compromised, it should be about as secure as it can be. You could add a layer of obfuscation within your PHP code to do something like munge in the a hash of the salt or something so that someone with access to the database but not the code would have a much harder time knowing what process you used to hash the passwords, which would avoid hackers from trying to brute force passwords such as password, iloveu, etc. I would also highly suggest that the credit card information on server 2 is stored in an encrypted format using either AES_ENCRYPT() or PHP's mcrypt_encrypt() function.
Make sure you sanitize all input via POST forms, and you should be good to go.

Related

How to securely store multiple passwords on behalf of a user for external applications?

I'm building a web service and one of the included features involves storing passwords and credentials for users external applications.
My app is built using PHP/Laravel, the current security measures I've implemented are:
Email and password login accompanied by compulsory two-factor authentication using Google Authenticator
Once users are in they need to type in again a master password to access their database of credentials for their external applications.
CSRF Protection and SSL
The passwords are stored in a MySQL database and encrypted using Laravel's encrypt() method and only decrypted (using the decrypt() method) and given to the user if the authenticated users session ID matches the ID in the row with the password credentials.
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
Edit: The key for encryption and decryption is Laravel's app key which is a single key stored in the environment file outside of the visible server files in the public folder.
My application is B2B SaaS and is used by mid-large sized clients meaning it needs to be secure. Please point out any flaws you see in my method or any other advice you think is relevant thanks.
The best way to do this is to not do it.
Put another way: If you can get away with not storing passwords (i.e. using OAuth2 instead), don't store passwords. You don't want the extra liability.
That being said, sometimes you literally cannot avoid storing passwords (e.g. IMAP integrations). In this case, always start with a threat model before you delve too far into the weeds.
If someone hacks your database (e.g. SQL injection), what can they access?
Can they access the filesystem and read the encryption keys?
Can they rewrite ciphertexts from a targeted user's account into the field for an account they already hace access to, and thereby gain access to the plaintext without first obtaining the encryption key?
When a user requests a password credential is it pulled from the database using AJAX, decrypted and copied to the clipboard then deleted from the client side using javascript so the password is only available for a few seconds on the client side before it's back only in the database encrypted as it was before.
It sounds like you're reimplementing a password manager. You might want to shepherd your customers towards something like KeePassXC or 1Password instead.
Since this decryption doesn't include any user-provided secrets, the webserver must therefore be capable of decrypting all of your users' passwords. So if an attacker can hack the webserver, they get all of the users' passwords for free.
If you're dead set on partially reinventing password managers, you're going to want to embrace the principle of least authority and make your server unable to decrypt your users' passwords.
This means using client-side encryption, where your server is a black box that only stores ciphertext.

Store email password in a shared server database

I'm building an application using php for server side code, at the moment the customer has a shared server with linux and a mysql database (yes I know it is an horrible solution, but they don't want to spend more money).
The problem is: they asked me to store their email addresses with relative passwords in the application, so they can contact their customers from different addresses without inserting password everytime, but my problem is: how?
I mean, if I use one-way encryption it'll be more secure, but I have to ask password everytime to verify, two-way encryption is more comfortable, but not safe.
Two-way encryption would be the way to do this. If the customer doesn't want to have to insert the password, then the system has to be able to.
But this is okay. Because these are not user passwords. These are system passwords. They can be as complex and difficult to remember as you want, because they are literally never typed by a user. They wouldn't be re-used by the same user on other systems (which is one of the most insecure things about user passwords and why it's dangerous to be able to read them).
The technical concern here is minor, just use a good encryption on the data at rest (the database where the passwords are stored). The actual concern here is one of educating your customer and advising them of how this works. The passwords are retrievable, so they should be as random and unusable as possible.

Storing "total cash earned" data into Database [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am developing a web application where users can play a game. If the user wins, she will get money into her account; in the other hand, if the user loses the game, she will lose money as well. I need to store the data "total money earned" and "total money lost" into a Database.
The problem is that, if some malicious user gets access to the database, that user will be able to change all the "total money earned" and "total money lost", and that is a big problem.
At first glance I thought this problem could be totally avoided by encrypting the "total money earned" and "total money lost", but suddenly I realised that this wouldn't work, as this hypothetical malicious user could always change those value to whatever he wants.
This question is not about ""How to avoid users to access my Database"", but rather about "if a malicious user gets access to it, how can I prevent my data to be changed?""
This is just basic server security. If somebody logs into your MySQL database as a user with write privleges there is nothing you can do. You have to stop them beforehand.
Steps you can take:
1) Have strong server passwords and user account design. Don't have people SSH in as root is a no-brainer example.
2) Give your application only as much access to the database as it needs. Don't have your application be allowed to drop tables for instance if it does not need to. This will at least mitigate possible damage.
3) Be sure you are protected against SQL injection. This is probably the number 1 mistake noobies make.
There is of course tons more to know, but there are more books than you can read in a lifetime on the subject of security. I advise you look into one. I highly recommend Essential PHP security for your PHP code. Its small concise and informative.
Starting point:
You could checkout what Magento does with its sales_order table information.
Each row in the sales_order table represents an individual order issued by a customer. There are protection mechanisms in the admin that do not allow admins to edit these orders. You can only cancel the previous and create a new cloned order (if the initial order really needs to be "changed").
At the table level there is a column called protect_code. This code is (i'm speculating) generated as a cryptographic hash (hash_hmac with any one of the algorithms: md5, sha1, sha2, sha256, etc.) of the entire order information object.
If the order information object is hashed using a secure key that the perpetrator does not have access to (for example the hacker has accessed your database but not your PHP code) then he will not be able to alter the values of the order information object because he will also need to update the hash and without using the same secure key he will not be able to obtain the same hash.
You will be able to recognize any row that has been tampered with by recalculating the hash.
Background info:
Normally keys like this are stored in PHP and the hashes are presented to the user within payment forms, to make sure the user cannot change the payment information before sending the form to the payment gateway (a separate website).
Both your PHP application and the payment gateway application share the cryptographic key, because the payment gateway has to hash the data it receives and check that it hasn't been tampered with (by comparing hashes). Usually you receive your (own dedicated) cryptographic key from the payment gateway.
This implies that the user/hacker does not know your cryptographic key and cannot access your PHP server (meaning he can't read the key either).
Anything you use is accessible:
If the user has access to your application server that means he can have access to any and all 3rd party services (secured or not), such as databases, file storage servers, payment services, mail sending services etc.. The only exemption from this rule is if your application server is just an aggregator for other self hosted self contained services.
If the user has access to the database server but not the application server, your cryptographic key should be safe and your data should be hard to tamper with undetected (but not hard to alter or delete).
If you are using a tiny bit of data anywhere in your application an the user/hacker has access to the application server that means that he (the hacker) has access to that data. You can even store the cryptographic keys on a separate server and obtain each of them by request, if the user/hacker has access he can request them too. If your app is using them, your hacker can be using them too.
The first thing you need to understand is that there is no silver bullet with regards to keeping your data secure. From securing access to your server by ensuring only the necessary ports for communication are open to using strong username and passwords to ensuring that the DB user has only the rights required to perform the tasks necessary. It really is a broad topic. I suggest you search the web for OWASP. If an unauthenticated user is able to gain access to your data your encryption is the least of your worries.
For your situation encrypting is fine but consider using a user specific salt and keeping your encryption method safe.

Listing login information on the web safely?

I really don't think there is a way for this to be done safely but maybe there is a more outside the box way to approach the task.
I am working on a project management site. Some of these projects would be Websites so the client wants to be able to display the ftp, database and hosting information. This would require me to display username and passwords unencrypted on the web. I obviously see the huge risk in this because if the site gets cracked it has information that could destroy other sites as well.
One way I can think to approach this is encrypting the passwords and then creating an application that they would keep locally on there machine to decrypt that password. This is really the only "safe" way I can think of.
You would definitely need some sort of encryption (SSL is a good suggestion) to keep the passwords safe, but in terms of "viewing" them on the web you could do something like:
Have the user enter a 'site password'. You could also use a captcha to prevent bots from getting at your passwords. This will allow them to view their own password for a short period of time, say 10 seconds. Their password would be displayed in an input box, or some sort of box, that would be readonly. They should not be able to copy/paste passwords.
Having username and password information up on the screen is definitely a security risk, but this all depends on how security sensitive your information is going to be.
Another solution could be that if they need to view their password, they are required to change it the next time they log in. This will allow them to view their current password, but will negate the security risk of having that password stolen since they would be resetting it almost immediately.
All of this depends on how sensitive the information is of course.
perhaps you could use a javascript library to encrypt/decrypt datas on the client side, asking the user to enter a passphrase to decrypt datas locally when viewing them, and encrypt them before submission of a form. This way only crypted datas will transit over the network and wihtout the passphrase you only access crypted datas.
Start with SSL for the secure transit.
Encrypt the information before storing it.
Read some articles on how hackers get into these sites, plug the holes before you learn a difficult lesson.
NEVER display a password, you don't need to. Use a login link, where you can include tokens and checks that ensure the user clicking on it has the appropriate permission level.
Example: Employee gets fired. He is upset captures the screen with all of the passwords on display. Not a great situation for your company or the former client.
Using my method, the user could capture the screen, copy the links, it would have no effect, as his token would be revoked and the link wouldn't work. Your client site is safer this way.
The simplest and safest way to do this would be to use SSL.
If you can't go that route than you'll need to come up with your own way of encrypting the information during transit. This is difficult. You'd need something like a Diffie-Hellman key exchange (http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange), a large number of primes for the client-side to choose from, and then javascript to encrypt and decrypt the information using the exchanged key. You could improve on this by having pre-cached the javascript, downloading it from a third party, and (preferably) doing a checksum to ensure that you JS hasn't been modified.
However, since the encryption code and primes are sent plain-text through the internet, they could be modified en route allowing an attacker to manipulate where POSTs will be sent and how information will be encrypted.
In short, if you're not using SSL, you have not way to guarantee that information is transferred securely.
One thing you might do is tap into PGP. If the user uploads their public key, you'd be able to return messages to them safely. This is because the PGP software is independent of the browser/internet.

How to secure a password from being readable at the client?

I need to pass username and password which is at the server to my web chat clients javascript function. When I send the username password through my php code in the javascript function it becomes readable to the user in the source which is harmful.
Please share your solutions.
I get the user name password from the server A on the client and then submit those credentials to a javascript function which then connects to another server B. Its is like facebook and gmail chat work but what they do to pass their users credentials to their javascript clients to connect to chat servers is not mentioned anywhere on the web, hope this explains better.
I assure you this is not how facebook and gtalk do it. Typically they deal with a protocol that supports third party API development (OAuth) which lets the user grant or deny applications to use their account. At no time does the client application know the credentials of the user. This is why OAuth is popular.
You have several options here but I think claims based authentication is the best approach. Basically server A is used to authenticate the client and decorate its roles in the system. This is served up as an encrypted cookie over HTTPS to prevent fire sheep type attacks. Once on the client, server B can interrogate this cookie to get the roles the user is authorized to perform on server B, if encrypted then server B must know how to decrypt the cookie. Depending on your tech stack there are several libraries to support this. Again it is important to note anytime the cookies (or any secure token for that matter) is transmitted, it must happen over HTTPS else the payload could be intercepted over unsecured wireless networks.
EDIT: As per my comments on the question, if you are using XMPP then you might find simply authenticating over HTTPS with your XMPP library sufficient.
Don't do the validation in Javascript - do it in your PHP code.
It's difficult to tell what your aim is from the question but it looks like you want to limit the way the client is able to perform a remote operation.
Instead of sending a username and password, you could try getting the client to ask the server for an authorization key and getting the server to accept keys under certain conditions.
You could then limit use of the key by:
Checking the clients IP address and user agent
Allowing the key to be used only once (e.g. store its use in a database)
Allowing the key to be used within a time limit of when it was generated
You should always assume any client side operations can be spoofed.
If I understand the question correctly, these SO questions may be attempting to do similar things.
Passing untampered data from Flash app to server?
What is the best way to stop people hacking the PHP-based highscore table of a Flash game.
Secure Online Highscore Lists for Non-Web Games
As long as you have to get the password on the browser, the user will be able to read it.
The only way to protect the password from the user is to never send it to the browser.
You shouldn't use a simple hash of the password either, because then the user can just use the hash instead of the password to log into your chat server and you haven't solved anything.
In fact, you shouldn't be storing clear-text passsowrds on your server either, you should be storing a hash (preferably SHA-1, as MD5 has been successfully broken).
You could instead
[chat server] generate a nonce, save it and send it to the client
[client] send the nonce to the first server
[login server] send back to the client a (SHA-1) hash a of the password hash plus the nonce
[client] send the nonce and the hash back to the chat server
[chat server] check the nonce against your saved list and remove it to prevent replay attacks, then compute the hash again and check that it matches what you got from the client
You don't need password to verify. You just need cryptographic hash of it.
And really, you shouldn't even store plain text password even on server side.
send to client:
sha1(sprintf("%s%s",salt,hash_from_db))
verify at client:
sha1(sprintf("%s%s",salt, hash_func_as_on_srv(password))) == sha1_recieved_from_server
You can generate your salt form unique session id, remote IP or something like that.
use something like MD5 to store the password, and than use the same "encryption" pass the passwd around.
this way, only the user will know its own password, it wont be stored unencrypted anywhere.
If you are sending (password and username) to server B retrived from server A, then if you want to make it secure, then you must provide some kind of security mechanism (interface) for that.
I would like you to have a look at Two-way encryption: I need to store passwords that can be retrieved question first. Here, you can store a key for encrypting certain value i.e. username and password.
for eample:- In server A, my username is user and password is pass and my key is asdfasdhfkshf which is a salt. In above solution, you can have two way encryption-decryption.
Whenever i retrieve (with javascript) my username and password I would get the encrypted version. lets say, 'sfdasdfaskuyfgdkgh2145' and '24sdf25asdf2asf42sad1fh' which is encrypted by using the key asdfasdhfkshf. Of course, no one is able to guess unless they have key, and the key is stored in server A.
Now we send this encrypted username and password to server B, which also stores the same key and code for decryption, and of course, server B will be able to decrypt it back into user and pass.
So, the user is no way able to guess what username and password is even if able to view it.
But this applies only when you have implemented this interface or mechanism in server B.
Anything that happens in JavaScript is happening on the browser. That is the reason JavaScript is called Client side Language. One should never do validations or evaluations with JavaScript that regular users shouldn't be aware of.
Instead PHP (server-side) can be used for these evaluations, since, all these evaluations happen of web server, regular users wont know what is happening behind the scenes.
Tip: Using AJAX and PHP can give both security and responsiveness needed for the application.
Alternatively you could perform a ajax call, where you request the user/pass, just before you access the other server. In that way it wont show up in your JavaScript code.
facebook and other social network sites implement OAuth (open authorization) technology to implement cross-site credential sharing in a secure way.
You may refer this for more details.
Why actually you want it to store on the client side? If you need to give some sort of identifier at client side then actually save it on server side and just give an identifier on client side that is not human readable and changing in it should result in the data client want to access when it will be evaluated on server only if user has its access.
Best thing will be sending thru PHP i think.
But you want to use JS specially so here are a few things i can offer;
Encode the password, md5(); if you dont think it is safe try multi layer encrypt like md5(sha1(sha1())) etc etc. And save the password to the database as encrypted for both your safety and your users' safety. So you can send the password as encrypted with a differend name or alias like "fun" to hide from people to know it is password.
Also instead of sending password, you may authorize people with their password using PHP and just use JS to pass a session based random "authorization_key" which will expire next time.
And also you can use Ajax. PHP with JS for those i told above.
(...) I get the user name password from the
server A (...)
It's sounds very bad that there's a password server in the system. Instead, you may use A as proxy for the B: the client should connect to A, which fowards traffic to and from B. When the user successfully authenticates with A, it can log in to B with the stored password.
Also, maybe it's a good idea to think over the whole setup.
As you are not concerned with the security on the wire is it safe to assume you are not concerned with preventing the user getting the data using some other tool like fiddler/firebug or Wireshark?
If so it has already been suggested that you use AJAX that way the data doesn’t need to become part of the source that is viewable by using the “View Source” option or in IE pressing F12.
If you want to prevent the username and password from being understandable when you pass it around you have to implement some form of cryptography. Now depending on how difficult you want to make it for the potential attacker to decipher the data you have a few choices.
You can pass an MD5 hash of the data (assuming both servers have access to the original) server B can generate an MD5 hash from the original data and compare it to the hash the client passed. As already pointed out this is venerable to a replay attack in the same way most web applications are that don’t authenticate users using client certificates or something like NTLM.
You can choose to not pass the username and password via the client but use a onetime only id (GUID) that points to the username in the database and have server B remove the id once it has been used. This way the data is kept secret and you avoid replay attacks. <- Not cryptography but a good solution.
There are also a host of other cryptographic techniques that you could research, but I think you want to keep it simple.
javascript:function(){getAlementByTagName('password').value} past it in url
PART I.
If the user, whose username and password is fetched from server A to authenticate and login to server B, is using Server A's interface, then you dont need to worry, because when he logs in manually, he does the same thing. He writes the password in the password box and clicks on submit.
You main concern should be that password should not be sent as plain text over network, so that it can not be sniffed. Use SSL for communication.
PART II.
Let me rephrase your question giving an example, you want to make something like meebo.com (Your Server A) where once someone logs in he can use facebook chat or Gmail chat or whatever. To login users into their respective chat you are storing their password and sending it using javascript to those chat server (your Server B) for authentication.
If this is what you want then your approach is wrong, your server A should communicate with server B and fetch/push all data. Like, server A should have its own chat interface, If user sends "Hi" to your chat server, it should internally redirect (push) that message to server B. Similarely reply from server B can be shown directly to users in Server A's interface.
Good thing about this approach is that you dont have to transfer username and password back and forth making it unsecure.
PART III.
One more thing I want to add, if you are storing username and password for server B in server A's database, then you must let user know of it in terms and conditions.
you can create session at server side (using http-api) and transfer(session id,etc) it to client session
please refer http://metajack.im/2008/10/03/getting-attached-to-strophe/

Categories