How can script injections be good?

Posted: 14/08/08

An image of How can script injections be good?

Wandering around the various blogs and forums relating to ActionScript, as I frequently do, I came across an article that not really troubled me.

Over on ActionScript.org, a chap called Peter McBride has written a tutorial called "JavaScript and VBScript Injection in ActionScript 3". Now when I started reading it, I thought it was going to be one of those technical articles that publicly exposes a vulnerability in a platform, forcing the vendors resolve the issue. To my surprise, the article instead went on to advocate why script injections 'in the right hands' could be a useful tool for any developer. Peter saw it as a feature of the Flash runtime; I saw it as a security vulnerability.

The lengthy tutorial covers the varying ways to conduct your script injection, but the phrase that serves as a warning to all concerned is "In the hands of a legitimate developer..."

As an advocate of both best practice in Flash and web standards in general, I struggle to see any legitimate use for this on the Internet. Flash developers should NEVER try to cross-site script other people's DOMs. The net result of doing so will be diminished trust in third-party Flash content, blocks being placed on Flash content on corporate networks, and ultimately a decline in the use of Flash.

Fortunately, Adobe resolved most of these vulnerabilities less than a month after the article was published

The article highlights that the concepts of best practices and standards are not to everyone's liking; not everyone sees your web page as your territory. My recommendation is to never implicitly trust Flash content from third-parties, particularly content with a high change frequency (such as ads). You can prevent any third-party or untrusted content from scripting your page by setting the allowScriptAccess parameter of the SWF embed code to "never".

If you're using SWFObject to embed, I'd recommend

var flashPlayer = new SWFObject( playerUri, "player", 400, 300, "9" );

flashPlayer.addParam("allowScriptAccess", "never" );

...

After Adobe's release of Flash Player 9.0.124.0, allowScriptAccess is now set as "sameDomain" by default, meaning you implicitly only trust SWFs served from the same domain as the hosting web page. This affords greater protection from people that believe script injections are a acceptable.

<a href="http://www.adobe.com/devnet/flashplayer/articles/flash_player9_security_update.html" target="_blank">Read the technical bulletin</a>

Update: Shortly after posting a comment, I received a response from the author:

A few people have raised concerns about script injection, stating that they see no legitimate uses for it, and that a well-designed web application has no need for it.

I counter by saying there are dozens of uses, and that understanding one person's interpretation of "the web" isn't nearly as important as understanding and being able to adapt to the practicalities of real-world situations. In a perfect world, script injection would not be needed. This is not a perfect world.

As I said, there are ***dozens*** of legitimate uses depending on your situation, need, and environment. I work for an online security and digital rights company and we use this technique all the time to solve numerous problems with deployment, implementation and integration.

I'll admit it: in general, script injection is a pointless exercise for small-scale development teams as they generally deal with smaller projects and have better control over all aspects of a project - particularly integration. The real benefits kick in on large projects, particularly where multiple teams and/or environments (often from differing companies) are involved. Examples:

1) Hosting: Sometimes it's not practical to install JavaScript files on the host server(s), either due to the number of install sites (such as in advertising, games, or video players used in multiple locations) or when the hosting site is largely maintained by a third party, making updates to external files other than a specific Flash-only directory impractical or impossible (CDNs and mega-corporations being classic examples). Many ISPs, for instance, will allow you to have Flash content on your personal sites, but don't allow external JavaScript files and almost certainly won't allow VB scripts.

2) Compression: Big Scripts? One I'm working on now is 17,000 lines long, and unless I'm supporting gzip, that's a lot to download. By way of example, the Dojo framework is over 200k, even in compressed mode, but if injected via Flash it's only 70k.

3) Collisions Avoidance: Flash provides a collision-proof namespace since scripts are attached to the Flash Player, not the global scope. Thus they will work in many more situations than traditional scripting methods, and you don't need to worry about some other team stepping on your code. Good JavaScripters often think they will not need to worry about this... but not everyone you are working with is going to be a good JavaScripter.

4) Site/Role Blur: It gives the Flash developer more control over the JS-AS bridge. The Flash developer can give the JavaScript developer a simple API, enabling the JS guys to begin work. Meanwhile, our Flash developer can tweak and hone his interface directly from Flash, which is useful.

5) Modularity and Integration. AKA "Badges" or "One file, one solution". Traditional programmers tend to want hard paths, directories, and multiple dependent structures, leading to great organization and order *for them*, but also creating dependency, rigidity, and making deployment complex, particularly where code is reused often. A new trend in programming is to reduce the number of objects, classes and files, and just make one ***single*** widget that works everywhere. Move the widget, rename it, use it in a new way, and it should still work. Script Injection via Flash facilitates this to a degree not otherwise possible.

6) Context. Script Injection allows the Flash Developer a really easy way to "scope out" the context his movie happen to be playing in. I can, for instance, detect the CSS that wraps my movie - are we using Helvetica or Courier? If the mouse moves outside the Flash window, where Flash cannot see it moving, where is it? The point is that I don't need to tell anyone on the other teams that this is happening, so the proper pointers can be updated, etc. This is simply not practical using traditional file-based JavaScript.

7) Flexibility. Where do I begin? Imagine a page full of widgets, that the USER (not the designer) has dragged out in a web-portal-type page. Traditional javascript approaches would require a fairly complex framework to support this. In script injection, each widget becomes responsible for it's own context, and the "framework" suddenly downgrades to just an "interface".

On one site I wrote, for example, there can be up to **90** Flash movies playing at any given point in time. Some play video, some display graphics or text data in multiple ways, some run ads, some play games. The catch is that they are all the ***exact same*** 100k swf, loaded only once and then cached, so the page loads almost instantly.

Script Injection is then used to analyze the context that each instance of the swf appears in... reading local-node CSS, position on the page, load order, etc..... Once it knows its context on the page, it knows what it needs to do, with no dependencies on third parties to maintain it. This would be a nightmare to implement traditionally, particularly if a designer, for instance, moved or renamed one of the DIVs.

Like I said in the article, Script Injection only sounds sinister because it sounds similar to an unrelated hacker URL exploit. I didn't come up with the name, and prefer to call it "Script Packing", but one runs with what's been accepted by the community, which is why VHS won over Betamax, and BlueRay won over HD-DVD, right?

I am still very confident that I have understood the context of the original article and replied with the following:

The injection you’ve kindly taken the time to qualify was exactly how I originally interpreted your article:

1) Hosting: Having a poor hosting solution is the problem here. Whilst this solution may get things working, you'd be creating an architectural time-bomb. Architects inside 'mega-corporations' would be unlikely to permit such practices. The reasons why cheap/free hosting companies don’t permit VBScript are blindingly obvious.

2) Compression: Minify code compression? G-Zip file compression is supported by most browsers these days.

3) Collisions Avoidance: This comes down to communication. If development teams aren't going to talk to each other, you're always going to end up with problems. "...but not everyone you are working with is going to be a good JavaScripter" ...And likewise I suspect the JavaScripter is likely to think the same about the ActionScript developer trying to script his DOM.

4) Site/Role Blur: I'm all for people being able to maintain multiple skill sets, but we need to have the right people doing the right job. The developer responsible for the web page - working in conjunction with rest of the dev team - will script the page in a specific way; understanding all of the use-cases involved. Is it right that a lone-ranger on the other side of the office, who doesn’t want to talk to anyone, starts executing scripts that alter this? No. There’s no reason why the ActionScript developer can’t work with the rest of the development team to integrate their JavaScript code with the website script libraries.

5) Modularity and Integration: Granted this allows independence from the environment, allowing the app to exist in other environments by moving only the SWF. We must not forget the bigger picture though; we’re making assumptions that the environment will not be negatively affected by the script injection. The SWF may work on Site A, then be moved to Site B and work fine too; but it doesn’t mean for one minute that Site B is unaffected by this injection. There may also be dependencies coded into the SWF that require the host DOM to contain certain element Ids.

6) Context: Here we’re talking about dependencies that should be passed to the object, which is essentially a child object of the DOM. A good application doesn’t call its parent for its dependencies, so why should a Flash app do this? Doesn’t doing so also create tight-coupling between the SWF and the page, breaking point (5)? “...The point is that I don't need to tell anyone on the other teams that this is happening”. Urm, there’s the lone-ranger again...

7) Flexibility: “...each widget becomes responsible for its own context, and the "framework" suddenly downgrades to just an "interface..." And I would expect a setup like this to fall apart within days of being launched! You don’t let your fingers and toes tell your brain what to do, and the same applies to a page with a myriad of Flash widgets operating in it. The framework that we so kindly demote to an interface was the only thing stopping every single widget asserting its own importance on the DOM.

As for the 90 Flash movies playing simultaneously, my concern wouldn’t have been for the file size but the impact on CPU and memory usage!

See the post on ActionScript.org

Keywords for this post: flash, script injection, vbscript, javascript, vulnerability, flash player