有没有办法在 Javascript 中进行监狱,以便 DOM 不可见 [英] Is there a way to jail in Javascript, so that the DOM isn't visible
问题描述
我真的很想为用户提供一些脚本功能,同时不让它访问更强大的功能,比如改变 DOM.也就是说,所有输入/输出都通过给定的接口进行隧道传输.就像一种受限的javacsript.
I would really like to provide the user some scripting capabilities, while not giving it access to the more powerful features, like altering the DOM. That is, all input/output is tunneled thru a given interface. Like a kind of restricted javacsript.
示例:如果接口是checkanswer(func)
这是允许的:
Example:
If the interface is checkanswer(func)
this are allowed:
checkanswer( function (x,y)={
return x+y;
}
但这些是不允许的:alert(1)
document.write("hello world")
eval("alert()")
罢工>
but these are not allowed:
alert(1)
document.write("hello world")
eval("alert()")
我想到的是一种使用 javascript 实现的简单语言,例如 http://stevehanov.ca/blog/index.php?id=92
what I had in mind was a simple language that was implemented using javascript, something like http://stevehanov.ca/blog/index.php?id=92
推荐答案
(Edit 这个答案与您的预编辑问题有关.不知道使用 Javascript 实现的任何脚本语言,尽管我希望有一些.例如,有一次有人为 Javascript 编写了 BASIC(曾经有一个链接,但它已经腐烂了).因此,这个答案的其余部分非常学术,但我只是将其留给讨论、说明,甚至是出于警示目的.另外,我绝对同意 bobince 的观点 —不要自己做,使用他人的工作,例如 Caja.)
(Edit This answer relates to your pre-edit question. Don't know of any script languages implemented using Javascript, although I expect there are some. For instance, at one point someone wrote BASIC for Javascript (used to have a link, but it rotted). The remainder of this answer is therefore pretty academic, but I've left it just for discussion, illustration, and even cautionary purposes. Also, I definitely agree with bobince's points — don't do this yourself, use the work of others, such as Caja.)
如果您允许在用户生成的内容中编写任何脚本,请做好准备,您将进入一场军备竞赛,人们会在您的保护机制中寻找漏洞并加以利用,然后您对这些漏洞作出回应.我想我可能会回避它,但你知道你的社区和你处理虐待的选择.因此,如果您为此做好了准备:
If you allow any scripting in user-generated content, be ready for the fact you'll be entering an arms race of people finding holes in your protection mechanisms and exploiting them, and you responding to those exploits. I think I'd probably shy away from it, but you know your community and your options for dealing with abuse. So if you're prepared for that:
由于 Javascript 进行符号解析的方式,似乎应该可以在 window
、document
、ActiveXObject 的上下文中评估脚本
、XMLHttpRequest
和类似的没有它们通常的含义:
Because of the way that Javascript does symbol resolution, it seems like it should be possible to evaluate a script in a context where window
, document
, ActiveXObject
, XMLHttpRequest
, and similar don't have their usual meanings:
// 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
的情况下跨浏览器隐藏默认对象,如果您'无论如何都以文本形式接收代码......)
(Now that uses the evil eval
, but I can't immediately think of a way to shadow the default objects cross-browser without using eval
, and if you're receiving the code as text anyway...)
但它不起作用,这只是部分解决方案(更多内容见下文).那里的逻辑是,在 codeString
中的代码中尝试访问 window
(例如)将访问局部变量 window
,而不是全局变量;其他人也一样.不幸的是,由于符号的解析方式,window
的任何属性都可以使用或不使用 window.
前缀(例如,alert
),所以你也必须列出那些.这可能是一个很长的列表,尤其是因为正如 bobince 指出的那样,IE 会转储任何带有名称或 ID 的 DOM 元素到 window
.所以你可能不得不把所有这些都放在它自己的 iframe 中,这样你就可以解决那个问题,并且只"必须处理标准的东西.还要注意我如何使 scope
函数成为对象的属性,然后您仅通过该属性调用它.这就是将 this
设置为 Scoper
实例(否则,在原始函数调用中,this
默认为 window
>!).
But it doesn't work, it's only a partial solution (more below). The logic there is that any attempt within the code in codeString
to access window
(for instance) will access the local variable window
, not the global; and the same for the others. Unfortunately, because of the way symbols are resolved, any property of window
can be accessed with or without the window.
prefix (alert
, for instance), so you have to list those too. This could be a long list, not least because as bobince points out, IE dumps any DOM element with a name or an ID onto window
. So you'd probably have to put all of this in its own iframe so you can do an end-run around that problem and "only" have to deal with the standard stuff. Also note how I made the scope
function a property of an object, and then you only call it through the property. That's so that this
is set to the Scoper
instance (otherwise, on a raw function call, this
defaults to window
!).
但是,正如 bobince 所指出的,有很多不同的方法可以解决问题.例如,codeString
中的这段代码成功破解了上面的监狱:
But, as bobince points out, there are just so many different ways to get at things. For instance, this code in codeString
successfully breaks the jail above:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
现在,也许你可以更新监狱,使特定的漏洞无法工作(在所有的constructor
属性上捣乱 —all — 的内置对象),但我倾向于怀疑它.如果你可以,某人(比如 Bob)就会想出一个新的漏洞利用,比如这个:
Now, maybe you could update the jail to make that specific exploit not work (mucking about with the constructor
properties on all — all — of the built-in objects), but I tend to doubt it. And if you could, someone (like Bob) would just come up with a new exploit, like this one:
(function(){return this;})().alert("hello again from global!");
因此是军备竞赛".
唯一真正彻底的方法是在您的站点中内置一个合适的 Javascript 解析器,解析他们的代码并检查非法访问,然后才让代码运行.这是很多工作,但如果您的用例证明它是合理的...
The only really thorough way to do this would be to have a proper Javascript parser built into your site, parse their code and check for illegal accesses, and only then let the code run. It's a lot of work, but if your use-case justifies it...
这篇关于有没有办法在 Javascript 中进行监狱,以便 DOM 不可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!