-
Notifications
You must be signed in to change notification settings - Fork 398
Outer Sandbox Security
One of the goals of the Shumway project is to provide a secure solution that will make execution of wide variety of SWF files possible. The Shumway SWF player (at least its major parts) has to operate in the JavaScript/HTML5 sandbox therefore reducing attack surface -- any security defect in the JavaScript/HTML5 sandbox will not be only Shumway project's issue but a browser's one. Also, in most of the cases, crashes associated with using HTML5 APIs can often be reproduced by a regular web page.
In its current state, HTML5 cannot provide all variety of the APIs that Flash implemented: some of the APIs might have different security model (e.g. CORS vs crossdomain.xml), or just be unsafe or proprietary (e.g. DRM). That being said, in some cases we will need to poke some holes to extend the functionality of the HTML5.
NOTE: The Shumway project is quickly evolving so this document can be out-of-date. Please also consult the source code in the primary repository.
Typical deployment of the Shumway is split into two major components: gfx and player. The gfx component is responsible to display graphics and to handle user events. The player component contains ActionScript virtual machines and SWF timeline interpreter.
The player component loads a SWF binary file, parses and interprets/compiles/executes script code provided in this file. We are trying really hard to forbid access to the global JavaScript object, however at the moment it is not a trivial task to proof that, therefore we will declare this component unsafe and will be trying to protect external system (a browser, a web page, the gfx component, etc.) by using outer sandboxes. Also the player component handles data that is requested/originated from some domains (will be discussed below) and can be exposed to other systems, e.g. a web page or gfx component.
The gfx component is responsible only to parse and display the data provided by the player component and to relay events (mouse/keyboard/display) to the player component. No external script execution is performed. The gfx component only handles data provided by the player component and provided via user interface. So let's declare this component safe.
JavaScript prefers asynchronous method of communication between systems. The gfx and player components use this type of communication in most of the case. However in some cases the player component has to send synchronous requests to the gfx component for temporary surface rendering or text layout.
Flash player's cross-domain file loading use crossdomain.xml as a policy file instead of cross-origin resource sharing (CORS) HTTP headers (as web browsers do). But they serve the similar goal: to control how resources are requested/shared across remote domains.
Before SWF player requests a remote file, it requests a crossdomain.xml file from the web server root (master policy file) to verify if access is enabled. Then it proceeds with main request. In comparison with CORS, a web browser performs a HTTP request and checks the HTTP headers of the response.
It is possible to not perform policy file verification or not use the verification result for video and image files (just to enforce that on reading pixel data back), but Shumway does not support that yet (see "Restrictions to the Flash Security Model" section below) and errors on initial loading of such files.
A Firefox extension extends functionality of the browsers and has the same virtually unrestricted rights to access system resources such as any network site, clipboard, TCP sockets, etc. Not fully trusting Shumway code with Firefox chrome rights, we instantiate a Shumway SWF player in the sandbox with privileges that are just enough to perform parsing, interpreting and display a SWF content.
NOTE: Currently, the extension code is integrated with the Firefox code base without overhead of initialization needed for a Firefox extension. So when we are talking about the extension, we will be talking about the integrated code as well.
The simplest and easy way to verify was to place the gfx and components into windows that will have resource privileges. That will limit I/O of Shumway or lock origin to "resource:" protocol, but still will allow to use HTML5 APIs such as Web Audio, CANVAS, etc.
To add further restriction on the player components, we are using iframe's sandbox attribute that will stop player from using its resource origin, and keeping it from accessing the script objects of gfx components directly. The only way to communicate between the gfx and player components will be postMessage; we just need to add a way allow player to send sync messages to the gfx component.
To provide viable solution that plays wide variety of SWF files, we identify the following requirements that will not be easy to implement if the origin is "resource:" and in the sandbox:
- the send sync messages to gfx
- to access files from remote domains
- clipboard
- full screen
- additional features (e.g. RTMP support)
The functions above will be implemented with chrome rights (see ShumwayCom and ShumwayChromeActions), but safely exposed with Xray vision to the gfx and player components.
Let's add some restrictions to our implementation of the Flash security model. That will help us to allow loading of the external SWF files (in addition to the main one) using the Loader.load method and to allow cross-domain data access:
- To load files (resources, images or SWFs) permitted only if its URL belong to the same domain or has master policy file at the remote server that lists main SWF file origin
- Loading of the SWF external SWF or image using
Loader.load
method is permitted only ifallowDomain
/allowInsecuredDomain
is called with the domain or wildcard that gives the SWF URL scripting rights before executing the load method - navigateTo is performed only for HTTP and HTTPS URLs
The restrictions 1 and 2 above will ensure that loaded as a child SWF would have some data access and has full rights to use the same features as main SWF. That will also allow us, not just disable the Loader.load
functionality, while we are working on proving that our AVM1/AVM2 virtual machines are save and security domain policies are enforced.
The primary deployment of Shumway is a Firefox extension. It has chrome permission, however the main part of the application does not need elevated privileges. The extension registers itself as a stream converter for the "application/x-shockwave-flash" mime type and as a plug-in preview for the native Flash plugin (a.k.a. PlayPreview). Once instantiated via stream converter or PlayPreview interface, it sets up initial IFRAME with chrome principal and ShumwayChromeActions object. The latter allows performing some functions with elevated permissions (see Appendix A. ShumwayCom Methods below) and communicate between the host page and Shumway instance if Flash movie is embedded via object/embed tag.
The initial IFRAME loads the gfx and player IFRAMEs with resource principal limiting what Shumway can do. Also the player IFRAME has sandbox="allows-script"
attribute to disable direct access from this IFRAME to the gfx one. Communication between these two IFRAMEs are limited to postMessage calls and calls via ShumwayCom.
If the external interface is required and is allowed (via object parameters and security policy), the Shumway instance can add few global utility functions to the host page, which allow it to call in and out functions from the ActionScript to host page and vice versa.
Similar to the single process deployment, the Shumway instantiation starts from creation of the initial IFRAME. But in this case the gfx IFRAME (and then player IFRAME) will be created out-of-process, and ShumwayChromeActions and ShumwayCom adapter will be forced to communicate using sendAsyncMessage/sendSyncMessage.
The exception is the external interface: the CPOW will be passed to the chrome side (initial frame) from the player IFRAME to perform the synchronous calls by the scripts of the host page.
As a by-product, we are trying to maintain the Shumway SWF player as a web application. It has functionality that is limited by a natural HTML5 sandbox, e.g. loading files is limited to CORS policies and extended functionality (such as setClipboard) is not available.
The gfx and player components located on the same domain allowing player perform sync requests/calls to gfx components.
ShumwayCom method | Used in | ShumwayChromeActions method | Description |
---|---|---|---|
userInput | gfx | userInput | Notify chrome code about user input |
fallback | gfx | fallback | Fallback to Flash Plugin |
endActivation | gfx | endActivation | Notify about end of Shumway SWF player initialization |
reportIssue | gfx | reportIssue | Opens the report issue page |
reportTelemetry | player | reportTelemetry | Reports some telemetry data |
enableDebug | gfx | Enables remote debugging | |
getPluginParams | gfx | getPluginParams | Gets object parameters |
getSettings | gfx | getSettings | Gets Shumway settings |
setClipboard | player | setClipboard | Sets clipboard |
setFullscreen | gfx | setFullscreen | Sets full screen |
getWeakMapKeys | player | getWeakMapKeys | Gets WeakMap keys |
externalCom | player | externalCom | Sets up and performs external interface operations |
loadFile | player | loadFile | Initiate remote file loading (including the original SWF) |
loadSystemResource | player | Initiate Shumway libraries loading | |
navigateTo | player | navigateTo | Navigates to different page |
setupComBridge | gfx | Sets up bridge between gfx and player for sync messages | |
postSyncMessage | player | Sends sync message from player to gfx | |
setLoadFileCallback | player | Sets callback for remote file data/events | |
setExternalCallback | player | Sets callback for external interface calls | |
setSystemResourceCallback | player | Sets callback for Shumway libraries loading | |
setSyncMessageCallback | gfx | Sets callback for sync messages from player |
The Flash Security model references:
Mozilla 2019