5 ms·
Defensive Javascript - Run code safely on untrusted pages
- taf2 13y agoPretty neat approach to adding an additional layer of security... I didn't finish reading the paper but did look at this component example: E = (function() { var F = function(x) { var secret = 42, key = 0xC0C0ACAFE; return x===key ? secret :0 }; return function G_F(x) { return F(x>>>0) } })(); The neat thing about this is that at runtime you can't get to the secret. I initially thought you might be able to toString the function but that won't work because it will only show you the algorithm used e.g. function G_F(x) { return F(x>>>0) } Still, I was thinking if you could devise a plan to remotely fetch the source then you could, I believe defeat all of this extra security... unless of course the server can secure things such that the key is unique to each request...
- fooyc 13y agoIs there a chance this could be vulnerable to timing attacks ? Is comparing two integers fixed time ? It may be pure hazard, but in the following two calls, E(0x000000FE); E(0xC0000000); The second one is significantly slower: http://jsperf.com/qsmflkjtest http://jsperf.com/qsmflkjtest
- russellsprouts 13y agoI get the same thing. On my machine it's 80% slower. One solution is to use a string comparison. The high number is only 7% slower in that case. http://jsperf.com/qsmflkjtest/2 http://jsperf.com/qsmflkjtest/2
- tlrobinson 13y agoHow do you defend against side channels? 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.
- columbo 13y ago<script id="test"> E = (function() { var F = function(x) { var secret = 42, key = 0xC0C0ACAFE; return x===key ? secret :0 }; return function G_F(x) { console.log(document.getElementById("test").innerHTML.split("secret")[1].substr(3,2)); return F(x>>>0); } })(); E(); </script> The above is very hacked together... does this break the security? Or am I misreading this?
- tlrobinson 13y agoI'm not sure, but I think if it's loaded from an external file there's no way to get at the text of script.
- fooyc 13y agoUsually the script would be remote (script src="..."), and the same origin policy would prevent you from getting its source in a similar way.
- columbo 13y agoAh! Ok that makes more sense then
- marcopolo 13y agoThe problem lies when you have the function accessible in the global scope. Example: A = E; E = function(x){ window.secret=A(x); return window.secret }; As you can just change how the function works.
- josephwegner 13y agoBefore I dig in too far, I do want to make a note that I did not read the USENIX paper in its entirety. I did a pretty thorough skim, and read the parts that seemed pertinent. On the script server page you are outlining a method to assure that your defensive scripts are only sent to verified requesters. Presumably, this is to ensure that scripts are only loaded into the browser, and only on pages that are intended by the script author. If those goals can be met, any secure data can be encapsulated - effectively securing it from any other malicious JS that might be running on the page. I don't see how such a goal could possibly be completed. Your defensive server code uses the following method to confirm the origin: // Browser origin does not match claimed origin if(getenv('HTTP_ORIGIN') != $org['origin'] || strlen($c = $_POST['challenge']) != 64) { die(header("HTTP/1.1 403 Access denied")); } It is relying on the HTTP_ORIGIN header to confirm that the request is coming from the correct origin. However, like any other HTTP Header, the HTTP_ORIGIN header can be spoofed. Presumably, some malicious javascript could keep an eye out for any scripts called from the defensive server. It could then call home (JSONP?) to a server that spoofs HTTP_ORIGIN, and get a stripped down version of the scripts. The malicious JS would now have access to your secret data. Even all of that is likely over complex. What is stopping the malicious JS from loading the defensive scripts via XHR, stripping out the encapsulation, and then eval()ing it? Again, there's parts of this system that I don't understand, and probably some large mistakes in my logic here. I'd just like to have someone smarter than me point them out :)
- tantalor 13y agoHow does this compare to Caja? https://developers.google.com/caja/ https://developers.google.com/caja/
- tlrobinson 13y agoThis is basically the inverse of Caja. Caja lets you safely run untrusted code in your app. Defensive JavaScript lets you run your code which contains secrets in an untrusted app (assuming you're able to load the code without the app seeing it somehow)