Kad*_*ath 7 javascript scope eval
不要在标题上评判我,我知道eval是邪恶的,但我有理由这样做,而且会非常有限.事情是这样的:我想创建一个安全的空间,我可以运行特定的(和可信的)代码,并检索结果(如果它符合我的预期).出于安全原因,我想将其从所有其他范围中删除(这个空间被要求提供结果,并且不应该自己将任何内容导出到周围的范围).
我找到了一个似乎有效的解决方案,也可以为执行添加上下文,但我不确定它是否有效,或者是否存在此系统中的安全漏洞.你能告诉我它是否有问题吗?
它实际上创建了与全局变量同名的本地变量,以防止访问它们.它还剥离了功能(我将添加功能以保留我想要保留的功能).该函数被声明为最接近全局变量,以避免可见性更高的局部范围(计划删除这些特定局部变量的参数).
function contextNoScope(root, context) {
//I had to pass window as parameter for it to work properly
for(var key in root){
if(key != '0' && key != 'window'){
eval('var ' + key + '=undefined;');
}
}
var window = undefined;
var root = undefined; //root has to be forbidden too
return function() {
this.eval = function(str){ return eval(str); };
return this;
}.call(context);
}
Run Code Online (Sandbox Code Playgroud)
用法:
(function(root){
function contextNoScope(root, context) {
//...same as previous
}
var context = { x: 3 };
var space = contextNoScope(root, context);
console.log(space.eval('this.x + 1'));
})(window);
Run Code Online (Sandbox Code Playgroud)
(注意:如果您以全局方式测试此代码,请不要忘记在为上下文传递全局变量时添加特殊修复,因为它将像所有其他变量一样被屏蔽.如果您需要修复此修补程序.你想尝试传递窗口作为上下文参数,原因很明显..)
编辑:
为了更清楚地了解脚本的功能以及可以解决我的问题的原因:我假设JS中没有完全安全的东西可称为"可信源",因为我们在这里谈论的是导入脚本.通过信任,我的意思是将检查脚本源,并添加安全密钥.
每个脚本从给定的上下文中获取某个变量,并为其添加属性.这里给出了名称,这意味着我们事先知道哪些var将被修改,以及添加到其中的属性的名称和类型是什么.在某种程度上,我已经可以检查是否有意做了什么,这里的问题是"确定"任何代码将无法主要干扰事件或DOM,并且不会删除或修改任何内容在给定的上下文中,除了添加propery ..
编辑2:请打破它!
(我还不是所有网站规则的专家,如果不是正确编辑的方式,请更正我:我选择不修改第一个代码并添加新版本,即使它有点长.)
我正在寻找一个适合我的解决方案的沙箱,由比我更好的人制作,但因为我很好奇并想继续学习,我在这里发布了我所做的改进版本,因为我想知道这是怎么回事可以打破.所以我现在正在寻找可以打破这个系统的精确技巧:
function contextNoScope(context) {
var len, i, keys, val, window = root, isNaN = root.isNaN, console = root.console;
if(!context){ context = {}; }
keys = Object.getOwnPropertyNames(window);
if(len = keys.length){
for(i = 0; i < len; i++){
val = keys[i];
//TODO: remove 'console' from the if (debug purpose)
if(isNaN(val) && val != 'window' && val != 'eval' && val != 'isNaN' && val != 'console'){
eval('var ' + val + '=undefined;');
}
}
}
isNaN = undefined;
len = undefined;
i = undefined;
keys = undefined;
val = undefined;
eval('var root = undefined');
return function() {
this.eval = function(str){
if(str){
str = str.toString();
//TODO: replace by more relevant regex (it currently throws error for words like 'evaluation')
if(str.indexOf('constructor') > -1 || str.indexOf('__proto__') > -1 || str.indexOf('prototype') > -1 || str.indexOf('eval') > -1){
console.log('ERROR - str contains forbidden code "constructor", "__proto__", "eval", "prototype"', '\n' + str);
return false;
}
try{
eval(str);
return true;
}catch(e){
console.log(e + '\nin:\n' + str);
return false;
}
}
console.log('ERROR - str is not defined: ', str);
return false;
};
return this;
}.call(context);
}
Run Code Online (Sandbox Code Playgroud)
对变化的一些解释:
var评估单词的基本错误,没有必要.但是传递窗口作为另一个名称(这里是"root")似乎更容易.整个函数的包装方式与第一个版本的使用方式相同.getOwnPropertyNames以获取不可枚举的属性,但我知道向后兼容性问题,这不是我所说的"打破系统"使用旧浏览器(我已经知道)isNaN(val)这里的测试不是作为一个变量来评估窗口的数字属性,它引用了i帧eval('var root = undefined'); 是一个技巧,可以在行执行时创建var,而不是在最开始时创建var,就像在常规行中一样 varalert(1),它将无法工作)小智 0
任何基于将变量设置为影子全局变量的内容都可以被 打破Function.apply(undefined),它运行一个设置this为全局上下文的函数。例如:
(function() {
this.alert(1);
}).apply(undefined);
Run Code Online (Sandbox Code Playgroud)
任何基于正则表达式的东西都可能被以下的某种组合所破坏:
new Function,eval, ETC底线:你无法用 Javascript 构建一个有效的沙箱。已经尝试过了;每一次尝试都是复杂的、脆弱的,并最终被打破。