Tuesday, July 29, 2008

Introducing the Adobe AIR security model

My goal in this document is to provide a high-level overview of the AIR security model, and the rationale behind it.


Note: For more information about the set of security rules and controls in Adobe AIR that help safeguard users and application developers, refer to the Adobe AIR 1.0 Security white paper.


Adobe AIR and the desktop

Adobe AIR allows developers to use their existing web development skills in HTML, Ajax, Flash, and Flex to build and deploy desktop applications. Although these applications may be based upon web technologies, it is important to keep in mind that the end result is a desktop application, and as such the primary security model for AIR is that of a desktop application, rather than a web application.

A desktop application has certain characteristics. On the one hand, desktop applications generally have a lot more privileges than a similar web application, as they have been installed by the user to a specific desktop machine, implying a degree of trust that is greater than that of arbitrary web content. On the other hand, the privileges inherent in a desktop application require a greater degree of caution as certain coding practices and patterns that may be common in web applications may never be acceptable in a desktop application.

AIR sandboxes

AIR applications can be built using a combination of Flash and HTML/Ajax. AIR applications can also leverage PDF for document rendering, although an AIR application cannot be based upon a PDF file alone.

Regardless of whether an application is built primarily in Flash or HTML, all AIR applications have some characteristics in common. Within a given AIR application, there is a set of AIR specific APIs that are available to provide access to local system and network resources that would not be normally available in a web application contained in a browser. Each AIR application also contains a number of different sandboxes, depending on what type of content is being loaded, and for what purpose:

  • Application sandbox is the root of every AIR application. This sandbox permits access to the privileged AIR specific system APIs. In return for access to these powerful APIs, some common dangerous APIs and patterns are restricted. For example, dynamic importing of remote content is generally prohibited and dynamic code generation techniques are heavily restricted. Only content loaded directly from the application home directory (via the app:/ URI scheme) can be placed in the application sandbox.
  • Non-application sandbox contains all other content that is not loaded directly into the application sandbox. This includes local and remote content. Such content does not have direct access to AIR APIs and obeys the same rules that it would have to obey in the browser when loaded from the same location (for example, a local SWF file behaves the same way a local SWF file would in the browser, and HTML from a remote domain behaves like it would behave in the browser).

For more information on AIR sandboxes, refer to the Sandboxes section in Developing Adobe AIR Applications with HTML and Ajax.

Differences between desktop and web application security

There are a number of design and implementation patterns common to web applications that are too dangerous to be combined with the local system access inherent in the AIR application sandbox. In a desktop application, the user grants system access (albeit sometimes unknowingly) to the application by downloading and then installing and running the application. This in theory allows the user to inspect and approve the application before installing or running it for the first time.

This in return limits the ability of the application to extend itself by silently and dynamically installing additional components or running code loaded from a remote server. For example, a fundamental desktop practice is to inform the user when downloading and installing updates, plug-ins, or other extensions to an installed application. Even applications that appear to do this automatically give some notice to the user, as well as providing a configuration option to disable automatic updates. When apps attempt to bypass this user consent, they run the risk of being labeled a privacy threat, if not a security vulnerability, which is why runtime script importing of remote content has been disabled in the application sandbox.

Imagine a scenario where your desktop application automatically imports some script from your website every time it runs, perhaps to render today's stock charts or to provide the latest application functionality. In the event that your server is compromised, or if you do not perform that code loading very diligently (that is, sign the script with your certificate and subsequently verify the validity of the signature), then an attacker could take over every machine that runs your application simply by compromising the server hosting that one script. So the user deciding to install a given application does not automatically grant the right to that application to download and execute additional code without additional, explicit user consent.

Another concern lies with practices that, while they may not be intended to load external code or script, permit injection of remote script (commonly known as cross-site scripting or XSS) where the developer never intended. The eval() function in JavaScript is a common example of this. eval() is often used to generate code from templates combined with data potentially loaded from a remote domain. Unless the developer is extremely diligent in scrubbing loaded data for every possible form of code injection, then any such data containing malicious code could compromise the user's system if eval()'ed in the application sandbox. This is why using eval() and similar APIs to generate code at runtime in the application sandbox is prohibited.

Finally, using any remote data in AIR specific APIs should be done with extreme care. For example, if a remote server can provide a file name and file contents for the application to download, it could write the file to a sensitive area of the file system, possibly resulting in installation of a malicious rootkit. This may seem farfetched, but it is a common mistake that is easily made, even when you believe you have exercised sufficient care. Suppose you have built an application that allows the user to browse and save photos from a remote server. At some point, your application would probably provide a function that looks something like this:

savePhoto(var filename, var content);

You may even take the extra step of ensuring that you provide a root directory—for example, C:\Photos— that you prepend to the file name variable. So imagine if the data provided by the remote server is something like this:

filename = "sailboat.jpg"
content =

Your code prepends C:\Photos, resulting in:

filename = "C:\Photos\sailboat.jpg"

Looks pretty good, right? But what happens if the remote server provides you instead with:

filename = "..\Windows\notepad.exe"
content =

When you prepend your root directory to the file name, you end up with:

Filename = "C:\Photos\..\Windows\notepad.exe"

This will still overwrite the Notepad application in the Windows directory, and end up executing the rootkit the next time the user attempts to run Notepad. This is a simple example, but it illustrates how easy it can be to make such a mistake.

For additional information, see the sections Best security practices for developers and Writing to disk in Developing AIR Applications with Adobe Flex 3.

HTML security considerations

The security model for the HTML application sandbox in AIR varies significantly from the sandbox available in the browser. The reason behind this is there are a number of design and implementation patterns common to HTML web applications that are too dangerous to be combined with the local system access inherent in the AIR application sandbox.

Patterns such as remote script importing and use of dynamic script generation via eval() and injection of code into innerHTML and outerHTML DOM elements—while already very dangerous—are very common in HTML applications. Their familiarity unfortunately does not make these practices acceptable in the application sandbox in AIR. As such, you will notice significant restrictions when trying to import script or generate code dynamically in the application sandbox. If you really need to implement such potentially risky runtime patterns, you will have to do so in a non-application sandbox (see below).

There are characteristics of the HTML security model that can be surprising. For example, the most granular security sandbox is an entire frame (whether frame, iframe, or window). This means that all code within a given frame is in the same sandbox and has exactly the same privileges, regardless of how it was loaded into that frame. As far as the browser (or AIR) is concerned, it can't really tell the difference between code that is originally part of the page versus code that is imported from outside the page versus code that is generated by an eval() function. This means that the only way to safely handle trustworthy and untrustworthy content is to separate them into different frames or sandboxes.

For more information, see the section HTML security in Developing Adobe AIR Applications with HTML and Ajax and the HTML security FAQ.

Interacting with different sandboxes

Due to the restrictions placed upon dynamic coding and script importing, the application sandbox is generally the safest sandbox to place your application code into as the risk from injection attacks is greatly diminished compared to the typical browser sandbox. However, there may be cases where developers still need to use these risky techniques in their applications—for example, when interacting with web services that only support JSON non-compliant JavaScript APIs.

The recommended technique in these cases is to create a non-application sandbox to perform the risky operations, and then interact with that sandbox via the SandboxBridge API. The SandboxBridge is a bi-directional serialization API designed to allow domains/sandboxes that otherwise cannot trust each other entirely to interact.

Application extensions such as plug-ins are best implemented via the SandboxBridge. After obtaining user consent, you can store the plug-in in a non-application location (such as app-storage:) and load it into a non-application sandbox. By exposing a well-defined plug-in API (much like the NPAPI does for most browser plug-ins), you can safely interact with your own plug-ins, or even third-party plug-ins developed for your application, without trying to import them into your application sandbox. In addition to being safer from a security standpoint, this type of well-defined plug-in API is a more stable solution, reducing the chances of plug-in breakage with subsequent updates to your application.

Note that the SandboxBridge is not fail-safe. Code in the application sandbox should not expose any APIs via the SandboxBridge that are not safe to be called by any arbitrary remote code. As such, you should not expose any system or sensitive application APIs directly via the SandboxBridge.

However, you could expose, for example, the eval() function from a non-application sandbox back into the application sandbox, as any code subsequently evaluated within the exposed eval() function then will be executed within the context of the non-application sandbox. This would not permit access to sensitive APIs or application data (unless you had expose those already to that particular non-application sandbox). As general guidance, it is usually ok to expose functions and data from a non-application sandbox into the application sandbox, but potentially risky to expose functions and data from the application sandbox into a non-application sandbox. Thus, if you want to use a specific non-application sandbox for these risky practices, you should not use it for anything remotely trustworthy or provide it with any sensitive APIs or data.

For additional guidance regarding usage of the SandboxBridge, see the section Working securely with untrusted content in Developing Adobe AIR Applications with HTML and Ajax.

Installation of AIR applications

AIR applications are usually installed in one of two ways:

  • Via a web browser using a seamless install badge feature
  • By opening a .air application installer file after it has been copied to the local computer

These two scenarios always use the AIR application installation experience, which is largely the same for all applications. The only significant differences in experience are determined by whether your application has been signed by a commercial, recognized code-signing certificate or a free, self-signed certificate.

Both workflows involved the download of a .air file, which is really just an in-order ZIP file that can contain HTML, SWF, JavaScript and any other types of files. As such, most existing security tools should be able to inspect the .air file itself, or the files that are extracted during the installation process and at runtime.

For an example of the seamless install badge experience, see the AIR sample applications in the AIR Developer Center.

Signing of AIR applications

All AIR applications must be signed by a code-signing certificate. The only question is whether the certificate in question is what is commonly know as a self-signed certificate, which means that it is not recognized as being trustworthy by a typical user's machine (unless the user chooses to import that specific certificate into his or her certificate trust store), or a commercial code-signing certificate purchased from a major certification authority (CA).

The recommended approach is to use a commercially obtained code-signing certificate, as that will be recognized by the AIR installer on almost all user machines. This permits the name of the publisher to be recognized and provides a better installation experience for the user.

For detailed information regarding code signing for AIR applications, please see Developing AIR applications with Adobe Flex 3 in Adobe LiveDocs and also Todd Prekaski's article, Digitally signing Adobe AIR applications.

Conclusion

Being a desktop application runtime, the AIR security model is significantly different from the web browser security model. The application sandbox in AIR provides direct access to system APIs, but in return a number of APIs have been restricted or outright prohibited. Specifically, importing of non-application (that is, not loaded via app:/) content and dynamic generation of code within the application sandbox is heavily restricted.

In many cases, frameworks and existing code will work with little or no modification in the application sandbox. However, in some cases the developer will have to perform high-risk operations (such as importing of remote JavaScript) in a non-application sandbox, then carefully expose the resulting code and data back to the application sandbox via the SandboxBridge API.

However, the privileges inherent in a full desktop application mean the developer can sometimes find ways around these restrictions. The reality is that doing so will almost certainly introduce a large amount of security risk into the application and for the end users of the application. Thus Adobe strongly recommends that developers stay within the restrictions placed by the AIR security model, and carefully consider the cost of implementing rigorous security mitigations for bypassing them. In most cases the development cost of these mitigations will significantly exceed the cost of finding an alternative solution that stays within the bounds of the security model.



post signature

Tip: Serving AIR app on IIS

In order to set up your IIS to serve Adobe AIR applications, you need to do few changes in your IIS configuration so it will handle additional MIME type. First of all find your IIS Manager in Control Panel\Administrative Tools:

image

When you double click on it it will open you a manager.

Select "Web Sites" or single web site that suppose to handle your AIR MIME, select Properties and it will populate Web Site Properties dialog.

image

Then, select HTTP Headers tab and on the bottom of it click MIME Types button, it will populate one more dialog:

image

In this dialog, select New and in new MIME Type dialog enter following:

  • Extension: .air
  • MIME Type: application/vnd.adobe.air-application-installer-package+zip

image

Then click OK, dialog will close. Another OK and you will close another dialog, and so on.

Well, you got your AIR MIME ready to use.



post signature

Adobe Flex in a Week

Flex in a Week is a week-long, video based online training program for developers. This self-paced program is free and is intended to help developers accelerate their Flex learning. The training will eventually be a full 5-day program, however we are launching with the first three days which will provide developers with enough learning to get them started using Flex. We will complete the remaining two days of content over the coming weeks.

Please help us promote this valuable new training resource by blogging about it and by including a link in your email signatures. This program should play a key role in increasing Flex adoption.

We are also looking for feedback. Please let us know what you think of this training.



post signature