背景:
我正在运行仅具有“ allow-scripts”许可的沙盒iframe。在沙盒中,脚本加载了用户提供的自定义js。现在,我想管理对诸如XMLHttpRequest之类的全局函数/对象的访问。目前,我通过以下代码实现了这一目标:
const CLEARED_WINDOW_SCOPE= {};
const scope = { /* Here goes the globals the script should have access too */};
const propertyNames = Object.getOwnPropertyNames(window);
for(let property of propertyNames){
CLEARED_WINDOW_SCOPE[property] = undefined;
}
with(CLEARED_WINDOW_SCOPE){
with(scope){
(function (window, self, frames, globalThis){
${scriptContent}
}).call(scope, scope, scope, scope, scope);
}
}
脚本执行以下操作:
with
语句包装用户代码,第一个清除所有全局变量,第二个清除对定义的全局变量的访问权限scope
作为this
值调用的函数包装用户代码到目前为止,一切正常,但例外。
问题:
我现在遇到的主要问题是,当用户定义这样的函数时:
function aFunction(){
console.log(this);
}
他可以访问普通窗口对象,因为函数中的默认this
值为窗口。
问题:
是否可以通过某种方式将函数的默认this
值更改为周围示波器的this
值。由于用户创建了脚本,因此我无法用aFunction.bind(scope)
包装所有函数调用。还是有其他任何值可防止访问全局窗口对象?
是否可以将函数的默认this值更改为周围范围的this值。
否,但是您可以做第二件好事(?):将其设置为undefined
。只是强制严格模式:
"use strict";
// User's code
(function (){
console.log(this)
})();
而且,我不是JavaScript安全专家,但是由于原型污染等原因,JS沙箱是一个非常复杂的话题。
编辑:如注释中所述,CherryDT并不完全安全。例如,用户仍然可以通过使用<iframe>
构造函数创建函数来访问window
Function
。另外,可以通过window
<iframe>
(window
)获得对主window.parent
的引用。
可以将这种解决方案用于用户提供的代码(因为用户只能打开DevTools控制台并开始输入),但是请确保代码来自用户,而不是来自URL。搜索参数,例如。如果代码完全不可信,我建议使用window.parent
之类的知名库。