【发布时间】:2013-05-22 00:05:11
【问题描述】:
tl;dr 我可以在 iframe 上安全地执行不受信任的脚本吗?
背景故事:
我正在尝试make secure JSONP requests。许多旧浏览器不支持 Web Workers,这意味着我提出的当前解决方案不是最佳的。
我想我可以创建一个<iframe> 并在其中加载一个脚本。该脚本将执行 JSONP 请求(创建脚本标记),该请求会将消息发布到主页。主页面将获取消息,执行回调并销毁 iframe。我已经成功do this sort of thing。
function jsonp(url, data, callback) {
var iframe = document.createElement("iframe");
iframe.style.display = "none";
document.body.appendChild(iframe);
var iframedoc = iframe.contentDocument || iframe.contentWindow.document;
sc = document.createElement("script");
sc.textContent = "(function(p){ cb = function(result){p.postMessage(result,'http://fiddle.jshell.net');};})(parent);";
//sc.textContent += "alert(cb)";
iframedoc.body.appendChild(sc);
var jr = document.createElement("script");
var getParams = ""; // serialize the GET parameters
for (var i in data) {
getParams += "&" + i + "=" + data[i];
}
jr.src = url + "?callback=cb" + getParams;
iframedoc.body.appendChild(jr);
window.onmessage = function (e) {
callback(e.data);
document.body.removeChild(iframe);
}
}
jsonp("http://jsfiddle.net/echo/jsonp/", {
foo: "bar"
}, function (result) {
alert("Result: " + JSON.stringify(result));
});
问题在于,由于 iframe 在同一个域中,注入的脚本仍然可以通过.top 或.parent 等访问外部范围。
有没有办法创建一个不能访问父作用域数据的 iframe?
我想创建一个 iframe,其中通过脚本标签添加的脚本将无法访问父窗口(和 DOM)上的变量。我尝试了top=parent=null 之类的东西,但我真的不确定这是否足够,可能还有其他解决方法。我尝试在循环中运行 for...,但我的函数停止工作,我无法找出原因。
注意:
我知道 WebWorkers 是一个更好的隔离环境。我知道 JSONP 是一种“糟糕”的技术(我什至有 some random guy 告诉我他今天永远不会使用它)。我正在尝试为您必须执行 JSONP 查询的场景创建一个安全的环境。
【问题讨论】:
-
如果您将
iframe的document.domain设置为其他内容怎么办?因此,如果没有postMessage,他们将无法与其他人交谈。只是一个想法。我记得如果你将它们都设置为相同的值,你可以让它们说话,所以我想知道做相反的事情是否会产生相反的结果。我在摆弄小提琴中的一些东西;这是一个有趣的问题,我喜欢你的方法:) -
@Ian 我可以在 iframe 的代码中自己更改
document.domain吗?如果我这样做了,我能保证它不会被恶意代码改回来吗? -
是的,我很确定你可以。好吧,您也可以将父页面中的值更改为随机/唯一的值,然后 iframe 脚本很难猜测和匹配它。我想我应该在评论之前考虑整个场景,但这可能是你可以玩弄的东西。我忘记了设置它的意义以及它的实际变化,我只记得看到它被同步,以便窗口和 iframe 可以交谈(通过什么方式,我不记得了)
标签: javascript iframe security