Ask HN: Does storing CC data in the session violate PCI compliance?

8 points by qeorge ↗ HN
In our app we wish to show an order confirmation screen between taking the customer's credit card data and processing the transaction. To achieve this, the app would need to store the customer's credit card information in the session while we present the interstitial confirmation screen. This would be the only time card data is ever stored by the app.

My question is whether this "counts" as storing card data, in regards to PCI compliance. My instinct is that it would, but I have seen similar payment flows on big-name retailers' websites. As storing CVV2 information is never allowed regardless of the level of PCI compliance, I don't know how they can do this while remaining compliant.

So my question is threefold:

1) In regards to PCI compliance, is there a distinction between short term and long term storage?

2) Is there another way to temporarily store sensitive data which is preferable to the session and adheres to the PCI guidelines?

3) Does this require PCI Level 1 compliance?

I've put a fair amount of time into Googling this and haven't found a clear answer. As so many of us on HN sell products of some kind online, surely someone here has dealt with this issue before.

Thanks for any advice you can provide. If I find a definitive answer, I will be sure to update this thread.

15 comments

[ 3.2 ms ] story [ 39.8 ms ] thread
Storing CC data anywhere is a huge nono. You use it at the moment you pass it on to your IPSP. No temp files, no database records, no session keys none of that.

Read the terms and conditions of your merchant account.

Edit: I'm very serious about this, CC companies periodically check the active merchant accounts and will ruthlessly block you if they see you violate these rules.

If you do recurring billing this can sting you in an extremely bad way, to lose a few days of income is bad, to have to rebuild your member base from the ground up is orders of magnitude worse.

The reasons are simple if there is any indication you store CC data in between pageviews you are literally asking to be hacked. The very best way to handle these issues is to use an IPSP that serves up your final payment page, that way even the form is not on your machine (and so not subject to having a nice little javascript payload embedded in it at some point by some joker that hacks your site).

Unless you are planning on being an IPSP you should not attempt to either receive or store CC info.

Thanks jacquesm. I'm somewhat familiar with PCI standards, and your answer is what I suspected. However, it doesn't totally answer my question, because confirmation screens are quite common. Even meeting PCI Level 1 compliance, and thus being allowed to store the acct #, cardholder name, and expiration date, its still not kosher to store the CVV2 number or track data, so how are others pulling this off?

I know some gateways will run cards without the CVV2 #, but the fees are usually higher. Is the answer then that order confirmation screens and sending CVV2 data are mutually exclusive to all merchants, regardless of their bankroll?

Edit: Unless you are planning on being an IPSP you should not attempt to either receive or store CC info.

This seems a bit extreme. Are you saying no one should build any sort of on-site payment processing into their own site?

We build a lot of e-commerce sites for clients, and our standard MO has been to send the data to the gateway immediately and never store it. With SSL and PCI Level 4 compliance, this hasn't been a problem. In this particular case, a desire for a confirmation page was voiced and we at first sought to examine whether or not this would require Level 1 compliance. Upon digging deeper, I'm now of the opinion that its not possible, even with Level 1 compliance, yet I see this in the wild all the time. What gives?

One thing you can try is to submit the credit card information as an Authorization Only transaction first. Most gateways will respond with a transaction id that you could then resubmit after confirmation from the user as a Prior Authorization and Capture transaction that would complete the transaction. Authorization Only transactions and their transaction ids expire after a set period of time if they're not submitted for capture (e.g., 30 days for authorize.net).

You won't ever have to store actual credit card information in this scenario (just transaction information) and you can freely show the the last 4 digits of credit used.

That's one solution I can think of, but if you can dig up a PCI compliant method to actually store the data, please share.

That's a really good idea Andy, and the gateway we're using in this particular case is primarily designed for restaurants (MercuryPay) so this would be commonplace for them.

I wonder though if its a faux pas to run the card at all without confirming first. I would be fairly upset if a merchant authorized my card (resulting in a hold) and I didn't complete the purchase, but if the authorization is for a short enough time I think this would be OK.

Also, a key function of the confirmation page is to minimize the number of invalid requests sent to the gateway, as too many bad requests can cause them to raise the rates.

I'm starting to think there is no PCI compliant way to store a CVV2 for any period of time whatsoever, but I'm also incredulous that so many brand name merchants would so wantonly violate the policy. Perhaps with enough volume and Level 1 compliance the gateway will make an exception.

The customer should not normally see any started but not completed transactions, but there have been cases where this data did become visible leading to lots of confusion.

Confusion = Chargebacks.

So you have to make really sure that there is no way the fact that you did that gets back to the customer.

Are you doing your own scrubbing ? Or do you purchase a scrubbing service from the gateway provider ?

The gateway is not the one that decides if you can store CVV2, the card companies make that decision. The rules for that are available, it's a fairly strict standard though.

Encrypted harddrives, all kinds of physical security.

I'm guessing that that is the reason why you see big name merchants do this, but hardly any little ones.

I know of one company that actually set up an IPSP just for that purpose. They now make more money on that part of their business than on the original business...

Jacques makes a good point that you should be careful with customers seeing started but not completed transactions. Any confusion on the customer's part is bad news.

If you're going to go the route of authorization only then capture, then I'd suggest that you invalidate authorizations yourself after a set period of time (maybe a few minutes?) rather than let the gateway invalidate it based on their criteria. This doesn't, however, solve your problems with the number of requests sent to the gateway.

I don't know much about MercuryPay (and their website is scarce on in-depth developer info), but maybe you could work with them on posting payment information and holding it until the transaction is confirmed?

I'm guessing - without further information - that some of these people are not aware they are crossing the line, or that they have very special arrangements with the CC companies regarding the machines where this is happening.

The demands on such a situation are pretty draconic, one step shy of having an armed marine in front of your server, otoh you have to sympathize with that since any machine that stores this information - even if only for 30 seconds - is with a high enough volume of cards a disaster waiting to happen.

The rules are pretty straightforward, I've never been tempted to store CC information anywhere.

For the record, a friend of mine runs a fair sized (E 150M+ / year) IPSP and I helped implement some of the bits, notably vbv, and yes, we do store the CC information there but those servers are in a class of their own with respect to security, nothing that I could justify for the sake of having a confirmation form.

As to not building any kind of on-site payment processing into your site, yes, you can do that but you really should not want to. After all the target profile of your site goes up tremendously if you do that and you get very little gain for it back (the payment page is still on your server).

That leaves all the employee and sysadmin related risks unmentioned, but those are unfortunately a reality as well.

Most IPSPs (or at least the half decent ones) allow you to upload the registration form to their server. The idea is you pre-capture all the fields that you are interested in on a form on your site, the submit then populates the authorization via an underwater call to the server of the IPSP, then you redirect the user to your form on the server of the IPSP where they get their choice of credit cards and enter other sensitive information. That's where the final confirmation screen sits.

The only really big downside here - and it is a serious one if your IPSP is not solid, which unfortunately has been the case several times, see DMR and IBill) is that if your IPSP bites the dust you lose the CC DB. This sucks royally, so you should limit your choice of IPSPs to those that require you to run your own merchant account. That way you are 100% sure that some other joker running fraudulent or wrongly tagged transactions is not going to cause your business to fall over one fine idle Tuesday.

Storing the CVV2 data is out even for IPSPs, they only use it to verify the card at the moment the pre-auth for the first transaction comes through, after that it simply says 'verified' in their records, no need to store the CVV.

> We build a lot of e-commerce sites for clients, and our standard MO has been to send the data to the gateway immediately and never store it.

That's the way to do it.

> In this particular case, a desire for a confirmation page was voiced

Doesn't your IPSP provide you with this function ? After the confirmation they are allowed to send you back all the relevant information under water or in a POST to the return page, whatever works best (I prefer the under water system because it stops people from attempting to mess with the post fields).

You are definitely asking the right questions here, as to how 'others' are pulling this off I'd have to look at specific examples and I might be able to tell you. I know some of the larger operators are willing to pay a premium to be able to hold on to the card info for various reasons but usually they find that the best way to do this is to abstract out this portion of their business and spin it out as an IPSP.

It makes sense, because the investment is a sizable one and it is good business once you have the tech you might as well sell it as a service.

EDIT: Theory about how you could make this work: You could simply send all the data back in the form in hidden fields, show whatever you want to show (last four digits of card numer, no CVV), ask the user to confirm which re-submits all the hidden fields and then go to the IPSP for the transaction. That way you get your confirmation form and you do not store any...

> I'm guessing - without further information - that some of these people are not aware they are crossing the line, or that they have very special arrangements with the CC companies regarding the machines where this is happening.

I think it has to be the latter. I would expect any good auditor would notice this and flag it, but perhaps I'm being naive.

> The rules are pretty straightforward, I've never been tempted to store CC information anywhere.

I agree. In this case we'll just skip the confirmation screen, possibly using JS to simulate one where its available. Its frustrating though, because I hate impacting the customer experience because of technical issues (especially in e-commerce).

> Most IPSPs (or at least the half decent ones) allow you to upload the registration form to their server. The idea is you pre-capture all the fields that you are interested in on a form on your site, the submit then populates the authorization via an underwater call to the server of the IPSP, then you redirect the user to your form on the server of the IPSP where they get their choice of credit cards and enter other sensitive information. That's where the final confirmation screen sits.

What's a good IPSP to use for this? Would we be able to mask the URL with one of our own, provided we buy our own SSL?

I've looked at PayPal's Direct Pay, Mercury Pay, and several others but haven't found one that provides a good user experience, allows us to mask with our domain, and allows the branding we need. FoxyCart.com looked promising, but they don't support users without Javascript, so that's a non-starter (and illegal).

>> We build a lot of e-commerce sites for clients, and our standard MO has been to send the data to the gateway immediately and never store it.

> That's the way to do it.

Thank you, very good to hear confirmation on this.

> Theory about how you could make this work: You could simply send all the data back in the form in hidden fields, show whatever you want to show (last four digits of card numer, no CVV), ask the user to confirm which re-submits all the hidden fields and then go to the IPSP for the transaction. That way you get your confirmation form and you do not store any data at all, it's either in the users browser (their risk) or underway to the IPSP, the only time it is on your server is the exact moment you pass it on.

This was actually the method we used during the initial build, just as a placeholder. But it just seems so inherently wrong.

My fear would be these pages being cached, and then the customer's CC info would be sitting on disk waiting for a piece of malware to find it. I know we could send a no-cache header, but I don't trust the browsers to honor the directive. And even though the risk would be offloaded to the user, we still want to avoid putting their data in harm's way whenever possible.

I really appreciate all your thoughts on this matter. I feel like this is a big blind spot for many online merchants, and is worth getting right.

This is getting long :) Feel free to email me by the way.

Tegarding the 'auditors', mistakes are made, it happens and not all audit rounds are equally good. Some are downright ridiculous (telling you to change stuff the previous audit told you to do).

I don't think it is appropriate to advertise any IPSPs here, the biggest things to look at are segregated merchant accounts, how long have they been in business, hold back period, fees, integration capabilities, customer service department reputation and references.

Roughly in that order.

It also helps if they process a sizable volume so that when there is a problem it is not just your problem.

Masking your own URL is the one thing that always seems to come up as a 'desirable' because nobody likes to send the customer elsewhere at the moment of making the sale.

But in practice it doesn't really matter much, as long as you get editorial control over the content of the landing page on the IPSP side and the customer is aware that a transition is going to happen and they get back to where they were on completion of the transaction. The latter is very important.

If your IPSP can not give you that sort of functionality then it might be problematic, it could cost you sales.

Using your own SSL certificate is not going to be enough to mask the IPSPs URL, after all, once the data captured gets posted you are on their domain anyway. I personally prefer to have the transition happen at the same moment you go from unencrypted to encrypted, that way you sort of guide the customer to the very last step before the payment happens. Depending on your environment that means they've filled up their cart or selected the type of subscription they wish to purchase and then the next click will take them to the 'checkout' where their payment information is captured.

I agree the repost seems wrong, but the good news here is that if you are in https anyway then caching is not your problem. No browser or proxy will cache that stuff, if it has passed there once during the post it might as well pass twice more, no harm done.

The only thing that is vulnerable to is mitm and by that time that has already happened, the only difference being that your mitm now has three copies of the data instead of just one.

IMHO, eliminating any potential source of confusion from a checkout flow is worth doing, and so masking the domain is usually worth it. And although we know it doesn't make a difference in practice, customers and clients don't like it.

Your point about SSL and mitm makes sense. I'll look into the idea of temporarily storing the data in hidden fields, and if I find anything definitive I'll be sure to update.

Thanks for the followups, I greatly appreciate your help. If I have further questions I will email you.

I've heard of companies having an internal policy: if in memory (in their data center's control) PCI sensitive data was allowed.

In some cases (memory mapped files) it could persist to disk, so either encryption, or a Compensating Control Document was created (limiting access to the filesystem).

The order confirmation screen only needs to display the last 4 digits. They know the rest. If any of the other digits were entered incorrectly, you'll both find out soon enough.
Yes, but the question is how do you keep track of the real information between the page views? The obvious answer would be session variables, but this still means the data would be stored briefly in the server's memory.
Use Javascript to change the caption of the submit button from "OK" to "Confirm" the first time it is pressed and then submit the form on the second press. That way, the data doesn't reach your server until the user has confirmed the purchase.