2

How can I overwrite the window.top object using a chrome extension?

This is what I'm trying:

manifest.json

{
  "name": "buster",
  "version": "0.0.41",
  "manifest_version": 2,
  "description": "Removes iframe buster scripts",
  "homepage_url": "http://google.com",
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
    "default_title": "buster buster"
  },
  "permissions": [ "webRequest", "webRequestBlocking", "<all_urls>", "tabs"],
  "web_accessible_resources": [
    "index.html"
  ],
  "content_scripts": [
  {
    "matches": ["*://*/*"],
    "run_at": "document_start",
    "js": ["buster.js"],
    "all_frames": true
  }
  ]
}

background.js

chrome.webRequest.onHeadersReceived.addListener(function (details) {
    return {responseHeaders: details.responseHeaders.filter(function(header) {
        return ((header.name.toLowerCase() !== 'x-frame-options'));
    })};
}, {
    types: ["sub_frame"],
    urls: ["<all_urls>"]
}, ["blocking", "responseHeaders"]);

chrome.browserAction.onClicked.addListener(function (tab) {
    chrome.tabs.update(tab.id, {url: chrome.extension.getURL("index.html")});
});

buster.js with all my attempts:

if (top!=self) {
    alert(location.href);
//console.log(document.head.querySelector("script:not([src])").innerHTML)
    window.self=window.top;

    Window.prototype.__defineGetter__('top',function(){return this;});

    window.top = window.top.window;


    var prevent_bust = 0  
    window.onbeforeunload = function() { prevent_bust++ }  
    setInterval(function() {  
      if (prevent_bust > 0) {  
        prevent_bust -= 2  
        window.top.location = 'http://httpstat.us/204'  
      }  
    }, 1) 
}

index.html - I'm using stackoverflow.com as an example

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title></title>
</head>
<body style="background: #ccc">
    <iframe id="ifr" src="http://stackoverflow.com/questions/37588058/inject-javascript-at-the-very-top-of-the-page-anti-iframe-buster" width="555" height="555"></iframe>
    <!-- http://time.com/4356072/missing-japanese-boy-found-forest/?xid=homepage -->
</body>
</html>

Extension zip file

Cornwell
  • 3,304
  • 7
  • 51
  • 84

2 Answers2

7

I am a few minutes late... :-)

You need to inject the "buster.js" into the page, you are executing it in the sandboxed environment of the content script. While content scripts have access to the page's DOM, they do not share its JavaScript execution environment (window). A nice overview is here: Insert code into the page context using a content script.

Change your buster.js to this and it will work:

var el = document.createElement("script");
el.textContent = "if (top !== self) {window.self = window.top;}";
document.documentElement.appendChild(el);
Community
  • 1
  • 1
Petr Srníček
  • 2,296
  • 10
  • 22
  • BTW: I have tried this before but it never occured to me to change the `self` property, I only tried `window.top = window.self` which doesn't work. It has to be the other way. – Petr Srníček Jun 03 '16 at 18:06
  • 1
    Completely forgot about the content script isolation. I was going crazy why it didn't work. Thank you – Cornwell Jun 04 '16 at 07:36
  • This won't work for window !== window.top . Both window and window.top are read only. I think the only way in this case is to intercept the data on request and replace strings: 'window.top' to 'window' - it still won't cover all cases though. – Maciej Krawczyk Sep 23 '19 at 15:27
1

AFAIK you cannot override the window.top from your content script. This is because your content script is running in an isolated world and cannot muck with any JavaScript variables or functions that reside in the page.

From the Chrome Extension documentation:

Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.

Read more about the Execution Environment.

EDIT: Also see this excellent answer for more info.

Community
  • 1
  • 1
Titus
  • 4,487
  • 6
  • 32
  • 42