Best practices to store CreditCard information into DataBase - mysql

In my country the online payments are not an old thing, the first time i saw a web application taking payments directly to a local bank account was last year.
So, Im a newbie coding web payment system.
My question is, what are the best practices to store creditcard information into the database...
I have many ideas: encrypting the creditcard, database security restriction, etc.
What have you done?

DON'T DO IT
There is simply far too much risk involved, and you will typically need to be externally audited to ensure that you're complying with all the relevant local laws and security practises.
There are many third-party companies that do it for you that have already gone through all trouble of making sure their system is secure, that they comply with local laws and so on. An example in the US that I have used in the past is authorize.net. Some banks also have systems that you can hook into to store credit card data and process payments.
I realise the country you're in may not have as strict laws as the U.S., but in my opinion that's no excuse for rolling your own. When you're dealing with other people's money, the risk is just too much to warrant.

In 2020, use Stripe, and avoid storing payment information yourself.
HISTORICAL ANSWER:
For this, I recommend a comprehensive, layered approach.
First, storing credit card info should be an option.
Secondly, the data should be stored securely, using a strong form of encryption. I recommend AES with 256bit key size. Make sure when choosing your key, you use the entire keyspace (it's a rookie mistake to just use a randomly generated alphanumericsymbol string as a key).
Third, the AES key needs to be properly secured. Do not embed the value inside your code. If you are using windows, consider using DPAPI.
Fourth, you will want to setup database permissions so that applications and computers will have access on a need to know basis.
Fifth, secure the connection string to your database.
Sixth, ensure that any application that will have access to the credit card data, will properly secure it.

At miniumum follow the PA DSS (Payment Appliction Data Security Standard). More info can be found here:
https://www.pcisecuritystandards.org/security_standards/pa_dss.shtml
Also it would be wise to look at PCI DSS, which could be found here:
https://www.pcisecuritystandards.org/security_standards/pci_dss.shtml

You should avoid storing any credit card information due to the risks to you and to customers of doing so.

Encrypt encrypt encrypt. Don't decrypt if you don't absolutely have to - don't decrypt to show the last 4 digits. Don't decrypt to tell the user what their card was.
In fact, if you can, don't even keep the encrypted card numbers in the same physical server as the rest of the user information.

Authorize.net has a Customer Information Manager API that allows you to store customer information in their system. It costs $20/mo. as an add-on to your account.

I suggest you encrypt card numbers with a strong algorithm( similar AES) and a long secret key.
Then,keep your secret key in a secure place similar an external hard or optical disk.
When you need to secret key,use external hard.
If you are using a shared host, you have to store your secret key in an external device.
Strict your database
Define strict users for your database
Remove root user of your database if it is not needed.

Related

saving email-addresses in database [duplicate]

I'm already using salted hashing to store passwords in my database, which means that I should be immune to rainbow table attacks.
I had a thought, though: what if someone does get hold of my database? It contains the users' email addresses. I can't really hash these, because I'll be using them to send notification emails, etc..
Should I encrypt them?
Bruce Schneier has a good response to this kind of problem.
Cryptography is not the solution to your security problems. It might be part of the solution, or it might be part of the problem. In many situations, cryptography starts out by making the problem worse, and it isn't at all clear that using cryptography is an improvement.
Essentially encrypting your emails in the database 'just in case' is not really making the database more secure. Where are the keys stored for the database? What file permissions are used for these keys? Is the database accesable publically? Why? What kind of account restrictions are in place for these accounts? Where is the machine stored, who has physical access to this box? What about remote login/ssh access etc. etc. etc.
So I guess you can encrypt the emails if you want, but if that is the extent of the security of the system then it really isn't doing much, and would actually make the job of maintaining the database harder.
Of course this could be part of an extensive security policy for your system - if so then great!
I'm not saying that it is a bad idea - But why have a lock on the door from Deadlocks'R'us which cost $5000 when they can cut through the plywood around the door? Or come in through the window which you left open? Or even worse they find the key which was left under the doormat. Security of a system is only as good as the weakest link. If they have root access then they can pretty much do what they want.
Steve Morgan makes a good point that even if they cannot understand the email addresses, they can still do a lot of harm (which could be mitigated if they only had SELECT access)
Its also important to know what your reasons are for storing the email address at all. I might have gone a bit overboard with this answer, but my point is do you really need to store an email address for an account? The most secure data is data that doesn't exist.
I realize this is a dead topic, but I agree with Arjan's logic behind this. There are a few things I'd like to point out:
Someone can retrieve data from your database without retrieving your source code (i.e. SQL injection, third-party db's). With this in mind, it's reasonable to consider using an encryption with a key. Albeit, this is only an added measure of security, not the security...this is for someone who wants to keep the email more private than plaintext,
In the off chance something is overlooked during an update, or an attacker manages to retrieve the emails.
IMO: If you plan on encrypting an email, store a salted hash of it as well. Then you can use the hash for validation, and spare the overhead of constantly using encryption to find a massive string of data. Then have a separate private function to retrieve and decrypt your emails when you need to use one.
In common with most security requirements, you need to understand the level of threat.
What damage can be done if the email addresses are compromised?
What's the chance of it happening?
The damage done if email addresses are REPLACED could be much greater than if they're EXPOSED. Especially if you're, for example, using the email address to verify password resets to a secure system.
The chance of the passwords being either replaced or exposed is much reduced if you hash them, but it depends what other controls you have in place.
I would say it depends on the application of your database.
The biggest problem is, where do you store the encryption key? Because if the hacker has excess to anything more than your DB, all your efforts are probably wasted. (Remember, your application will need that encryption key to decrypt and encrypt so eventually the hacker will find the encryption key and used encryption scheme).
Pro:
A leak of your DB only will not expose the e-mail addresses.
Cons:
Encryption means performance loss.
Allot of database actions will be harder if not impossible.
Don't accidentally conflate encryption with obfuscation. We commonly obfuscate emails to prevent spam. Lots of web sites will have "webmaster _at_ mysite.com" to slow down crawlers from parsing the email address as a potential spam target. That should be done in the HTML templates -- there's no value to doing this in persistent database storage.
We don't encrypt anything unless we need to keep it secret during transmission. When and where will your data being transmitted?
The SQL statements are transmitted from client to server; is that on the same box or over a secure connection?
If your server is compromised, you have an unintentional transmission. If you're worried about this, then you should perhaps be securing your server. You have external threats as well as internal threats. Are ALL users (external and internal) properly authenticated and authorized?
During backups you have an intentional transmission to backup media; is this done using a secure backup strategy that encrypts as it goes?
Both SQL Server and Oracle (and I believe also others DBs) support encryption of data at the database level. If you want to encrypt something why don't simply abstract the access to the data that could be encrypted on the database server side and left the user choose if use the encrypted data (in this case the SQL command will be different) or not. If the user want to user encrypted data then it can configure the database server and all the maintenance work connected with key management is made using standard DBA tool, made from the DB vendor and not from you.
A copy of my answer at What is the best and safest way to store user email addresses in the database?, just for the sake of the search...
In general I agree with others saying it's not worth the effort. However, I disagree that anyone who can access your database can probably also get your keys. That's certainly not true for SQL Injection, and may not be true for backup copies that are somehow lost or forgotten about. And I feel an email address is a personal detail, so I wouldn't care about spam but about the personal consequences when the addresses are revealed.
Of course, when you're afraid of SQL Injection then you should make sure such injection is prohibited. And backup copies should be encrypted themselves.
Still, for some online communities the members might definitely not want others to know that they are a member (like related to mental healthcare, financial help, medical and sexual advice, adult entertainment, politics, ...). In those cases, storing as few personal details as possible and encrypting those that are required (note that database-level encryption does not prevent the details from showing using SQL Injection), might not be such a bad idea. Again: treat an email address as such personal detail.
For many sites the above is probably not the case, and you should focus on prohibiting SELECT * FROM through SQL Injection, and making sure visitors cannot somehow get to someone else's personal profile or order information by changing the URL.
It's worth to encrypt data in Databases, it's not making it a bit more difficult but way more difficult when its encrypted in the right way so stop philosophy and encrypt the sensitive data ;)
#Roo
I somewhat agree to what you are saying but isn't it worth encrypting the data just to make it a little more difficult for someone to get it?
With your reasoning, it would be useless to have locks or alarms in your house, because they can also easily be compromised.
My reply:
I would say that if you have sensitive data that you don't want to fall in the wrong hands, you should probably do it as hard as you can for a hacker to get it, even if it's not 100% fool proof.
I miss one important answer here.
When you have European users, you have to comply with the GDPR rules.
Email addresses are considered personal data meaning Art.5 does apply on email addresses.
processed in a manner that ensures appropriate security of the
personal data, including protection against unauthorised or unlawful
processing and against accidental loss, destruction or damage, using
appropriate technical or organisational measures (‘integrity and
confidentiality’).
Of course this does not say that you must encrypt email addresses. But by encrypting the data you do protect it from snooping employees. And protect yourself as a developer from requests to make a manual change in the database.
You really have to weigh your worst case senario of someone obtaining those email addresses, the likelihood of someone obtaining them, and your extra effort/time needed to impliement the change.

How to securely encrypt credit card information in a database

I have already read through Saving credit card information in MySQL database? and Storing Credit Card Information.
I'm aware that storing credit card information requires PCI compliance, which is not an easy task.
That is not what this question is about. My question is the following:
What is a secure way to encrypt user credit cards? The simplest and easiest that comes to mind is using a private key and encrypting CC's with that. This doesn't seem very secure because the key has to be stored on the server, and if an attacker can get my database, they can probably get the key too.
What I'd like to be able to do is encrypt every CC using that users password as part of the encryption process. If anyone gets the database, they can't decrypt anything because the passwords are stored as salted hashes. This would work great for transactional purchases - the user clicks "Buy," types in their password as a confirmation, I decrypt their CC and make the charge. Their password is only in memory for the duration of the request, and is never written to disk.
Unfortunately this won't work for what I'm trying to build - a service which charges a recurring fee (say, once a month), regardless of whether or not the user is logged in when I need to make the charge.
Given this scenario, is there a secure way of storing user CC's?
As you need to be able to decrypt, there's always the possibility that the encryption keys leak and you'll lose everything. So you'll never get to absolute security, but you can make it harder for attackers to get to the data.
Nobody but you can really judge what level of security (or obscurity) you should have. This is most likely a function of size of database, visibility etc.
For leaks, unfortunately you'll have to assume that everything leaks and sooner or later (e.g. with brute force attacks on weak passwords) you haven't gained too much when they get out.
Given the last credit card leak scandals - the worst ones had the 3-digit (CVV) number saved with the regular credit card number, which credit card companies explicitly forbid (that's why you'll always have to give it again even if someone has your credit card information on file)
If you don't want to assume the responsibility for holding and processing this kind of data, a good way to go is with an external payment service - let them do the processing and just assert to you that the payment has been processed. You'd have to pay them for their services, but you'd also have to pay for implementing your own solution and for taking the risk.
If you use the password as the salt for the CC encryption, it would be a very effective way of securing the information, however, they would never be able to change their password... If it is changed, then the encrypted data is lost. The bottom line for securing the encryption key is to make it as difficult as possible to find... essentially the more steps you use to hide the key, the harder it is for them to find it... which means it is harder for you to use and program for it. There is no magic bullet at this time to protect everything. (Invent a secure way to keep the key and you will be rich)
As for the CVV number, it cannot be stored as previously mentioned. With each transaction the cc processing company will give the merchant a Reference Number which is then used in each reoccurring payment. This means if the original transaction required the CVV number, then logic will dictate that the recurring payment will also be authorized by the same user who put it in on the first transaction. Therefore, the reoccurring payments will not need the CVV to maintain the same level of security.
You could essentially use multiple servers. Encrypt the cc with a key, but keep that key on a separate encryption server, the is only accessible by a master username and password for windows or whatever OS you're using. This way you're securing your key, setting up a services on the encyrption service to run the card through the encryption and then submit it to the database.
Use php's private/public openssl functions when a user makes a purchase you use the data in memory to make the purchase then you store the information using a public key to encrypt it.
To process billing monthly you decrypt the data using the private key that could be manually punched in or stored in code. If you want to store the ssl key in code and not have to remember it or get it everytime. I would encrypt the key using a salt stored in the configuration variables + buy a yubi key and generate a 32 character password + my own password on top of it. Store the yubikey in a safe place (A safe lol). When you need to process credit cards do it with a script that runs in the background and runs all billing at once. To change the password would require you decrypt all cards and re-encrypt them using the new private/public key, or you may just decrypt and re-encrypt the private key ssl.
Magic :)
You require the card information to be reversibly encrypted. The decryption information has to come from somewhere. You've said the data cannot come from the user, and you don't want it stored at the server, so it must be on separate equipment that is presumably more secure. And if you have the ability to recall that information, so does an attacker who has compromised your system. So presumably the decryption information is not retrieved at the vulnerable host during decryption.
Perhaps consider a third-party service that you can encrypt and send information to, perhaps one that specializes in PCI compliance. It might be able to decrypt the credit card information when you send it a second time and apply a charge, or it might actually store the card information for later use. It might even perform recurring transactions for you.
http://www.authorize.net/solutions/merchantsolutions/merchantservices/automatedrecurringbilling/
I just Googled that, I don't recommend them. But it's an example.
Encrypt the CC information twice. First, encrypt the credit card data based off the user's password (+ salt). Then encrypt the output of that with the server's key.
To access the information, you thus require the user's password (i.e. decrypt using server's key, then decrypt based off password). If the database and server key are compromised, the information still isn't exposed without attacking the user's password first.
It's important that the user's password is for the internal encryption - this allows you to re-encrypt when you change server encryption keys.
When the user changes their password, you also re-encrypt the data. If the user resets their password, then the CC information should be erased (and is lost anyway, as it can't be unencrypted).

How to store data in db so that nobody with access to it can understand it?

We are soon releasing a private beta of a domestic economy website.
The website of course gathers information from a user's (identified by email only) private financial situation: salary, rent, bills, mortages, etc. All of these are really sensitive information and should not be accessible by anyone - not even us, the tech ppl.
What are best practises for storing data in a non-readable fashion? Of course, member passwords are already hashed in the db.
What I'm thinking about is to encrypt all data using some kind of key. But then again, the application needs access to that key. And I don't want to store it in the db. If supplied by user, I guess I could keep it in the session in order to decrypt every retreived db result. But what about overhead?
Pls, anyone with guidelines?
First, separate the personally-identifiable information from the statistics. This allows you to perform computations without putting sensitive data at risk. Next, strongly encrypt the personally-identifiable information, and store the keys in a hardened system with limited access. Don't use the same key for all data, but the number of keys you do use is a design decision that is up to you. More keys will be more secure, but harder to handle.
There may be existing standards that apply to your data, depending on where in the world you are and what industries you are working with. Seek these out and follow them.
Anyone with admin level access (your tech people for example) can get access to any decryption keys stored on the machine. Regarding session, any admin level person can do memory dumps to pull keys out of session.
Point is, the only "solution" of sorts is great off machine access logging combined with a strong legal document acknowledging that they are being watched and you will prosecute. Also you should perform annual background checks of your tech people. Next, the number of people with that type of access should be extremely limited. As a CEO who takes an active part in our development process, even I don't have access to our production systems.
Regardless, you should still encrypt the database, especially the PII data. Depending on your industry you could be sued if you don't, and never mind the bad press if someone does pull a data dump.
What about a second keyphrase secured by the users keyphrase? When he logs in his second will be decrypted and stored.

public Web access to companys Application database

im struggling to find the best practice to this so any links or research reading materials or any Google search terms will be much appreciated.
Im a volunteer for a local charity organization, a childcare setting.
We have a mysql database that contains various tables containing children & Parent information, invoices, staff rotas etc.
What we would like to attempt to do is have secure online access for parents to view there own contact details and invoices.
My question is, is it safe to allow the website to have access to the main database. it would be a second set of userPermisions with only read access to select tables and not the entire database.
I don't want the website to open up a hole to allow users to obtain all our data or destroy or corrupt the main database.
Or
should i create a second database that the website will have access to and have the main database sync with the second? I can see future issues if we decide to allow parents to edit there own contact details, pay invoices online.
Web specific details will be kept in a second database such as user name password, forum etc
Its not any thing iv ever attempted to do before and don't know where to start in terms of research.
Kind regards
Matt
You certainly couldn't hurt anything by having a second, slave/read-only database accessible to your user interface. If done properly, MySQL grants can restrict users to read-only operations, so it's not necessary from a functional standpoint to have a second database. Perhaps, given the nature of your business, there may be a legal reason why you must have a second database though. Be sure to investigate the requirements for protecting PII (e.g. HIPPA)
Security is an ongoing process - part of it is ensuring proper identification and authorization as well as defense in depth - ensuring that the account used to access the database has least privileges and that the surface area exposed to that account is minimal. Also if the database is on the same machine as the web server, then ensuring that a compromise of the web server doesn't also compromise the database.
You also have to contend with the standard social elements - ensuring users have a way to get their first password/setup an account, maintain their own passwords. You should not store their passwords (even encrypted), but instead store only a salted hash. When they forget their password, the reset it themselves, since the web site cannot and should not send them a permanent password via email.
And you should be aware of XSS (cross-site scripting attacks), SQL injection - you should be able to find references to that in most discussions of web application development.

Can passwords for other sites be stored securely?

My university has a portal which students use to register for classes. If you want to get into a full class, you have to keep checking the portal, and sign up when the class has an opening.
I wrote a tool that can check for openings and register automatically, but it needs the students university username and password. These passwords are tied to email accounts, network shares, server logins, and most every other university service.
Is there any way to do this securely?
In security, the most important thing is the "threat model". What kind of attack do you fear?
somebody may steal the computer where this program runs on: put the computer in a locked room.
somebody may hack into the computer and read it from memory: use firewalls and other protection against remote attacks
other users may read the hard disk where the password is stored: only store the password in memory (which would require re-entering it every time you start the program)
the super user may read the password even if it is in memory: only run the program on a computer where you trust the superuser.
etc.
Unfortunately, this is not really possible -- at least not the way you want to do it -- unless the university provides a key-based authentication API. You could always ask them nicely, but they'll probably be too busy to help. If you give your users full disclosure and keep your server secure, it should be enough.
Actually, there is one way to do it through the web without storing passwords -- you could use a Java or Flash app. Unfortunately your users would need to leave the browser open while the app does its work, but this way you wouldn't need to store the information.
You could encrypt the password strings when you store them and then decrypt them when you need to try logging in. Simply generate a symmetric key and use that to encrypt and decrypt the passwords for storage and retrieval (respectively).
You can't store them entirely secure because you'd need to be able to encrypt and decrypt so one-way hash algorithms like MD5, SHA-1, SHA-2 wouldn't suffice. You could look into something like DES or Triple-DES encryption.
I do not think there is. As Martin pointed out one way encryption won't do it for you. Also this will create a maintenance nightmare for you - every time a user changes password you will have to update your data.
I think to make it really work you have to change the design: find a way to do the registration without the user password, i.e. talk to the owners of the app if they would give you an account through which you can do registration on behalf of somebody else