Alastair’s Place

Software development, Cocoa, Objective-C, life. Stuff like that.

Don't Bash Iframe Payment Forms


OK, some background first. Owing to the increasing level of card-not-present fraud committed via the Internet, and the generally lax security standards of some of the websites involved, the Payment Card Industry Security Standards Council (PCI SSC) was formed and tasked with creating and maintaining a set of security standards called the Payment Card Industry Data Security Standard (PCI DSS).

The idea is a good one, as are many of the rules themselves, though I think it’s legitimate to criticise PCI-DSS for demanding things of smaller businesses that are simply unrealistic. The upshot of this is that smaller companies, and the payment processors who serve their market, wish to avoid the burden of being PCI compliant, but because they know that conversion rates are strongly impacted by being sent to a third-party site for payment, they would also like to design payment flows where a small business is able to take card payments on its own website.

The first attempt at this was to use client-side Javascript to securely encrypt the user’s payment data, and then the payment form itself would be submitted to the merchant’s system, but with only the encrypted blob rather than the original payment details. The downside of this approach is that if something goes wrong with the Javascript code and the HTML form isn’t carefully written, payment details go to the merchant’s server anyway and they are dragged into the scope of PCI compliance.

This method of avoiding having to be fully PCI compliant was “dealt with” in PCI DSS 3.0, which specifically imposes a compliance burden on sites doing the above.

However, PCI DSS 3.0 does allow payment processors to host parts of the payment form on their own servers instead, such that the merchant can embed those parts into the merchant’s own form using HTML iframe tags. This provides the same visual effect, but at reduced risk because it no longer relies on client side Javascript to keep the payment data away from the merchant’s servers.

So, that’s the background.

Why am I writing this?

Now, on Troy Hunt’s blog, in the comments, I happened across some remarks from Craig Francis:

This Stripe implementation is insecure as well.

They use an iframe, which is trivial for a malicious hacker to replace if the original website is hacked (often possible as they use old software, FTP, bad passwords, etc - which all gets missed at the basic level of PCI checking, that Regpack also seem to suggest is acceptable).

Troy is right to suggest that you should go to the payment gateway directly to enter your details, at least customers will know who has them.

I’m currently working with Christine at Google to pressure the PCI council into doing something about this.

Craig then linked to this piece on his blog which advocates extending full PCI compliance (technically SAQ-A-EP) to those businesses who are using iframe-based payment systems.

This would, in my opinion, be a huge mistake.

The claim, basically, is that an iframe-based system is insecure because a third party could edit the page in which the iframe is embedded and make it point somewhere else. This is true, and it is a genuine vulnerability.

But what are the alternatives for smaller businesses? Well, the alternative being suggested is that they should send their customers off to a third-party payment processor’s website, have the details filled in there, and then come back again. Those of us who run small businesses that take card details will tell you for nothing that this causes two problems:

  1. Our conversion rate drops. Instantly. Customers don’t like being bumped to another website, which they probably don’t recognise anyway, to make a card payment.

  2. We actually get people e-mailing us to tell us they think they might be being defrauded. Wait, what? Yes, that’s right. Customers don’t expect to be suddenly redirected elsewhere; when it happens, they think something dodgy is going on.

Now, if your goal is to destroy small business and make the huge advantages experienced by big businesses even bigger, that’s a great idea. What it won’t do is improve security. Why? Because passing customers off to a third-party payment website has the exact same vulnerability we were just talking about. The web page that does it could be edited by a malicious third party, and pointed at a different page.

OK, you might say, but in that case you’ll see it in your browser’s address bar. Sure. Do you know the names of every payment gateway on the Internet? No, me neither. So how do you know that the page you’re looking at is a genuine payment processor? If you’re about to utter the words “they have an EV SSL certificate” or “because my address bar is green”, I have news for you: it’s easy to get an EV certificate. Even if we assume that certificate authorities can’t be convinced to issue EV certificates in error, all the certificate really says is that it belongs to the party listed in the certificate details. It doesn’t tell you they’re trustworthy.

What should happen?

So Craig’s assertion that merchants using the iframe approach should be forced to use SAQ A-EP, the more onerous compliance route, is clearly a non-starter. It doesn’t improve security in practice, and has a significant impact on lots of small businesses, most of whom will be forced to use third-party payment gateways, which is not only bad for business but is annoying for their customers too.

It’s also worth pointing out that, assuming we did tighten up this aspect of PCI DSS, there is still nothing stopping someone from setting up a website with a similar name, copying its appearance from a given merchant’s site, and defrauding customers that way. This is exactly the same kind of fraud we’re worrying about here – customers are being sent to a site other than the one they should be being sent to – only now it would be happening via Google, instead of from the merchant’s own (hacked) page. Should Google search suddently be dragged into scope for PCI DSS somehow? I don’t think anyone sensibly argues that.

This is a hard problem, and the iframe solution is not perfect, but it is an improvement over the client-side Javascript approach and it isn’t significantly less secure than redirecting to a third-party website to perform the payment.

The way forward is probably services like Apple Pay, which is now available in Safari 10, where the browser is responsible for capturing the payment information and sending it securely to the payment processor. Even that is not perfect – hackers could still change the merchant’s site to point at a different payment processor and try to collect money that way.

But aren’t servers insecure if they aren’t completely PCI compliant?


Nor are completely PCI compliant systems necessarily secure.

PCI DSS compliance means that the system in question ticks all the relevant checkboxes in the latest PCI DSS standard, meets any audit requirements and has the appropriate paperwork in place. There’s a good chance that systems that are PCI DSS compliant are secure, but it isn’t guaranteed.

Why, if your system is secure, would you not want the burden of PCI DSS compliance? Well, unless you think that all small businesses’ websites (and we’re talking about sites here that explicitly avoid touching payment data) need automated audit logs, two factor authentication, sophisticated penetration testing, incident response plans, written security policies, written change control procedures, separate logging servers, and so on, I think you already know the answer to that question.