12

My company makes a JavaScript widget that e-commerce sites can embed on their pages. Our current instructions to our customers tell them to load our JS on every page of their site and most follow this advice to the letter, even including it on their pages with credit card forms. I have been petitioning for us to change the instructions to "load on every page except the one with the credit card form", but I have not yet been successful.

My company's primary concern is that our customers will put us through extra scrutiny or otherwise conclude that our product is insecure and that we will loose business as a result of this. They also do not believe that there is a significant risk in having our JS on the credit card page.

Update: As BrianAdkins mentioned below, I had already suggested that we send our clients a short snippet of JavaScript that checks the URL and then adds our <script> element only if URL isn't a match for the checkout page. But it was met with the same opposition as before. There were also concerns about what if the url changed or how to handle situations where we can't tell if it's a CC page or not from the URL. (We have at least one customer where this is the case.) So my original request still stands.

What I'm looking for is:

  1. Facts: Are there any examples of business that have been compromised this way? What was the outcome?

    • Or, alternatively, is there any data that shows I'm wrong and that this is only a theoretical issue that doesn't happen in practice?
  2. Perception: What can we share with our customers to counter the idea that being concerned about security indicates we're less secure?

    • For example, does including third-party JS on the CC page violate PCI-DSS? "Requirement 7: Restrict access to cardholder data by business need to know" sounds like it might, but I don't see anywhere where it explicitly discusses this situation.
Nathan Friedly
  • 221
  • 2
  • 6
  • Question. If it's a widget...why not just sandbox it within an iframe? It'll be off-site so the IFRAME won't be able to ping the outside or vice versa. – Sébastien Renauld May 15 '13 at 20:28
  • This particular widget needs to access the HTML of the page and also interacts with the Facebook JS SDK which checks that the domain matches the given application ID. – Nathan Friedly May 15 '13 at 20:34
  • 1
    It was just an idea. Looks like you don't really have a choice - but you'll need to make sure no-one can rewrite your JS, which involves a hefty amount of security auditing. – Sébastien Renauld May 15 '13 at 20:36
  • Yea.. our scripts get rewritten by automatic processes fairly frequently. (We bundle the code + the customer's configuration into a single .js file - so it gets rebuilt any time either of those changes.) And a number of employees have access to the server that stores them. That's probably an additional area where we could improve security. But it doesn't really solve the initial issue that my company shouldn't be able to trivially get credit card details from our customers' users. – Nathan Friedly May 15 '13 at 20:47
  • 2
    Let's stop getting ahead of ourselves here. The company considers you a trusted third-party, so it **should** be trivial. However, you need to audit your employees and make sure they **cannot** make such changes. That's your job. The attack vector is modification of that JS file by a malicious user - make sure it can't happen. – Sébastien Renauld May 15 '13 at 20:56
  • That's a good point. – Nathan Friedly May 15 '13 at 20:58

5 Answers5

6

Most ecommerce sites include google analytics code on payment pages. Payment pages are also a prime candidate for a/b testing using JS tools such as optimizely or visual-website-optimizer.

There are also integrations to third-party product subscription engines that rely on JS passing CC data from the cart back to the service's mother ship (e.g. Ordergroove) via https.

Many ecommerce platforms make it easy to include a widget on all pages via a templating system, but difficult to exclude just a single page in the conversion funnel.

One option might be to wrap your widget in a bit of JS that ends up NOT including your remote code in instances where the URL matches a specific pattern. This would allow your customers to place the code everywhere (in all templates), while easily preventing the execution of your code on specific pages. This could be delivered as alternate installation instructions.

Brian Adkins
  • 1,817
  • 1
  • 17
  • 14
  • I had actually suggested the "check the URL and not load our JS" but it was met with the same opposition: it could be perceived as indicating our JS was insecure. I'll update the question to note that though. – Nathan Friedly May 15 '13 at 18:17
  • In your documentation, there's no need to state why a customer might want to exclude your code from execution... Leave that to the customers. Just provide the flexibility should they encounter any situation where they might need it... Could be a log-on page... Could be a payment page... Could be a private page, etc. – Brian Adkins May 15 '13 at 21:08
3

If I understand correctly, you are trying to proactively protect your clients from the perception of potential risks by suggesting that your own code should not be run on certain pages. Your efforts might not be necessary.

Let your clients protect themselves by letting them choose for themselves. Alter your documentation to say, "install on every page, but pages with CC process may be safely omitted."

schroeder
  • 123,438
  • 55
  • 284
  • 319
  • I think that's an improvement but still not enough to sell it. I want clients to both be more secure (important to me) and come out with the perception that my company is protecting their security, not that my company doesn't trust the security of our own software (important to management). – Nathan Friedly May 15 '13 at 18:29
  • 2
    As a 3rd party provider, you can't be responsible for client security beyond your own code base. Pushing your company and theirs into territory that is not your direct responsibility is going to be tough at best, and the fruits of your efforts undefined. You are at the wrong spot to have any leverage, and the leverage you do have is small, even if you were in the right spot. In terms of 'picking your fights', I would advise looking for better fights. – schroeder May 15 '13 at 20:52
  • Yea.. as much as I don't like it, I think you might be right. – Nathan Friedly May 15 '13 at 20:57
3

I have yet to encounter any security best practice that says "All JS scripts should be omitted when presenting web pages with personal/credit card data".

Is there a way to hack your JS Widget in such a way as to pose a threat if the widget and customer credit card data are on the same page? Maybe. You'd need to really review the widget, and how it can be compromised - it's more of a design question than a blanket rule.

In terms of compromise examples - they are always few and far between - unless they are notorious, most companies don't publicize them. Your best bet is to check for OWASP guidance and the vulnerability publication sites to see if there's any particular JS alerts connected to anything in your widget.

In terms of rules to live by - common best practice is to keep your implementations and interfaces simple, clear and subject them to careful review. Putting the JS widget in places it's not needed may violate that premise by adding unnecessary complexity. OTOH - asking customers to find a way to omit it only from payment/login pages may induce risk-causing complexity in the customer code. No way to tell without sitting down with each customer's architecture.

bethlakshmi
  • 11,606
  • 1
  • 27
  • 58
  • I'm not aware of any exploits against my widget, but it also loads other libraries including Facebook's JS SDK - which changes almost daily. – Nathan Friedly May 15 '13 at 20:41
1

Many such "helpful" widgets are often loaded using direct cross-site <script> tags, this is a real do not do until you have established the legal liability matter clearly. As usually all liability rests with the card processing entity (the web merchant or card processing gateway) not with the widget author entity.

As a merchant or PCI card processing gateway allowing your 3rd party JS on our card data handling pages would require full indemnity from you with proof of past, present and future business insurance to cover the potential liability to our business. It does not actually matter if you "say" have you "procedures" in place to stop a rogue employee from doing something evil in JavaScript, what matters is legal ass covering between businesses. That is the main reason PCI exists to pass liability away from the card issuer / card network and onto the merchant / card processor.

Another strategy is to request such widget authors provide a download ZIP of static data that can be audited/checked by the merchant or PCI card processing gateway technical engineers for possible problems and evil activity. Then this static version of the widget is served up from the merchant's own system. This of course means getting it updated is a pain for the widget author since they need to ensure long backwards compatibility or risk customer annoyance. Since often it will never be updated by the merchant that would required expensive web development skills.

Another strategy is for the widget author to provide a real supported API which the e-commerce merchant can interact with the widget authors system using controlled code. This would be similar to the static JS but handled server side. Widget authors stay away from this solution as it is usually a too expensive option for merchants to adopt the widget, compared to the lazy adding a <script> tag and loading cross-site.

The alternative is usually much easier, to simply not use such a widget and save yourself from the risk.

To explain the attack vector it is possible for evil widget author's hosting system to serve up different versions of the JS to different users, maybe using Referrer header, randomness, country, time-of-day, etc... So one in 10000 hits gets the evil version of the JS code. But all casual inspection appears to serve up the correct good version of JS code.

Like all JS code, the evil version of the JS can read all form data fields during the submit process by attaching itself to the forms of the page. All data (including CVV/CSC, address info as well as usual card data) that is on the form is then relayed to more than one website when the unaware customer (there will be no alerts or warnings) performs the submit action. The data is then copied to both the site it should be going to (the merchant or PCI card processing gateway) as well as the evil site collecting data for evil purposes.

IFRAMEs are also not perfectly safe encapsulation mechanisms, problem have existed in the past that permitted things that should not possible to be circumvented by evil JS code. Not everyone updates their browser.



No amount of yes we have "secure" procedures double-speak from "helpful" widget authors is going to assist the PCI compliant entity when a problem occurs; and don't be fooled otherwise.



I have personally brought it to the attention of at least two UK operated PCI compliant card processors of their direct <script> third-party cross site elements on pages presenting or receiving security (username / password) or card holder data. The problem for them is that it just isn't worth the risk to their business and bad publicity as a result of a breach due to incompetence.

These things come to your attention very quickly when you provide a secure system and network for your merchant accounting department to access payment data but only allow internet connectivity via firewall/proxy with white-list access only to the specific systems they expect to use, it is amazing how much stuff breaks that shouldn't.

Asking for an example of a breach is fruitless, no one advertises such as thing.

Hypothetical technical fix (or rant depending on your viewpoint)

What HTML really needs is the ability for the original origin server to provide one or more checksums (MD5/SHA1/etc) and length information of the target script. This way it is possible to the consuming website to have complete control over the exact copy that the browser will accept from the serving website.

<script src="http://mostly.trusted-site.com/useful-script.js" security:checksum="md5:0123456789abcedf;sha1:0123456789abcdef0123;length:543" security:options="load-from-cache-from-anywhere-matching-checksum;no-send-referrer-header;no-use-cookies;no-use-etag;high-security"></script>

This script tag is hypothetical (do not use) but where HTML needs to move towards. It serves to illustrate a potential future HTML5+ fix in the problem domain.

Now the target site can not change the content from under us, they get to see the hits and serve the content. Multiple parties across the internet would independently audit the same code allowing many eyes of peer review of the same JS code for evil things, as you can build trust around checksum values.

Multiple hashes are allowed to support overlapping migration to more secure/longer/widely-supported hashes, also reduces theoretical chance of collision.

Allow loading from cache from any alternative website that has same checksum matches (allowing for zero-hit CDNs which are the fastest CDNs you can get, finally you get to go back to your server again). Since you can have your own local copy of jquery.js but allow the client browser to satisfy the script completely from cache when if loaded from another website. Since for most users there will never be any hit for jquery.js on any server (not even to revalidate) as it will resolve from cache.

Get to control what identifiable information the clients browser will send by default when accessing the URL to download the script. You can hit it without Referrer header, never sending or storing any cookies, same with ETag, etc.. I illustrate the use of "no-" implying a default of these things being allowed, the default should be the reverse, all things inhibited unless allowed. The "no-" is to illustrate the kind of information control the consuming website can obtain.

Until this happens simply copy the JS into your website (after you audit it)

Darryl Miles
  • 151
  • 3
0

To me, there are no inherent risks to allowing the widget on a CC processing page. There are many sites that have various snippets on these pages (like Google analytics). Your code doesn't have access to the CC information on the form unless it's coded to do so anyway, plus the code's should be on their server anyway so it couldn't be modified maliciously.

Nathan C
  • 800
  • 6
  • 9