

Tell HN: How to keep CA Security Suite from breaking your app - asuth

Hello HN:<p>I've been lurking for a long time but tonight I discovered interesting that I thought I should share.<p>I run a large site with lots of users, and we occasionally get mysterious bug reports about things just plain not working. We got one of these a couple days ago so I decided I'd try to get to the bottom of it. I got on the phone with this user and spent 45 minutes trying to figure out the problem. She had the latest firefox and a 6-month-old computer, so that checked out. Her other home computer had the same problem. She also had CA Security Suite installed, which I understand is reasonably popular (approx ~10% market share). She had gotten it bundled free with her RoadRunner ISP. When she turned off its firewall, the site worked, so the firewall was doing something my app didn't like. I asked her to open her firefox error console and she found errors like this:<p>http://qdaq.com/zzR.png<p>Ok, strange. I then asked her to open the file causing this error, which was at 127.0.0.1:37935/xpopup.js -- and had her email me the code. CA Security Suite is injecting some JS into the page (which is bad, yes, but not fatal). See if you can spot the problem in this js code:<p>http://pastie.org/801433<p>They're remapping the window.open, window.setTimeout, and window.setInterval to their "safe" versions of the code. Their "safe" version wraps the original setInterval() ("secretly" remembered as _orig_windowSetInterval) with some popup blocking code. It's all rather clever, and could even work transparently (apart from blocking your popups) if not for a code error in both _safe_setTimeout and _safe_setInterval:<p><pre><code>  function _safe_setInterval( sCode, iMilliSeconds )
  {
        // first block window.open -&#62; execute the code -&#62; unblock window.open
        return (_orig_windowSetInterval("_block_windowOpen(); " + sCode + "; _unblock_windowOpen();", iMilliSeconds ));
  }
</code></pre>
They use the "eval" mode of setTimeout and setInterval, to which you pass a string. They rely on the idea that whatever function you used setInterval() for will work when it's been toString()ed. For example, setTimeout(function() { alert('test'); }, 100); will work just fine because its toString() value will work. But any function with bound properties will break because toString() will lose them. In my case, it was any function on which I used bind() or similar in Mootools, included default mootools stuff like style tweening. I would imagine JQuery would be similarly affected, though I don't use it. Thus, anything that relied on css fade-ins or anything else with timers was broken.<p>Fortunately, they made it easy to circumvent. Here's how I fixed it.<p><pre><code>  function undoBrokenBlockers() {
	if (typeof _orig_windowOpen != 'undefined') {
		window.open = _orig_windowOpen;
		window.setTimeout = _orig_windowSetTimeout;
		window.setInterval = _orig_windowSetInterval;
	}
  }
  undoBrokenBlockers();
</code></pre>
...with another call to that code onDOMReady (I'm not sure where they insert their script tag in html).<p>SO, I would recommend thinking about adding this code to your site, because you may have users who are broken right now as well.<p>After figuring all this out, I googled it and found someone who had reported it to CA four months ago: http://homeofficeforum.ca.com/homeofficeforum/showthread.php?t=5365 ... Who knows when they'll fix it.<p>moral: be careful when you mess with JS internals! Or don't mess at all!
======
jim_lawless
I have encountered a similar problem with JS injection. There are HTTP proxy
servers that inject JavaScript into HTML and JS documents ... I believe the
purpose of the injected snippets is to examine the DOM and/or the JS code to
try and squelch malicious behavior.

The problem is that this particular proxy observes the MIME type in the
content-type header very strictly when deciding to inject raw JS or JS bounded
by HTML "script" and "/script" tags.

I've found that a number of sites return a content-type of "text/html" for
pure JS documents ... documents often referred to in HTML documents via
"script src=xxx". The appliance then injects the HTML "script" tags into the
raw JS document, breaking the legal JS code.

This causes the JS runtime to halt processing for a number of sites. For many,
the sites become unusable as event-handlers are either not in place or refer
to functions that did not have a chance to solidify. Some don't render
correctly.

I built a pair of documents illustrating the problem and showed the proxy
vendor the difference in behavior when the JS document had a MIME type of
"text/javascript" as opposed to "text/html". They told me that their proxy is
behaving correctly and that the sites are broken as they are returning
incorrect content-type headers.

Their advice was to contact the offending site when I encountered such a
problem and ask them to correct the issue.

I should note that this proxy server does have a programming interface. It is
possible to alter the behavior of the proxy via this interface to more
intelligently inspect documents with "text/html" to determine if they contain
HTML markup. My concern was that while I could fix it for my use of the proxy,
other users out in the wild would be subject to the same problem.

I'm not a fan of this trend of script-injection, even under the guise of
making computing safe for the end-user. I've begun to wonder if it's time to
include self-checks in JavaScript code to ensure that no alteration has
occurred in transit.

------
Thogek
Nice find. I've been foraying into where these strange xpopup.js errors
filling my web server logs have been coming from for awhile now...

I've run into too many cases over the years in which web-browsing computers'
security software made strange presumptions in tinkering with incoming web
pages' HTML. All too often, those presumptuous tinkerings result in breakages
in some cases or others, and the "secured" web-browsing users (and the web
developers to which they complain) are left wondering why stuff doesn't work
right.

 _sigh_

Thanks.

