4

我正在尝试设置一个 javascript 变量来识别是否安装了 Firefox 扩展。这个想法是在页面上读取这个变量。

在使用 XUL 附加组件(在 Firefox 扩展的页面窗口对象中设置一个对象? )并在 Firefox Add On SDK 中找到适合该任务的 contentScripts时未能使用复杂的方法实现这一点后,我仍然访问页面上 contentScript 中设置的 javascript 变量时遇到问题。

我的 main.js 中有以下内容(使用此处提供的示例https://addons.mozilla.org/en-US/developers/docs/sdk/latest/modules/sdk/page-mod.html):

var pageMod = require("sdk/page-mod");

pageMod.PageMod({
  include: "*",
  contentScript: 'window.isInstalled=true;window.alert("Page matches ruleset");',
  contentScriptWhen: "ready"
});

但是,当我尝试window.isInstalled在页面上的 javascript 中获取变量时,尽管显示了警报,但它是未定义的。

如何确保内容脚本写入的值在页面上可用?

4

1 回答 1

6

内容脚本中的window对象通常是XRayWrapper,这意味着您将取回原始对象,而不是网站可能覆盖的任何对象。这反过来也意味着,网站不会看到您对window对象所做的任何修改。

但是,unsafeWindow.isInstalled = ...应该可以工作(尽管.isInstalled非常通用,因此可能与网站已经使用的变量发生冲突)。

请参阅有关和的文档XRayWrapperunsafeWindow

解决@canuckistani 提出的非常有效的问题:

读取数据或执行函数unsafeWindow是安全的,因为它不能直接导致另一个(您的内容脚本)隔间中的代码执行。蜘蛛猴的隔间将确保这一点。其他一切都将是 Spidermonkey 或 Gecko 中的安全问题。(请注意,这仅指 Spidermonkey。IIRC 它是唯一实现隔间或膜或任何您想称呼它的引擎。其他引擎可能具有其他安全属性)。

但是,您绝对不能相信来自网站的数据,这是非常正确的。unsafeWindow只是有更多方法可以让您获得 pwnd。总是除了要抛出的代码之外,拒绝服务您会出现意外的无限循环或类似情况,并且永远不会在您的上下文中显式或隐式地评估代码。

例如,这是一个安全漏洞,无论您使用的是 window 还是 unsafeWindow:

for (var el of window.document.querySelectorAll("*[onclick]")) {
  el.addEventListener("click", el.getAttribute("onclick"));
  el.removeAttribute("onclick");
}

这将.getAttribute您的脚本上下文中从网站控制的字符串 ( ) 创建匿名函数(事件侦听器),而不是网站的上下文。

这也是不安全的,但仅在使用unsafeWindow这个时间时:

for (var el of unsafeWindow.document.querySelectorAll("p")) {
  el.addEventListener("click", 'alert("I am ' + el.clientHeight + 'px tall");');
  el.removeAttribute("onclick");
}

使用XRayWrapperWrappedwindow时,您可以确定它document实际上是文档,document.querySelectorAll实际上是一个吐出一些元素的函数,并且el.clientHeight实际上是一个数值。

经历unsafeWindow所有这些假设可能是不正确的。该网站可能做了这样的事情:

document.querySelectorAll = function() {
  return [{
    clientHeight: 'a pwnd content script"); doSomethingEvil(); alert("Now I own you! And I am certainly not 0'
  }];
};

虽然从特权升级的意义上说执行仍然是安全的unsafeWindow.document.querySelectorAll,因为被覆盖的函数仍将在网站的隔离区(安全上下文)内运行,但返回值根本不可信。

或者脚本可能做了其他事情来破坏你的东西,不一定是恶意的。例如,您的现成拒绝服务。

Object.defineProperty(document, "title", {
  get: function() { while(true); }
});
// or
Object.defineProperty(document, "title", {
  get: function() { throw new Error("get off my lawn!"); }
});
于 2013-11-14T18:11:54.120 回答