Modern web applications are conglomerations of JavaScript written by multiple authors: application developers routinely incorporate code from third-party libraries, and mashup applications synthesize data and code hosted at different sites. In current browsers, a web application's developer and user must trust third-party code in libraries not to leak the user's sensitive information from within applications. Even worse, in the status quo, the only way to implement some mashups is for the user to give her login credentials for one site to the operator of another site. Fundamentally, today's browser security model trades privacy for flexibility because it lacks a sufficient mechanism for confining untrusted code once it reads sensitive data.
COWL (Confinement with Origin Web Labels) is a robust JavaScript confinement system for modern web browsers. COWL introduces label-based mandatory access control to browsing contexts (pages, iframes, etc.) in a way that is fully backward-compatible with legacy web content. With COWL, developers not only can restrict with whom they share data, but also can impose restrictions on how their data is disseminated once it is shared. COWL achieves both flexibility for developers and privacy for users: it allows code to fetch and share data as necessary, but once code has read sensitive data, COWL confines the code by revoking its right to communicate with unauthorized parties.
IFC Inside: Retrofitting Languages with Dynamic Information Flow Control. Stefan Heule, Deian Stefan, Edward Z. Yang, John C. Mitchell, and Alejandro Russo. In the Proceedings of the Conference on Principles of Security and Trust (POST), London, UK, April, 2015. [ bibTex | extended version ]
Protecting Users by Confining JavaScript with COWL. Stefan, D., Yang, E., Marchenko, P., Russo, A., Herman, D., Karp, B., and Mazières, D. In the Proceedings of the 11th USENIX Symposium on Operating Systems Design and Implementation (OSDI 2014) , Broomfield, CO, October, 2014. [slides | bibTex]
Toward Principled Browser Security Yang, E., Stefan, D., Mitchell, J., Mazières, D., Marchenko, P., and Karp, B. In the Proceedings of the 14th USENIX Workshop on Hot Topics in Operating Systems (HotOS XIV), Santa Ana, NM, May, 2013. [slides | bibTex]
We have implemented COWL as a new DOM-level API for the Firefox and Chromium browsers. The preliminary version of our Firefox COWL implementation is available for download.
$ git clone https://github.com/scslab/cowl.git
We have implemented several case-studies. We will upload them to this page, incrementally, as tutorial-like pages. For now, checkout:
COWL is a collaboration among several researchers from several organizations. We are:
Today, developers use contexts (e.g., tabs, pages, and iframes) to isolate content from different origins (web sites). COWL extends contexts with labels, which encode the origins from which a context has read information. COWL then uses these labels to restrict how code within a context communicates: it confines the code to disallow any communication that would result in leaking an origin's sensitive data. COWL fits well with existing legacy web sites because it imposes these restrictions within the framework of existing discretionary access control (DAC) policies, such as the same-origin policy and CSP.
To impose restrictions on how third-party code can use sensitive data, developers can label data before handing it off to a third-party context (e.g., using postMessage). When the third-party code later decides to use the data, COWL "taints" its context's label to confine the executing code. This approach differs from the status quo, in which the developer must effectively choose between benefiting from the functionality of the third-party code or risking the leaking of the sensitive data. With COWL, a developer can safely use third-party libraries by ensuring they are confined once granted access to sensitive information.
In today's model, when the browser retrieves a page from https://example.com, any script within the context for the page is trusted not to violate the security concerns of https://example.com. This is natural: https://example.com should be allowed to dictate how its data is disseminated! In COWL, this notion of trust is made explicit with privileges. Privileges enable code to act on behalf of a page's origin and thus avoid becoming confined when reading data sensitive to that origin. Equally importantly, however, COWL allows code to "drop" its privileges or delegate them to other trustworthy code. Developers can use this primitive to build applications that adhere to the principle of least privilege.
These simple three primitives are amenable to a fast browser layout engine-level implementation, without any modifications to the underlying JavaScript engine. Moreover, because they extend already familiar concepts (e.g., contexts, postMessage, and XMLHttpRequest), we believe developers will find them a natural means for exerting additional control over the privacy of the data they curate. An example (see link above) illustrates how the COWL API can be used to confine a third-party password strength-checker library; our paper details three other common application design patterns.
COWL can be used to build several common types of application securely. Our paper describes several examples, including an encrypted document editor, an app that relies on jQuery, a third-party mashup, and a password strength checker. We will release the code for all of these soon, but for now let's see how we can confine a third-party library such as a password strength-checker.
Suppose the developer of the page https://example.com wants to use the password strength checker from http://sketchy.ru/checker.js. Maybe the developers at sketchy.ru are not malicious, but the developer doesn't trust them to write bug-free code. Note that the checker may need to communicate with sketchy.ru to fetch data that it needs to do its job. (For a more realistic library, e.g., the syntax highlighter running in this page, this is desirable functionality.) How does the developer use COWL to ensure that the checker won't leak a user's password to sketchy.ru or any other site?
// In example.com page, create new context: var checker = new LWorker("http://sketchy.ru/checker.js");An LWorker is a lightweight labeled worker, COWL's approach to creating cheap labeled contexts. (These are similar to Web Workers, but labeled and run in the same thread as the parent.) This code simply creates a new context and starts running the untrusted checker code in this context. (
// In example.com page, register message handler waiting for result checker.onmessage = function(result) { console.log('Password is: ' + result.toString()); };Since all communication between labeled contexts is done by message passing, we register a handler to be invoked once the checker sends us the result.
// Is the password sensitive? Yes, label it with example.com! var labeledPassword = new LabeledBlob(password, "http://example.com"); // Send the checker the labeled password: checker.postMessage(labeledPassword);Finally, let's send the checker the password so it can do its job. Since the password is sensitive, though, we label it with the origin it's sensitive to: example.com. Now when when the checker reads the password, it will be confined!
Our code expects the checker to use message passing. What might this code look like? Here is one possibility:
// In checker.js, register handler waiting for request from parent: onmessage = function(labeledPass) { if (doneLoading) { // Taint contex to preserve privacy or password COWL.privacyLabel = COWL.privacyLabel.and(labeledPass.privacy); // Now we can read the password var password = labeledPass.blob; // Cannot communicate with sketchy.ru anymore, but can reply to parent: postMessage(checkStrength(password)); } }; // .. use XHLHttpRequest to communicate with arbitrary sitesThis checker code starts out unconfined: it can communicate with arbitrary web sites to fetch any data it needs. However, once it has finished doing so (indicated by doneLoading) and the parent has supplied it the labeled password, it can proceed to check the strength of the password. Specifically, in the onmessage handler, the code extracts the password from the labeled blob--at which point COWL taints the context--and computes the strength with the checkStrength function. Once the code has inspected the password COWL confines it, preventing it from communicating arbitrarily. The code can, of course, send the containing example.com page the strength of the password.