保护JavaScript eval功能

前端之家收集整理的这篇文章主要介绍了保护JavaScript eval功能前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们希望让用户能够在我们的应用程序中执行自己创建的 JavaScript代码.为此,我们需要使用eval来评估代码.为了将所有安全问题降至最低(如果不是零),我们的想法是防止在代码中使用任何窗口或文档功能.所以没有XMLHttpRequest或任何类似的东西.

这是代码

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"

现在我有几个问题:

这种模式是正确的方法来保护eval吗?
>窗口和文档的哪些功能被认为是有害的?
>绕过问题2.我试图掩盖窗口的所有(本机)功能但是我无法枚举它们:

这不列举XMLHttpRequest:

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

有没有办法获取窗口和文档的所有本机功能的列表?

编辑:

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

>无法访问原始文档
>无法访问原始窗口
>没有机会与外部资源进行沟通(没有ajax,没有脚本)

你在这里看到什么缺点或泄漏?

EDIT2:

在此期间,我发现了this question这个答案解决了我的许多问题,还有一些我甚至没想到的事情(即浏览器死锁与“while(true){}”).

解决方法

您的代码实际上并不阻止使用XMLHttpRequest.我可以使用以下方法实例化一个XMLHttpRequest对象:
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.

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

使用工人

好的,所以使用Worker来运行代码将会照顾第二和第三种情况,因为在Worker中没有可访问的窗口.和…嗯..第一种情况可以通过在其范围内的shadowing secure_eval来处理.故事结局?要是…

如果我把secure_eval放在一个web worker里面运行下面的代码,我可以重新获取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,因为为什么不呢?但是,真正的全局空间中的任何功能都可以像这样修改.

其实为什么要等到工作人员使用我们篡改的一些功能?这是另一个更好,更快捷的方式来访问XMLHttpRequest:

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

即使在一个工作人员(使用原始的console.log)中,这将输出XMLHttpRequest的实际值到控制台.我还会注意到,传递给setTimeout的函数中的值是全局范围对象(即不在工作中的窗口,或工作中的自身),不受任何变量阴影的影响.

这个问题提到的其他问题呢?

解决方here?更好,但在Chrome 38中运行时仍然有一个漏洞:

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

这将显示

function XMLHttpRequest() { [native code] }

再一次,我不是安全大师或者破解者,就是为了造成麻烦.可能还有更多的方法我不在想.

猜你在找的JavaScript相关文章