保护JavaScript评估功能 [英] Securing JavaScript eval function
问题描述
我们想让我们的用户能够在我们的应用程序中执行自己创建的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"
现在我有几个问题:
- 此模式是保护
eval
的正确方法吗? -
窗口
和document
的哪些功能被认为是有害的? - 要解决问题2.我试图掩盖
window
的所有(本机)功能,但是我无法枚举它们:
- Is this pattern the right way to secure
eval
? - What functions of
window
anddocument
are the ones which are considered harmful? - 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屋!