有没有办法在Javascript中坐牢,这样DOM就不会';看不见
我真的很想为用户提供一些脚本功能,同时不让它访问更强大的功能,比如修改DOM。也就是说,所有输入/输出都通过给定接口进行隧道传输。就像一种受限JavaCScript 例如: 如果接口是有没有办法在Javascript中坐牢,这样DOM就不会';看不见,javascript,dom,scripting,restriction,Javascript,Dom,Scripting,Restriction,我真的很想为用户提供一些脚本功能,同时不让它访问更强大的功能,比如修改DOM。也就是说,所有输入/输出都通过给定接口进行隧道传输。就像一种受限JavaCScript 例如: 如果接口是检查应答(func) 这是允许的: checkanswer( function (x,y)={ return x+y; } 但这些是不允许的: 警报(1) document.write(“你好世界”) eval(“警报()”) 编辑:我想到的是一种使用javascript实现的简单语言,类似于听起来你需要
检查应答(func)
这是允许的:
checkanswer( function (x,y)={
return x+y;
}
但这些是不允许的:警报(1)
document.write(“你好世界”)
eval(“警报()”)
编辑:我想到的是一种使用javascript实现的简单语言,类似于听起来你需要处理用户输入的数据,并根据允许内容的白名单或黑名单替换无效标记。T.J.Crowder对“军备竞赛”提出了极好的观点建造一个水密沙箱将是非常困难的 不过,可以很容易地重写某些函数 简单功能:
document.write
这样的东西也很简单
document.write = function(str) {}
如果这在您需要支持的浏览器中有效(我假设它在所有浏览器中都有效),那么这可能是最好的解决方案
备选方案:
- 将脚本沙箱化到不同子域上的IFrame中。可以操纵自己的DOM并发出alert()等,但周围的站点将保持不变。无论您选择哪种方法,您可能都必须这样做
- 使用允许函数的白名单解析用户代码。这样做也非常复杂,因为有太多的符号和变体需要处理
- 有几种方法可以监视DOM的更改,我很确定可以构建一种机制立即恢复任何更改,这与Windows的DLL管理非常类似。但这将是非常复杂的建设和非常资源密集
- (Edit这个答案与您的编辑前问题有关。我不知道有任何使用Javascript实现的脚本语言,尽管我希望有一些。例如,有人曾为Javascript编写过BASIC(以前有一个链接,但它已经腐烂)。因此,这个答案的其余部分是相当学术性的,但我把它留作讨论、说明,甚至是警告之用。此外,我绝对同意-不要自己这样做,使用其他人的作品,例如。)
如果您允许在用户生成的内容中使用任何脚本,请准备好迎接这样一个事实:您将进入一场军备竞赛,人们将在您的保护机制中发现漏洞并加以利用,您将对这些漏洞做出响应。我想我可能会避开它,但你知道你的社区和你处理虐待的选择。因此,如果你对此做好准备:
由于Javascript进行符号解析的方式,似乎可以在
窗口
、文档
、ActiveXObject
、XMLHttpRequest
、以及类似内容没有其通常含义的上下文中评估脚本:
// Define the scoper
var Scoper = (function() {
var rv = {};
rv.scope = function(codeString) {
var window,
document,
ActiveXObject,
XMLHttpRequest,
alert,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
Function,
arguments;
// etc., etc., etc.
// Just declaring `arguments` doesn't work (which makes
// sense, actually), but overwriting it does
arguments = undefined;
// Execute the code; still probably pretty unsafe!
eval(codeString);
};
return rv;;
})();
// Usage:
Scoper.scope(codeString);
(现在它使用了邪恶的eval
,但我无法立即想出一种方法,在不使用eval
的情况下,在浏览器中隐藏默认对象,并且如果您仍然以文本形式接收代码……)
但它不起作用,它只是部分解决方案(详见下文)。其中的逻辑是,在代码字符串
中的代码中,任何试图访问窗口
(例如)的尝试都将访问局部变量窗口
,而不是全局变量;其他的也一样。不幸的是,由于符号的解析方式,可以使用或不使用窗口访问窗口的任何属性。
前缀(警报,例如),因此您也必须列出这些属性。这可能是一个很长的列表,不仅仅是因为如前所述,IE会将任何带有名称或ID的DOM元素转储到窗口中。因此,您可能必须将所有这些都放在它自己的iframe中,这样您就可以围绕这个问题进行结束运行,“只”需要处理标准的东西。还要注意我是如何将范围
函数作为对象的属性的,然后您只通过属性调用它。这使得this
被设置为Scoper
实例(否则,在原始函数调用中,this
默认为window
!)
但是,正如博宾斯所指出的,有很多不同的方法可以达到目的。例如,codeString
中的这段代码成功地打破了上面的牢笼:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
现在,也许你可以更新监狱,使特定的漏洞不起作用(在所有内置对象上乱搞构造函数属性),但我倾向于怀疑它。如果可以的话,有人(比如Bob)会想出一个新的漏洞,比如:
(function(){return this;})().alert("hello again from global!");
因此出现了“军备竞赛”
要做到这一点,唯一真正彻底的方法是在站点中构建一个合适的Javascript解析器,解析它们的代码并检查非法访问,然后让代码运行。这是一个很大的工作,但是如果你的用例证明了这一点…你可以像Facebook那样做。他们正在对所有javascript源代码进行预处理,为除自己的包装器API之外的所有名称添加前缀。不太可能。JavaScript是一种非常动态的语言,具有许多隐藏的或特定于浏览器的特性,可以用来摆脱任何你可以设计的牢狱之灾
不要把这件事归咎于你自己。考虑使用现有的“迷你JS语言”项目,例如.,我得到另一种方法:使用谷歌GoelsWorksPoPAPI BR>
看到这个了吗
已创建的辅助进程没有访问权限
到DOM;对象,如文档和
窗口仅存在于主页面上。
这是工人的后果
function safe(code,args)
{
if (!args)
args=[];
return (function(){
for (i in window)
eval("var "+i+";");
return function(){return eval(code);}.apply(0,args);
})();
}
ff=function()
{
return 3.14;
}
console.log(safe("this;"));//Number
console.log(safe("window;"));//undefined
console.log(safe("console;"));//undefined
console.log(safe("Math;"));//MathConstructor
console.log(safe("JSON;"));//JSON
console.log(safe("Element;"));//undefined
console.log(safe("document;"));//undefined
console.log(safe("Math.cos(arguments[0]);",[3.14]));//-0.9999987317275395
console.log(safe("arguments[0]();",[ff]));//3.14
Number
undefined
undefined
MathConstructor
JSON
undefined
undefined
-0.9999987317275395
3.14