Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace window or document objects with Javascript object

Tags:

javascript

dom

Is there a way to replace "window" or "document" objects? What I basically want is to provide some kind of JavaScript Proxy, I want to prevent user from getting "SOME" (only some! this is important) DOM element's on the page. By "user" I mean any third patty script.

I can do this:

document.getElementsByTagName("a")
//NodeList[129]
document.getElementsByTagName = function(){}
//function (){}
document.getElementsByTagName("a")
//undefined

But what I can do about document.all how can I replace DOM object field to make it return only "SOME" of the DOM elements?

UPD: If there is a way to replace 'document' object with some JavaScript object this would be much more better

UPD2: I don't care if your method won't work on 'older' browsers. So i'm good with any solution that works on "A" graders

UPD3: I know that 100% security doesn't exist in JavaScript, I don't want to prevent hackers from "HACKING", I know it's not possible, I want to prevent developers that write "plugin" for my "home made" framework, to do stupid things..

UPD4: ok, I can't replace Document nor Window, but can I at least replace all "fields" or "functions" that repsonsoble for returning "DOM" elements? like "document.getElementById" or "document.all" ?

UPD5: User @pebbl suggested something that 'close' to the thing I want

function a(window, document){
   /// in here window and document should be numerics
   alert(window);
   alert(document);
}

a(123,456);

but his solution have one big problem http://jsfiddle.net/kRLax/

UPD6-7: This is the 'perfect' one (at least for me)

http://jsfiddle.net/kRLax/12/

function Fx(){return function(){}}
function SafeThis(that){ 
    if (that == window) {
        return fakeWindow;
    } else if (that = document) {
        return fakeDocument;                    
    } else {
        return that;
    }
}
var fakeDocument = {
    write: function(a){ document.write(a) }
}
var fakeWindow = {
    document: fakeDocument
}

var moduleA = function(Function, window, document, eval){
    document.write(window + "<br>");
    var f = new Function("return this");
    document.write(f() + "<br>");
    var win = (function(){return this;})();
    document.write(win + "<br>");
    var e = eval("this"); 
    document.write(e + "<br>");
    document.write(this + "<br>");
    document.write(window + "<br>");
    document.write(document + "<br>");
    this.a = 1;
    document.write(JSON.stringify(this));
};

var moduleA_Fx = '!' + 
    moduleA.toString().replace(/\bthis\b/g,"SafeThis(this)") + 
    '(Fx,fakeWindow,fakeDocument,Fx)';

document.write(moduleA_Fx + "<br><br>");

eval(moduleA_Fx);
​
like image 505
obenjiro Avatar asked May 23 '26 18:05

obenjiro


1 Answers

You can do the following, but you would have to eval the external script within your function's scope:

function a(window, document){
  /// in here window and document should be numerics
  alert(window);
  alert(document);
}

a(123,456);

Or if you had a server-side proxy you could rewrite their code with a wrappered anon function that then called in your proxy document and window object.

;(function(window, document){

  /// the unknown external code here.

})(windowProxy, documentProxy);

There would still be ways around this however, as they might be able to use the following depending on the JS environment:

var win = (function(){return this;})();

You may also have to include the other collections to make sure they are not accessible:

;(function(window, document, all, images, ...){ ... }

But, they would also be able to access the original document through any dom elements you allowed them access to as well...

With regards to UPD6

Just in case it's useful you may also want to plug the following holes:

  • setTimeout
  • setInterval

Both the above can be used to evaluate code.

setTimeout('(function(){alert('+'th'+'is'+');})()');

Plus as you are exposing document.write this would also be feasible:

document.write(
  '<img src="data:image/gif;base64,ERROR" '+
     'onerror="alert(th'+'is.ownerDocument);" />'
);

And you should block access to SafeThis and rewrite any mention of it in the target code, otherwise it can be overriden:

SafeThis = function(that){return that;}

Other than that though it seems quite secure. I'm sure there will be other ways round it—if you try hard enough—but it really depends on how determined you think your possible attackers might be ;)

like image 119
Pebbl Avatar answered May 26 '26 08:05

Pebbl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!