DJS is a defensive subset of JavaScript: code in this subset runs independently of the rest of the JavaScript environment. When propertly wrapped, DJS code can run safely on untrusted pages and keep secrets such as decryption keys.
DJS is especially useful to write security APIs that may run alongside other untrusted scripts, for instance an OAuth library such as the one used by "Login with Facebook", or a Node.js program that includes untrusted modules.
Techical details can be found in our USENIX Security 2013 paper Language-Based Defenses Against Untrusted Browser Origins. Our security properties do rely on assumptions on JavaScript implementations that have been violated in the past due to bugs and may not hold in ECMA Script 6. We also provide details about attacks and their disclosure on security components that may be loaded in untrusted pages.
In addition, the fragment of DJS without loops and arrays, but extended with our cryptographic library DJCL, can be translated into ProVerif spi-calculus processes, in particular, it can generate the client processes for the WebSpi library automatically to verify the DJS implementations of complex web protocols.
Finally, because DJS is proved to run independently of the JavaScript environment, it provides a more expressive subset for compilation
to native code than the existing best effort, asm.js.
Current work: we now compile statically typed JavaScript (similar to DJS) to asm.js.
If you have questions, comments or find a bug or attack, please contact Antoine Delignat-Lavaud, Karthikeyan Bhargavan or Sergio Maffeis.
A: We claim we can trim down DJCL to fit in a bookmarklet. There are various ways to achieve this, the most space efficient being to use hexadecimal strings internally. For instance, this sample bookmarklet can do HMAC-SHA1 with a secret key (assuming the input is an hexadecimal string), and compresses to 1868 bytes. Encryption is also possible with some effort.
A: If you redefine Function.prototype.call in the Chrome or Firefox console, it may seem like function calls are tampered - however, this is only due to the way the console tool is implemented - it itself is written as a JavaScript wrapper. As for the object and array constructors, the ECMA specification clearly states that the built in constructor should always be used for literal objects and arrays, however, some browsers didn't implement this behavior until 2008 when cross-origin JSON hijacking attacks have been mounted by tampering those constructors.
A: Yes, you can even implement a TLS channel between two scripts provided they embed a shared secret or user-specific public keys for authentication. As always when dealing with JavaScript cryptography, key management is the biggest issue - your script server must act as a trust anchor and long term secret manager. Note that in general, it is easier and more efficient to use postMessage between frames from trusted origins instead.
A: We only focus on semantic language safety, and if you use the translation to ProVerif, the correctness of the protocol implementation. There are many side channels available to a same-origin attacker - the most obvious ones being time and memory. In SJCL, we sometimes try to mitigate those channels - for instance, in CCM tag validation. However, we do not have any formal proof of robustness against any side-channel attacker - furthermore, user-written DJS code must also take into account this risk. For instance, use the AES.ctEq function for constant time string comparison.
A: If you are not sure whether you would benefit from using DJS for your application, you should probably not try to write DJS code. There are few sensitive applications that need to defend against same origin attackers, and good security knowledge is required to write (and verify) them properly. There are exceptions - for instance, you may want to write a CSRF protection system that is safe against an XSS attacker. For those frequent use case, we will ultimately provide our own verified, easy to use solutions.
DJCL is a complete cryptographic library written in DJS, based on SJCL and JSBN, two popular JavaScript libraries for symmetric and asymmetric encryption. It supports AES-256 in CBC and CCM mode, HMAC on top of SHA1 or SHA-256, RSA encryption and signature with OAEP/PSS or PKCS#1 v1.5 padding.
You can try to tamper base object prototypes and default functions on the demo page and verify the independance of the cryptograpic compoutations.
N.B. We do not guarantee robustness against side-channel attacks at this time.
Current version of DJCL - Documentation
Note that the various DJCL components should be loaded together inside a DJS wrapper to be secure against a same origin attacker. See the Script Server tab for a demo of how to embed DJCL and encryption keys into a security component.
Key:
IV:
Key details | |
---|---|
Modulus | |
Public exponent | |
Private exponent | |
First prime p | |
Second prime q | |
d mod p | |
d mod q | |
q^-1 mod p |
Defensive scripts must be loaded from a secure isolated origin to preserve source secrecy and other security properties. The primary reason to use defensive scripts is to keep secrets, such as encryption keys, even when loaded into an attacker's page. The purpose of a defensive script server is to embed keys and entropy into the script and making sure that the origin it is being loaded into is authenticated.
We implement a demonstration script server both to serve our examples and be used as a trusted third party script server, where one can register scripts for his own origin with a public key.
The source code of our defensive script server is available at https://dss.defensivejs.com.
We have registered www.defensivejs.com on the defensive script server at dss.defensivejs.com to serve a script that retrieves the time in Los Angeles from the host page's server. This script must authenticate the origin it is being loaded into; there are several ways of doing this, one of the safest is to use the CORS-based encrypted AJAX method described in the USENIX Security paper.
The script is loaded using: <script src="https://dss.defensivejs.com/?script=1"></script>. The security goal for this script is that the server time will only be released on www.defensivejs.com - trying to load the same script on any other origin must fail, and no other script may be able to tamper the displayed time assuming the alert() function is not tampered (however, other scripts may cause the AJAX call to fail).
It is recommended to use your web console (F12) to track the HTTP requests and scripts loaded from the example.
You must first register your website. First, generate the private key offline using openssl genrsa -out key.pem 2048. Export the public key using openssl rsa -in key.pem -pubout -out pub.pem. Finally, put the public key on the webserver where you wish to load your defensive script. Enter the URL of the public key below to complete registration of your origin, note that it must include the protocol, domain and port as they would appear in the Origin header. Note that if the origin was already registered it will update the public key.
Origin:
If you want to update a script enter its ID: