Highly flexible applications and highly secure applications are usually at the opposite ends of the spectrum and require some sort of constant balance. So how do you mitigate your security risks when you need to build an application that is dependent on running modules at runtime via some sort of configuration?

ApplicationDomain.currentDomain is the just about the worst thing you can do when trying to build a secure application.

The problem:
Your modules are loaded at runtime which need to interface internal code you’ve written in your main application. This means the ModuleLoader needs to then set the currentDomain to ApplicationDomain.currentDomain. However ideally the module loader needs to be able to distinguish levels of trust if it’s a module you (or trusted developer) have written, or a rogue module.

The ugly issue:
When using a blanket statement to allow all modules to load with the currentDomain, you are giving every loaded swf trusted access to your entire platform. Some cases, this isn’t a big deal. It becomes a nasty headache if you’re building an e-comm solution. It will allow man-in-the-middle attacks to allow someone to load their module, and using any number of methods for decompiling and introspection to figure out what class and methods are used to capture and/or listen to events for sensitive information like user info and payment tokens. Their swf only needs to add itself as an IEventDispatcher or through the document tree to add itself to the sensitive classes and wait for these methods to be triggered.

The solutions:
There are several different ways to help combat this problem, however some are better than others. Any solution pretty much involves using 2 ModuleLoader’s. One for secure / trusted, another for insecure untrusted. Always start the loading process from the insecure, then based on which method you choose -transfer the loaded swf to the untrusted ModuleLoader via addChild(), swapChild(), etc.

  1. Use a trusted Interface in your platform that is always loaded at the application layer. However this is the weakest of them all since this only provides a minimal level of security as it can still be broken. The most flexible Modules use -load-externs as a compiler command to allow most of the dependent classes to be front loaded to the application. This makes things a bit speedier especially when loading several modules that share an entire platform. By using an internal interface you can check at the ModuleLoader level if the loading module has sufficient trust to be given access. This works in theory since the Flash AVM will not replace a duplicate namespace collision, but can still be defeated since I can write a rogue module and duplicate the secure interface using the exact same package.
  2. Use server side methods to generate hash key’s in the configuration which matches the particular node of the module in question. NEVER use this method in conjunction with deciphering the hash key internally, it’s way too easy to figure out what’s going on in your code. Instead pass this hash key back to the server, ask it to validate it against the file name and it’s own interally identifiable metrics (eg file size, mod date, etc) to then pass back a Boolean pass/fail for trust. Based on this service, then assign which domain it can be loaded into.
  3. Use a domain trust method in a static and final class to determine if the source of the module’s URL is coming from a place that is trusted. This basically means using RegEx along with hardcoded strings to determine if the URL is from ‘mydomain.com’. While this can be a bit laborious since it might require constant care to edit the domains that are trusted, however this particular solution isn’t as easily defeated since the list of trusted domains are embedded in your application.