保护JavaScript评估功能 [英] Securing JavaScript eval function

查看:51
本文介绍了保护JavaScript评估功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们想让我们的用户能够在我们的应用程序中执行自己创建的JavaScript代码.为此,我们需要使用 eval 来评估代码.为了将所有安全问题降至最低(如果不为零),我们的想法是防止在代码中使用任何 window document 函数.因此,没有 XMLHttpRequest 或类似的内容.

We want to give our users the ability to execute self created JavaScript code within our application. For this we need to use eval to evaluate the code. To reduce all security concerns to a minimum (if not zero), our idea is to prevent the usage of any window or document function within the code. So no XMLHttpRequest or anything similar.

这是代码:

function secure_eval(s) {
    var ret;

    (function(){
        var copyXMLHttpRequest = XMLHttpRequest; // save orginal function in copy

        XMLHttpRequest = undefined; // make orignal function unavailable

        (function() {
            var copyXMLHttpRequest; // prevent access to copy

            try {
                ret = eval(s)
            } catch(e) {
                console.log("syntax error or illegal function used");
            }

        }())
        XMLHttpRequest = copyXMLHttpRequest; // restore original function
    }())
    return ret;
}

其工作原理如下:

secure_eval('new XMLHttpRequest()'); // ==> "illegal function used"

现在我有几个问题:

  1. 此模式是保护 eval 的正确方法吗?
  2. 窗口 document 的哪些功能被认为是有害的?
  3. 要解决问题2.我试图掩盖 window 的所有(本机)功能,但是我无法枚举它们:
  1. Is this pattern the right way to secure eval?
  2. What functions of window and document are the ones which are considered harmful?
  3. To ship around question 2. I tried to mask all (native) functions of window But I am not able to enumerate them:

这不会列出 XMLHttpRequest 例如:

for( var x in window) {
    if( window[x] instanceof Function) {
        console.log(x);
    }
}

有没有办法获取 window document 的所有本机功能的列表?

Is there a way to get a list of all native functions of window and document?

我的想法之一是在 Worker 中执行 eval ,并阻止访问 XMLHttpRequest document.createElement (请参阅上面的解决方案).(在我看来)这将带来以下后果:

One of my ideas is to perform the eval within a Worker and prevent access to XMLHttpRequest and document.createElement (see my solution above). This would have (to my mind) the following consequences:

  • 无法访问原始的文档
  • 无法访问原始的窗口
  • 没有机会与外部资源进行交流(没有ajax,没有脚本)

您在这里看到任何缺点或泄漏吗?

Do you see any drawback or leaks here?

在此期间,我发现了这个问题,该答案解决了很多问题问题以及我什至没有想到的几件事(例如,使用"while(true){}" 的浏览器死锁.

In the meantime I have found this question which answer solves many of my problems plus a couple of things I did not even think about (i.e. browser dead lock with "while(true){}".

推荐答案

您的代码实际上并未阻止使用 XMLHttpRequest .我可以实例化 XMLHttpRequest对象具有以下方法:

Your code does not actually prevent the use of XMLHttpRequest. I can instantiate an XMLHttpRequest object with these methods:

secure_eval("secure_eval = eval"); // Yep, this completely overwrites secure_eval.
secure_eval("XMLHttpRequest()");

或者:

secure_eval("new (window.open().XMLHttpRequest)()")

或者:

secure_eval("new (document.getElementById('frame').contentWindow.XMLHttpRequest)()")

此第三种方法依赖于页面HTML中 iframe 的存在,有人可以通过在其浏览器中操作DOM来添加.我不时使用Greasemonkey进行此类操作,以消除烦恼或修复损坏的GUI.

This 3rd method relies on the presence of an iframe in the HTML of the page, which someone could add by manipulating the DOM in their browser. I do such manipulations every now and then with Greasemonkey to remove annoyances or fix broken GUIs.

这花了我大约5分钟的时间来弄清楚,我绝对不是安全专家.这些只是我能够很快找到的漏洞,可能还有其他我不知道的漏洞.这里的教训是,真的很难通过 eval 保护代码.

This took me about 5 minutes to figure out, and I am not by any means a security guru. And these are only the holes I was able to find quickly, there are probably others, that I don't know about. The lesson here is that it is really really really hard to secure code through eval.

好,所以使用 Worker 来运行代码将解决上述第二种情况和第三种情况,因为在 Worker 中没有可访问的窗口.而且...嗯..第一种情况可以通过在其作用域内加上 secure_eval 来处理.故事结局?如果只有...

Ok, so using a Worker to run the code is going to take care of the 2nd and 3rd cases above because there's no window accessible in a Worker. And... hmm.. the 1st case can be handled by shadowing secure_eval inside its scope. End of story? If only...

如果将 secure_eval 放在网络工作者中并运行以下代码,则可以重新获取 XMLHttpRequest :

If I put secure_eval inside a web worker and run the following code, I can reacquire XMLHttpRequest:

secure_eval("var old_log = console.log; console.log = function () { foo = XMLHttpRequest; old_log.apply(this, arguments); };");
console.log("blah");
console.log(secure_eval("foo"));

原理是通过将 secure_eval 之外使用的函数覆盖,以将 XMLHttpRequest 分配给将被故意泄漏的变量,以捕获该函数到工作人员的全局空间,请等待直到 secure_eval 之外的工作人员使用了该函数,然后获取保存的值.上面的第一个 console.log 模拟了 secure_eval 之外的篡改函数的使用,第二个 console.log 显示该值已被捕获.我使用了 console.log ,因为为什么不呢?但实际上,可以像这样修改全局空间中的任何函数.

The principle is to override a function that is used outside secure_eval to capture XMLHttpRequest by assigning it to a variable that will be deliberately leaked to the global space of the worker, wait until that function is used by the worker outside secure_eval, and then grab the saved value. The first console.log above simulates the use of the tampered function outside secure_eval and the 2nd console.log shows that the value was captured. I've used console.log because why not? But really any function in the global space could be modified like this.

实际上,为什么要等到工人可以使用我们篡改过的某些功能?这是访问 XMLHttpRequest 的另一种更好,更快的方法:

Actually, why wait until the worker may use some function we tampered with? Here's another, better, quicker way to do access XMLHttpRequest:

secure_eval("setTimeout(function () { console.log(XMLHttpRequest);}, 0);");

即使在工作人员(具有原始的 console.log )中,这也会将 XMLHttpRequest 的实际值输出到控制台.我还将注意到,传递给 setTimeout 的函数中的 this 的值是全局作用域对象(即,不在工作区中时的 window ,或工作者中的 self ),不受任何变量阴影的影响.

Even in a worker (with a pristine console.log), this will output the actual value of XMLHttpRequest to the console. I'll also note that the value of this inside the function passed to setTimeout is the global scope object (i.e. window when not in a worker, or self in a worker), unaffected by any variable shadowing.

此处解决方案如何?好得多了,但是在Chrome 38中运行时仍然有一个漏洞:

What about the solution here? Much much better but there is still a hole when run in Chrome 38:

makeWorkerExecuteSomeCode('event.target.XMLHttpRequest', 
    function (answer) { console.log( answer ); });

这将显示:

function XMLHttpRequest() { [native code] }

再说一次,我不是安全专家,也不是想引起麻烦的饼干.我可能还没有想到更多的方法.

Again, I'm no security guru or cracker bent on causing trouble. There are probably still more ways I'm not thinking about.

这篇关于保护JavaScript评估功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆