We at O’Reilly just got bit on perl.com, which redirected to a porn site courtesy a piece of remotely-included Javascript. One of our advertisers was using an ads system that required our pages to load Javascript from their site. It only took three things to turn perl.com into porn.com: (1) the advertiser’s domain lapsed, (2) the porn company bought it, (3) they replaced the Javascript that we were loading with a small chunk that redirected to the porn site (note that nothing on or about perl.com changed). Our first concern was that we’d been hacked and “run this remote Javascript” inserted from our servers without our knowledge, but that hadn’t happenedâ€”our change records and RT logs show we’ve had that Javascript and advertiser since May 2006.

There’s nothing especially new about this; the external Javascript model has always been in place, long before Ajax and widgets. Yet, with widgets taking off, more and more users and developers are cutting-and-pasting script tags into their web pages, pulling in code from a wide variety of providers, big and small. How well equipped are publishers to decide which is safe and which is not, and deal with situations like O’Reilly experienced, where someone takes over an expired domain?

This is a general problem about having Business Logic in JavaScript which I have written about several times… ;)
We have a model where no BL is written in JavaScript but rather on the server which removes a whole slew of problems, this one too in fact…
Another thing it removes is the whole “Ajax is insecure” thing since everything executes on the server and as long as your server is secure then your Ajax Solution is secure since everything you do you do on the server.

This does raise an interesting problem that is hard to solve. Partnerships that involve running remote javascript are an important part of a lot of web sites. Its a powerful technology, allowing richer ads, content syndication, and outsourcing of page components, so business logic in javascript isn’t going to go away. It does increase your attack surface because a compromise of any of your partners can effect your site, as it did here.

You can’t really do any sort of validation in javascript, because the logic to do so would be out in the open and easily faked. I think a hybrid approach might be the best solution. Have you server do a “secret handshake” with the partner every so often, and if it fails then don’t display the script tag for their service. The handshake could go as far a cryptographic signing system that requires active support on the partner’s server, or it could be a passive system that checks for the existence of certain hidden urls and that the whois information hasn’t changed.

Secret handshake using public and private keys would take no more effort than HTTPS. It’s where everything is headed.HTTPS itself shouldn’t be considered secure since many just hit OK/Continue when the dialog pops up saying there is something wrong with the cert.

Perhaps domain-aware JS would help, whereby script called from a remote domain would not have permission to set window.location and so on. “Then again”, this may not really work as any CDNs serving JS would then have issues (Akamai and so forth), despite being used for legitimate purposes. There is a lot of implicit trust in the ad model, this is an interesting (and unfortunate) example of that breaking.

Safe JavaScript subsets are a good option. ADsafe.org and Caja are two examples. They can work, but it is difficult to have confidence in them. It seems almost certain that new holes will be discovered which will render them useless. So in my view, safe subsets are at best a short term solution. I say that as the developer of ADsafe. I know the guys doing Caja. They are really smart, and I think Caja is good stuff. But I think they would agree with me about the vulnerability of the platform.

So we should proceed on the next level, adding communicating vats and modules. This will at least give us cooperation and better containment, but we will still be subject to XSS attacks.

XSS is a direct consequence of the design of JavaScript. JavaScript is an insecure language that invites XSS attacks. The current ES4 proposal preserves the weakness in favor of compatibility, so it is not a solution.

Ultimately we need to replace JavaScript with a secure language. That is the only way to protect our sites and our users from XSS. It will take a while to get such a thing designed, implemented, tested, standardized, and deployed, so we should proceed on that as well.