ColdFusion Muse

Securing Credit Card Data

CF Muse Reader Shane Asks:
Hey mark, I'm a frequent visitor to your blog. I'm curious what precautions I should take when dealing with storing credit cards in a MSSQL2000DB. I've done plenty of e-commerce solutions, but haven't done one where I need to store the CC's for many years. I know things have changed. Do I need to encrypt these? If so, what methods do you recommend?

Well this is a huge can of worms. In early 2004 (if memory serves) Visa required all its merchants above a certain threshold that sell on-line to be "certified" as "CISP" (Cardholder Info Security Program) compliant. Non-Categorized merchants - which may be defined as merchants with less than 6,000 transactions a year, no "hack" attempts (pretty vague) and who are not on Visa's radar - have avoided the cost of auditing by keeping a low profile while visa has other fish to fry - but the free pass may be coming to an end. Since "level 1" merchants are anyone that Visa says they are, they can require you to submit to an audit (at your expense) in order to continue processing Visa transactions. Wait.. it gets suckier....

If you are identified as "level 1" you must have an annual onsite security assessment by a crony... er.. company certified by Visa. You also must have your network scanned quarterly by an independent scan vendor. The cost of these changes is enough to make you flock to Paypal.

What's on the checklist

What does it take to "get certified"? The following items are on the checklist. Much of this is "network" related so you may need to talk to your provider unless you host your own.

  • Build and Maintain a Secure Network - This could mean a lot of things. Visa is secure, NASA more secure and DOD very secure. Visa apparently means a Firewall and no "vendor supplied defaults" for passwords. Surprisingly this still ranks near the top on the list of security no nos. The other day I was trying to re-configure my wireless router and it wouldn't let me in, so I tried the default password and I got in. The first thing I did was change the password (naturally) - right before I realized I was connected to somebody else's router. Was I red in the face....
  • Protect Cardholder Data - This means protect stored data from unauthorized access and encrypt the transmission of cardholder data across the Internet. Note: encryption in the database is NOT a requirement. This is talking about always using SSL for web based transactions.
  • maintain a vulnerability management Program - "My name is Mark and I'm an insensitive jerk... it's been 2 years since I last criticized my wife's choice of shoes...." No, that's not what it means. It means to scan for viruses and maintain your definitions and "develop and maintain secure systems". That last one is pretty wide open to interpretation.
  • Implement Strong Access Control measures - This means "need to know" data dissemination, independent logins for network access (no shared logins) and restricted physical access to cardholder data. Presumably it means you can't host your ecommerce site on your laptop at Kinkos.
  • Regularly Monitor and Test Networks - This is referring to an audit trail of access to Cardholder data, and a test of the security systems and processes (again pretty generic).
  • Maintain a Security Policy - This means you have a document stored somewhere in your office that is out of date the instant it was completed.

What is interestingly absent from this list is encrypted data. The only mention of encryption has to do with ensuring the transmission of data was encrypted.

Personal Take

In my opinion you should not choose to store the Credit Card Number in the database unless you have a reoccurring charge - a subscription service. Simply require folks to re-enter that bit each time they purchase from you. If you do choose to store the CC data you should follow the guidelines above (within reason) - even if you are not subject to an audit. Personally, in my view the credit card number should always be stored as encrypted in the DB, and it should never be visible or unencrypted until the time comes to create a transaction. Moreover I would also use the CVV2 value and encrypt that as well. Since it is a check bit of the number and the exp date against a key value (generated by Visa) it is a valuable bit of information - arguably more valuable than the exp. date.

To encrypt I think I would shy away from cfencrypt in favor of one of the many Java based CF tags found on CF Lib.org. I'm sure that on CFMX the cfencrypt tag is safer than it was on CF 5. But since I've been avoiding it for years now, why stop.

One final note, you can also encrypt the network packets to and from your SQL server using built in net libraries. While this is doable it slows down your connection considerably in my experience. If your DB server and Web server are on the same network this might be overkill. If they are not on the same network (not a good idea but sometimes necessary) then I would recommend a hardware solution like 2 pix routers with point to point 3DES. This keeps you out of the business of managing encryption as well as all the other stuff you have to look after on your SQL server.

Resources
Visa CISP Compliance
Merchant Categories

Comments
Peter J. Farrell's Gravatar Great post Mike!

I'm bookmarking it now - so I have some otherside reference when talking to clients.

.Peter
# Posted By Peter J. Farrell | 12/22/05 4:39 PM
mkruger's Gravatar It's Mark - and Thanks!
# Posted By mkruger | 12/22/05 4:41 PM
Peter J. Farrell's Gravatar Arrgh! Mkruger -- didn't look closely at the top of the blog. Sorry Mark...

.Peter
# Posted By Peter J. Farrell | 12/22/05 4:45 PM
Gus's Gravatar I would definitely not recommend storing credit card info at all, encrypted or otherwise. The are many reasons for not storing CC info, encrypted or not.

1) The liability alone is reason enough.
2) Most large CC transaction processors will allow the recurring charges to be billed - keep the responsibility for securing the info on them
3) Even if the data is encrypted, a disgruntled employee or even someone at an ISP may be able to look at your code and decrypt it.
4) There is no reason to store the info!
# Posted By Gus | 12/22/05 5:00 PM
mkruger's Gravatar Gus - all excellent points.
# Posted By mkruger | 12/22/05 5:03 PM
barry.b's Gravatar what is often glossed over is the human element - unauthorised employee (or boss) access to the data.

sometimes CC stuff is written directly into the workflow. With VirginBlue airlines, the CC number is a searchable index field in the database so it can be used to find a customers file. Don't know your resivation number? give them your CC number and they'll find your details....
# Posted By barry.b | 12/22/05 5:21 PM
mkruger's Gravatar Yes - in some ways the whole CC industry is a bit like that story of the emporers new clothes. There are lots of flaws in the way it is handled. It is also so complex - involving so many entities - that it is difficult to control or even wrap you head around.
# Posted By mkruger | 12/23/05 8:52 AM
shane j montgomery's Gravatar Mark,

Thanks so much for answering this question. What a great post. I'm going to try and steer the client away from storing the CC information. It's a yearly subscription service, but I think we can do without the automated re-bill. Thanks again, Shane
# Posted By shane j montgomery | 12/23/05 3:56 PM
mkruger's Gravatar Shane - no problem. Thanks for providing grist for my little blog-mill :) Have a great holiday.
# Posted By mkruger | 12/23/05 4:00 PM
Mike Kelp's Gravatar Storing a credit card # is a massive liability that just isn't worth it usually. Besides there are a lot of tools through credit card gateways that often make storing the CC# unnecessary.

Authorize.net for instance has an API for recurring transactions and auth/charge transactions that is really useful.

Normally what I do is save the last four (to help remind them what card it was) and any billing information other than card # and security code to remember for them.
# Posted By Mike Kelp | 12/23/05 10:57 PM
Michael Dyer's Gravatar Encrypting the numbers before they're saved to the database still creates a big issue: storage of the encryption key. If a hacker can get to the point where they can download the credit card numbers, they can also probably download the code that works with the number and pick up the key from within.

An additional issue is that each of the card numbers is encrypted with the same key. We know how the string length of the card numbers an we know the rules for a valid/invalid card. As a result, the database is a good candidate for a brute force attack.

I would like to be able to store card numbers to provide functionality similar to Amazon (remember my card number), but the risk are definitely very high. My latest experimentation has been with using public/private PGP keys. When the customer signs up I generate a public/private key pair (in memory) and the public key is stored on the server. The private key is provided back to the customer. The upside is that I can encrypt the cards with the public key and the customer is the only one who can provide the password to decrypt. The downside is that most of the customer passwords are very 'guessable' so this solution creates a facade of security but in fact may be very open to attack.
# Posted By Michael Dyer | 12/24/05 7:30 AM
mkruger's Gravatar Michael - thanks for the excellent comments. I agree with you on encryption and on storage. In fact it is my advice to never store the numbers - but if you choose to do it or if you have no choice, then you certainly MUST use some form of encryption.

Your public/private key method has some merit. I like it - but it adds an additional layer of complexity, and I have no doubt that it increases customer service issues. In my experience CS is the most costly part of any online ecommerce venture. How do you handle the situation where a user forgets the password? Do you just do a reset and require new keys based on a hint or something?
# Posted By mkruger | 12/24/05 7:53 AM
Michael Dyer's Gravatar Mike,

I agree with you on the CS issue: the solution has to be transparent to the end-user. I don't really like the idea of having to 'lose' their stored information as a result of losing their password but I haven't been able to think of a way around this yet. I'm somewhat bothered that the end-use can use a 'weak' password but I think I canlive with it since the exposure is limited to their own information and not the entire database. (I could also force the users to use strong passwords).

The best I've been able to come up with regarding a password recovery mechanism would be to keep a second copy of the password that is encrypted with MY public key. Then I could log in, enter my password and process all of the pending password resets. Obviously I would want to automate the reset process but I haven't been able to figure that out yet.

Password changes aren't bad a all because you know the old key and the new key and can re-encrypt the data.

Trying to find a solution for this problem has been frustrating. Google returns a TON of information regarding the VISA requirements but suprisingly little on algorithms. Here's the best link I've found to date (although I don't completely agree with the author on all points): <a href="http://www.unixwiz.net/techtips/secure-cc.html&quo...;. There are also several tools out there to provide table-level encryption for SQL server but the problem of the key storage still exists.

One alternative solution that has been proposed would be to forget about the public/private key stuff and just have a master encryption key that must be entered when the application starts. This master key is stored ONLY in memory and must be re-entered if the server is rebooted, etc. Downsides are that you have to be around with the server reboots. I also think that it would be difficult to hide a encryption key variable within the CF server memory - if it's in memory and the hacker has access to the code then he can write a script to read the encryption key and he's in.

BTW, I'm REALLY glad that you made your initial post as this is a subject I'm very interested in at the moment. I too have looked at the Authorize.net recurring payments API but would prefer to be able to handle the scheduling on my side. The Authorize.net approach definitely has merit (let them deal with the security).

//MDYER
# Posted By Michael Dyer | 12/24/05 8:48 AM
barry.b's Gravatar to play devils advocate, at what point shouldn't a company store CC data? I mentioned VirginBlue airlines searching on the CC field for customer/filght details ***by the customer phone service***... Aparently Richard Branson thinks it's not big deal...
# Posted By barry.b | 12/29/05 10:41 PM
Michael Dyer's Gravatar Barry,


This thread seems to have broken down into two sub-discussions: 1. When should card or other securedata be stored and 2. if you're stuck storing the data, how to do it in a truly secure manner.

Mike and I had a side conversation a couple of days ago about this same subject (at what point shouldn't a company store CC data). Many customers simply don't have the resources or don't have enough business to merit an audit to verify their compliance. As a rule of thumb, I don't store credit card data (or even hashes of cards) unless I have a very specific reason for doing so.

Personally, what I've been looking for is a combination algorithm and system configuration that would allow me to store credit card or other customer-specific information without having to be overly worried about it being compromised. I'm really looking for something to address a situation where the box had been fully taken over and the bad guy has access to the code and database. Many systems give the illusion of security because the card database is encrypted but if you consider a situation where the attacker has the code they suddenly become very insecure.

In our data center operations, we provide an environment for our customers that meets all of the card company requirements so that if they have to be audited we can provide the necessary information on their behalf. We charge a premium for providing this environment and we run firewall, IPS and Vulnerability Assessment solutions to provide the highest level of security against theft. The approach is really to avoid theft in the first place. However, I would still sleep much better at night if there was an algorighm that would allow me to store the data in a way that leaves it open only to a brute-force attack once it is stolen.
# Posted By Michael Dyer | 12/30/05 8:39 AM
robi's Gravatar Michael Dyer,

Both Asymetric and Symetric key managment have the same issue and you are not solving the problem by going to PGP if you are not first solving the problem of secure key management. Its not that big of a deal and there are a ton of open source and commerical tools for securley managing keys. If you are worried abour someone getting on your system and getting your private key why would you not be concerned about someone do a man in the middle on your PGP keys? Also doing full PKI for e-commerce is a great idea and I have done this as well but usally the PIV on the client end is far beyond what your going to get the standard user to do (such as biometrics).
Its far easier, cost effective, and much more practical to just use a Symetric Key and a secure Key Store and following good security practices.
# Posted By robi | 3/23/06 8:24 AM
Fred's Gravatar In order to comply with PCI DSS requirement 3.6, do most people use a key management service or some home-grown method? How do you implement the split knowledge/dual control requirement?
# Posted By Fred | 6/5/07 12:26 PM



Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.