2

I have a website where people can make purchases.

The entire website is served with https.

On the first page, I accept user profile data and generate a random ID for my client and store that in my database.

I then pass the user ID to my second page where I accept user credit card data. When the user submits their information on this page, I make a POST XMLHttpRequest to a server API that I control, sending over the credit card data and the user ID.

This server API then queries my database using the user ID, and if it finds a match, then proceeds to send the credit card information to my payment processor. I am essentially using the user ID as my API key.

The credit card information would never hit my server. Since I can't store my API key client side, I am instead generating 1-time user IDs to validate API calls. I would need to update my database so that the same user ID couldn't be called again to validate my API.

Would this be secure? My limitation here is I am using Weebly, which I do not believe allows server side code. So instead I'm figuring out another way to validate API calls.


This question is based on a similar question

I wanted to preemptively address some of the attack vectors in the top answer:

1) Leaked credentials

This seems like the main vulnerability with client side API calls. However, I am creating a 1-time user ID, which is validated and essentially acts as a 1-time API key. So there is no leaked credentials, as all credentials can only be used once.

2) Altered order data

The user data (e.g. billing amount) would be validated against my server side database. The only thing they would have control over would be their credit card number and user ID.

3) Hijacked calls

I suppose there is no CSRF that can be done here.

4) Open API

I guess anyone could send a request to my API. I could whitelist my API to a specific IP (however Weebly sites share IPs) and set up throttling.

  • I think this is similar to authorize.net – bones225 Jul 24 at 18:24
  • 1
    It looks like the link you intended to add to the related question is missing. – Xander Jul 24 at 18:49
  • You say you send the data to an API you control, but you also say it never touches your servers. Both can’t be true - even if you’re not storing it at all, it’s transiting your server in plaintext, and thus it does touch your server. – Bobson Jul 25 at 11:28
  • @Bobson Gotcha, you're right. Sorry, I think I was using the "touching server" term incorrectly then, I intended to say I wasn't writing it to any server. – bones225 Jul 26 at 6:20
2

This is potentially a reasonable approach, but it comes with some conditions that may not make it palatable for you to use.

Before I begin I think it's worth me mentioning that I worked for a PCI ASV/QSA organisation for a number of years and performed quite a few PCI assessments during that time. I'm a little rusty on the very latest standards but I don't think anything I mention here has changed significantly since I last worked on this stuff. I am, however, just a random dude on the internet, and you should speak to your PCI QSA and payment provider directly (which may be your bank) to ensure proper adherence to requirements. PCI DSS compliance is usually a contractual obligation with your payment provider or bank, and failing to take the necessary steps to be compliant may land you in breach of contract (or worse, investigated by your jurisdiction's data protection ombudsman).

The PCI Security Standards Council published a document called Best Practices for Securing E-Commerce which I suggest you read, as it is a very useful document. It outlines the best options available for merchants who want to have payment facilities on their website but don't want to have to go through the hassle of PCI DSS certification.

The document calls the method that you're proposing the "JavaScript Form process" (see Section 2.4), and it considers it to be roughly equivalent in security to a direct form POST process where the customer enters their payment information into a form on your website and it posts the content to the payment provider.

The document provides a reference example as to how this should be implemented. However, it is important to note that they also state the following:

Merchants using a JavaScript e-commerce implementation may be eligible for PCI SAQ A-EP, providing they meet the eligibility criteria of that SAQ. Merchants should consult with their acquirer (merchant bank) or with the payment brands directly to determine whether they are required to validate their PCI DSS compliance and which reporting method they should use. SAQ A-EP for PCI DSS v3.2 currently includes 191 requirements.

What they mean by this is that, if you meet certain requirements, you only have to be certified as PCI SAQ A-EP complaint by a PCI QSA (Qualified Security Assessor) instead of certified for the whole of PCI DSS like a payment provider. The PCI SAQ A-EP requirements effectively state that if you're not touching card details, never retain any card details, use a PCI DSS compliant payment provider, and only control the web page into which card details are entered before being sent directly to the payment provider (either by POST or XMLHttpRequest) then you "only" have to get certified to the less-comprehensive PCI SAQ A-EP standard by a PCI QSA.

Ultimately what this means is that if you use the direct form POST or JavaScript form methods, you still need to get assessed to SAQ A-EP standards. The overview of the standard requirements is as follows:

  • Requirement 1: Install and maintain a firewall configuration to protect data
  • Requirement 2: Don’t use vendor-supplied defaults for system passwords and other security parameters
  • Requirement 3: Protect cardholder data
  • Requirement 4: Encrypt transmission of cardholder data across open public networks
  • Requirement 5: Regularly update anti-virus software
  • Requirement 6: Develop and maintain secure systems and applications
  • Requirement 7: Restrict access to cardholder data by business need to know
  • Requirement 8: Identify and authenticate access to systems
  • Requirement 9: Restrict physical access to cardholder data
  • Requirement 10: Track and monitor all access to network resources and cardholder data
  • Requirement 11: Regularly test security systems and processes
  • Requirement 12: Maintain a policy that addresses information security for all personnel

The full standard goes into specific details about what does and does not constitute satisfactory adherence to these requirements.

If all this sounds way too complicated and costly, don't worry, because there's an alternative. If you look in the best practices document I linked, in section 2.2, they describe an iFrame approach. In this approach you put the payment provider's payment page inside of an iframe, thus having the payment information (card details) entered into a page whose security origin cannot be tampered with by scripts running on your page due to the Same Origin Policy (SOP). This carries with it a greatly reduced set of compliance requirements:

Merchants using an iFrame e-commerce implementation may be eligible for PCI SAQ A, providing they meet the eligibility criteria of that SAQ. Merchants should consult with their acquirer (merchant bank) or with the payment brands directly to determine whether they are required to validate their PCI DSS compliance, and which reporting method they should use. The PCI SAQ A for PCI DSS v3.2 questionnaire currently includes as few as 22 requirements.

As you can see, you're going down from 191 requirements to as few as 22, which is much simpler and cheaper. This also reduces the amount of development you have to do on your side of the fence, because everything is handled by the payment provider via the frame.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.