Is It Possible to Sandbox JavaScript Running In th

2019-01-01 07:55发布

I'm wondering if it's possible to sandbox JavaScript running in the browser to prevent access to features that are normally available to JavaScript code running in an HTML page.

For example, let's say I want to provide a JavaScript API for end users to let them define event handlers to be run when "interesting events" happen, but I don't want those users to access the properties and functions of the window object. Am I able to do this?

In the simplest case, let's say I want to prevent users calling alert. A couple of approaches I can think of are:

  • Redefine window.alert globally. I don't think this would be a valid approach because other code running in the page (i.e. stuff not authored by users in their event handlers) might want to use alert.
  • Send the event handler code to the server to process. I'm not sure that sending the code to the server to process is the right approach because the event handlers need to run in the context of the page.

Perhaps a solution where the server processes the user defined function and then generates a callback to be executed on the client would work? Even if that approach works are there better ways to solve this problem?

14条回答
春风洒进眼中
2楼-- · 2019-01-01 08:36

1) Suppose you have a code to execute:

var sCode = "alert(document)";

Now, suppose you want to execute it in a sandbox:

new Function("window", "with(window){" + sCode + "}")({});

These two lines when executed will fail, because "alert" function is not available from the "sandbox"

2) And now you want to expose a member of window object with your functionality:

new Function("window", "with(window){" + sCode + "}")({
    'alert':function(sString){document.title = sString}
});

Indeed you can add quotes escaping and make other polishing, but I guess the idea is clear.

查看更多
公子世无双
3楼-- · 2019-01-01 08:38

You can wrap the user's code in a function that redefines forbidden objects as parameters -- these would then be undefined when called:

(function (alert) {

alert ("uh oh!"); // User code

}) ();

Of course, clever attackers can get around this by inspecting the Javascript DOM and finding a non-overridden object that contains a reference to the window.


Another idea is scanning the user's code using a tool like jslint. Make sure it's set to have no preset variables (or: only variables you want), and then if any globals are set or accessed do not let the user's script be used. Again, might be vulnerable to walking the DOM -- objects that the user can construct using literals might have implicit references to the window object that could be accessed to escape the sandbox.

查看更多
荒废的爱情
4楼-- · 2019-01-01 08:42

An ugly way but maybe this works for you , I took all the globals and redefined them in the sandbox scope , as well I added the strict mode so they can't get the global object using an anonymous function.

function construct(constructor, args) {
  function F() {
      return constructor.apply(this, args);
  }
  F.prototype = constructor.prototype;
  return new F();
}
// Sanboxer 
function sandboxcode(string, inject) {
  "use strict";
  var globals = [];
  for (var i in window) {
    // <--REMOVE THIS CONDITION
    if (i != "console")
    // REMOVE THIS CONDITION -->
    globals.push(i);
  }
  globals.push('"use strict";\n'+string);
  return construct(Function, globals).apply(inject ? inject : {});
}
sandboxcode('console.log( this, window, top , self, parent, this["jQuery"], (function(){return this;}()));'); 
// => Object {} undefined undefined undefined undefined undefined undefined 
console.log("return of this", sandboxcode('return this;', {window:"sanboxed code"})); 
// => Object {window: "sanboxed code"}

https://gist.github.com/alejandrolechuga/9381781

查看更多
春风洒进眼中
5楼-- · 2019-01-01 08:42

An independent Javascript interpreter is more likely to yield a robust sandbox than a caged version of the builtin browser implementation. Ryan has already mentioned js.js, but a more up-to-date project is JS-Interpreter. The docs cover how to expose various functions to the interpreter, but its scope is otherwise very limited.

查看更多
梦该遗忘
6楼-- · 2019-01-01 08:44

As mentioned in other responces, it's enough to jail the code in sandboxed iframe (without sending it to the server-side) and communicate with messages. I would suggest to take a look at a small library I created mostly because of the need to providing some API to the untrusted code, just like as described in the question: there's an opportunity to export the particular set of functions right into the sandbox where the untrusted code runs. And there's also a demo which executes the code submitted by a user in a sandbox:

http://asvd.github.io/jailed/demos/web/console/

查看更多
听够珍惜
7楼-- · 2019-01-01 08:45

Google Caja is a source-to-source translator that "allows you to put untrusted third-party HTML and JavaScript inline in your page and still be secure."

查看更多
登录 后发表回答