Categories ‐ Tech Thoughts

April 13, 2015

PCI DSS 3.0, Stripe, Braintree, and My Thoughts

In January, PCI DSS 3.0 (the rules that govern payment card data) came into effect and with it major changes to the PCI requirements including the development of PCI SAQ A-EP. SAQs are questionnaires for merchants to ensure their systems meet PCI standards, and the introduction of SAQ A-EP was in response to merchants who do some partial outsourcing of cardholder data. For instance, Stripe, Braintree and others allow developers to collect card data on their site and then send it directly to the payment company’s servers in order to minimize their PCI compliance (the idea being that the actual card number does not touch the merchant’s servers). PCI DSS 2 allowed developers to do this easily and fall under SAQ A, the easiest level of compliance. Under most people’s reading of the new PCI SAQ A and A-EP, collecting data on your site and sending it to a payment processor requires you to comply with PCI SAQ A-EP, which is quite a massive leap – 12 requirements instead of 2, even if the card data never touches your servers. Stripe, however, has updated its javascript library to transport card data using an iframe and has stated that this meets the necessary requirements for their users to maintain PCI SAQ A compliance. Before we dig in much deeper, let’s take a quick comparison between the eligibility requirements for SAQ A vs. A-EP:

SAQ Comparison

The same document that has that above picture clarifies it even further with:

“If any element of a payment page delivered to consumers’ browsers originates from the merchant’s website, SAQ A does not apply; however, SAQ A-EP may be applicable. Examples of e-commerce implementations addressed by SAQ A-EP include:
- Merchant website creates the payment form, and the payment data is delivered directly to the
payment processor (often referred to as “Direct Post”).
- Merchant website loads or delivers script that runs in consumers’ browsers (for example, JavaScript) and provides functionality that supports creation of the payment page and/or how the data is transmitted to the payment processor.”

The development of this SAQ to directly be targeting tools like Stripe.js and Braintree.js. By utilizing a javascript library or a direct post, a developer can create their own form, send the card data to Stripe or Braintree, and then they only have to handle the token on their server. Braintree and the Understanding PCI SAQs docs that I quoted above seem to be on the understanding that these tools require merchants to be PCI SAQ A-EP compliant, (Braintree even provides their merchants with free SecurityMetrics account) but Stripe says that their Stripe.js qualifies for PCI SAQ A. How can they claim that? Stripe’s support site provides some insight.

“For context, the part of DSS 3.0 that’s most applicable to Stripe users is the new SAQ A-EP (Self Assessment Questionnaire), specifically aimed at businesses who accept payment data via a “direct post” (where cardholder data is sent directly to their processor, completely bypassing the servers of the business).
We’ve been working with our Qualified Security Assessor and others to update Stripe.js to meet the new requirements and security constraints, while still keeping it simple to use. The new version of Stripe.js meets these criteria by performing all transmission of sensitive cardholder data within an iframe served off of a stripe.com domain controlled by Stripe. This in turn allows our customers to continue to be eligible for SAQ-A (the older questionnaire) in most cases.”

While Stripe.js transmits the card data to Stripe through an iframe tunnel, the customer still has to enter their card data into the merchant’s site. In my opinion, transmitting the data through an iframe doesn’t meet the PCI requirements for SAQ A. Looking at SAQ A, merchants must confirm that:

“- Your company has no direct control of the manner in which cardholder data is captured, processed,
transmitted, or stored;
- The entirety of all payment pages delivered to the consumer’s browser originates directly from a
third-party PCI DSS validated service provider(s).”

By creating their own form and calling the Stripe tokenization API, the merchant has direct control on which cardholder data is captured. At least I would consider the inputs that asks for the card number, expiration, and CVC, which are developed by the merchant as direct control. Furthermore, it seems like it would violate the “entirety of all payment pages originates from the service provider” provision (though allowing an iframe is a bit of a loose interpretation of this). The card input is on the merchant’s website __not__ on the payment providers.

For comparison, Stripe and Braintree both offer iframe alternatives. With the iframe, the page that prompts the user for card info is loaded from the payment provider. Thus the payment provider, not the merchant, has direct control over how the data is captured, processed and transmitted. Also, because the card data is entered directly into the iframe, the merchant’s website can’t access the card number directly at all.

From some conversations with people at Stripe, the argument they make is that javascript tokenization is just as secure as an iframe and thus the PCI requirements for them should be the same. This is a bit interesting. There is definitely the thought of “if you have malicious JS, then your whole site is compromised”. But with malicious JS they couldn’t access the card data in an iframe, but they could access the card data if inputted directly into your site. An attacker could theoretically change the API key for your tokenization iframe or change the link of the iframe, but that would likely result in lost sales as the tokens are tied to an API key. So it’s much easier for a malicious piece of javascript or something to affect Stripe.js users than Checkout users because of the iframe where card data is entered.

Stay tuned for my next post where I prove Stripe’s theory right and create a malicious iframe that would be invisible to your customers as well as provide some best practices for tokenization.