mirror of
https://github.com/kkapsner/CanvasBlocker
synced 2024-12-22 12:50:36 +01:00
Improved iFrame protection
This commit is contained in:
parent
92ff2ff5d4
commit
2da680bfcb
44
lib/frame.js
44
lib/frame.js
@ -11,6 +11,7 @@
|
|||||||
const {check: originalCheck, checkStack: originalCheckStack} = require("./check");
|
const {check: originalCheck, checkStack: originalCheckStack} = require("./check");
|
||||||
const {getWrapped} = require("./modifiedAPIFunctions");
|
const {getWrapped} = require("./modifiedAPIFunctions");
|
||||||
const extension = require("./extension");
|
const extension = require("./extension");
|
||||||
|
const iframeProtection = require("./iframeProtection");
|
||||||
|
|
||||||
const logging = require("./logging");
|
const logging = require("./logging");
|
||||||
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = logging;
|
const {error, warning, message, notice, verbose, setPrefix: setLogPrefix} = logging;
|
||||||
@ -149,41 +150,16 @@
|
|||||||
{check, checkStack, ask: askWrapper, notify, prefs}
|
{check, checkStack, ask: askWrapper, notify, prefs}
|
||||||
);
|
);
|
||||||
message("prepare to intercept (i)frames.");
|
message("prepare to intercept (i)frames.");
|
||||||
|
|
||||||
[window.HTMLIFrameElement, window.HTMLFrameElement].forEach(function(constructor){
|
function interceptAllFrames(){
|
||||||
var oldContentWindowGetter = constructor.prototype.__lookupGetter__("contentWindow");
|
const currentLength = window.length;
|
||||||
Object.defineProperty(
|
for (let i = currentLength; i--;){
|
||||||
getWrapped(constructor.prototype),
|
if (!interceptedWindows.get(wrappedWindow[i])){
|
||||||
"contentWindow",
|
interceptWindow(window[i]);
|
||||||
{
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true,
|
|
||||||
get: exportFunction(function(){
|
|
||||||
var window = oldContentWindowGetter.call(this);
|
|
||||||
if (window){
|
|
||||||
interceptWindow(window);
|
|
||||||
}
|
|
||||||
return window;
|
|
||||||
}, window)
|
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
var oldContentDocumentGetter = constructor.prototype.__lookupGetter__("contentDocument");
|
}
|
||||||
Object.defineProperty(
|
iframeProtection.protect(window, wrappedWindow, interceptWindow, interceptAllFrames);
|
||||||
getWrapped(constructor.prototype),
|
|
||||||
"contentDocument",
|
|
||||||
{
|
|
||||||
enumerable: true,
|
|
||||||
configurable: true,
|
|
||||||
get: exportFunction(function(){
|
|
||||||
var document = oldContentDocumentGetter.call(this);
|
|
||||||
if (document){
|
|
||||||
interceptWindow(document.defaultView);
|
|
||||||
}
|
|
||||||
return document;
|
|
||||||
}, window)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const matchMediaDescriptor = Object.getOwnPropertyDescriptor(wrappedWindow, "matchMedia");
|
const matchMediaDescriptor = Object.getOwnPropertyDescriptor(wrappedWindow, "matchMedia");
|
||||||
const originalMatchMedia = matchMediaDescriptor.value;
|
const originalMatchMedia = matchMediaDescriptor.value;
|
||||||
|
150
lib/iframeProtection.js
Normal file
150
lib/iframeProtection.js
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
(function(){
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let scope;
|
||||||
|
if ((typeof exports) !== "undefined"){
|
||||||
|
scope = exports;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scope = require.register("./iframeProtection", {});
|
||||||
|
}
|
||||||
|
const {getWrapped} = require("./modifiedAPIFunctions");
|
||||||
|
|
||||||
|
scope.protect = function protect(window, wrappedWindow, singleCallback, allCallback){
|
||||||
|
|
||||||
|
|
||||||
|
[window.HTMLIFrameElement, window.HTMLFrameElement].forEach(function(constructor){
|
||||||
|
var oldContentWindowGetter = constructor.prototype.__lookupGetter__("contentWindow");
|
||||||
|
Object.defineProperty(
|
||||||
|
getWrapped(constructor.prototype),
|
||||||
|
"contentWindow",
|
||||||
|
{
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get: exportFunction(function(){
|
||||||
|
var window = oldContentWindowGetter.call(this);
|
||||||
|
if (window){
|
||||||
|
singleCallback(window);
|
||||||
|
}
|
||||||
|
return window;
|
||||||
|
}, window)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
var oldContentDocumentGetter = constructor.prototype.__lookupGetter__("contentDocument");
|
||||||
|
Object.defineProperty(
|
||||||
|
getWrapped(constructor.prototype),
|
||||||
|
"contentDocument",
|
||||||
|
{
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
get: exportFunction(function(){
|
||||||
|
var document = oldContentDocumentGetter.call(this);
|
||||||
|
if (document){
|
||||||
|
singleCallback(document.defaultView);
|
||||||
|
}
|
||||||
|
return document;
|
||||||
|
}, window)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
[
|
||||||
|
// useless as length could be obtained before the iframe is created and window.frames === window
|
||||||
|
// {
|
||||||
|
// object: wrappedWindow,
|
||||||
|
// methods: [],
|
||||||
|
// getters: ["length", "frames"],
|
||||||
|
// setters: []
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
object: wrappedWindow.Node.prototype,
|
||||||
|
methods: ["appendChild", "insertBefore", "replaceChild"],
|
||||||
|
getters: [],
|
||||||
|
setters: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
object: wrappedWindow.Element.prototype,
|
||||||
|
methods: [
|
||||||
|
"append", "prepend",
|
||||||
|
"insertAdjacentElement", "insertAdjacentHTML", "insertAdjacentText",
|
||||||
|
"replaceWith"
|
||||||
|
],
|
||||||
|
getters: [],
|
||||||
|
setters: ["innerHTML", "outerHTML"]
|
||||||
|
}
|
||||||
|
].forEach(function(protectionDefinition){
|
||||||
|
const object = protectionDefinition.object;
|
||||||
|
protectionDefinition.methods.forEach(function(method){
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(object, method);
|
||||||
|
const original = descriptor.value;
|
||||||
|
descriptor.value = exportFunction(eval(`(function ${method}(){
|
||||||
|
const value = arguments.length?
|
||||||
|
original.apply(this, window.Array.from(arguments)):
|
||||||
|
original.call(this);
|
||||||
|
allCallback();
|
||||||
|
return value;
|
||||||
|
})`), window);
|
||||||
|
Object.defineProperty(object, method, descriptor);
|
||||||
|
});
|
||||||
|
protectionDefinition.getters.forEach(function(property){
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(object, property);
|
||||||
|
const temp = eval(`({
|
||||||
|
get ${property}(){
|
||||||
|
const ret = this.${property};
|
||||||
|
allCallback();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
})`);
|
||||||
|
descriptor.get = exportFunction(Object.getOwnPropertyDescriptor(temp, property).get, window);
|
||||||
|
Object.defineProperty(object, property, descriptor);
|
||||||
|
});
|
||||||
|
protectionDefinition.setters.forEach(function(property){
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(object, property);
|
||||||
|
const temp = eval(`({
|
||||||
|
set ${property}(value){
|
||||||
|
const ret = this.${property} = value;
|
||||||
|
allCallback();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
})`);
|
||||||
|
descriptor.set = exportFunction(Object.getOwnPropertyDescriptor(temp, property).set, window);
|
||||||
|
Object.defineProperty(object, property, descriptor);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// MutationObserver to intercept iframes while generating the DOM.
|
||||||
|
var observer = new MutationObserver(allCallback);
|
||||||
|
observer.observe(window.document.documentElement, {subtree: true, childList: true});
|
||||||
|
window.document.addEventListener("DOMContentLoaded", function(){
|
||||||
|
observer.disconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
// MutationObserver does not trigger fast enough when document.write is used
|
||||||
|
const documentWriteDescriptor = Object.getOwnPropertyDescriptor(wrappedWindow.HTMLDocument.prototype, "write");
|
||||||
|
const documentWrite = documentWriteDescriptor.value;
|
||||||
|
documentWriteDescriptor.value = exportFunction(function write(str){
|
||||||
|
const parts = str.split(/(?=>)/);
|
||||||
|
const length = parts.length;
|
||||||
|
for (let i = 0; i < length; i += 1){
|
||||||
|
documentWrite.call(this, parts[i]);
|
||||||
|
allCallback();
|
||||||
|
}
|
||||||
|
}, window);
|
||||||
|
Object.defineProperty(wrappedWindow.HTMLDocument.prototype, "write", documentWriteDescriptor);
|
||||||
|
|
||||||
|
const documentWritelnDescriptor = Object.getOwnPropertyDescriptor(wrappedWindow.HTMLDocument.prototype, "writeln");
|
||||||
|
const documentWriteln = documentWritelnDescriptor.value;
|
||||||
|
documentWritelnDescriptor.value = exportFunction(function writeln(str){
|
||||||
|
const parts = str.split(/(?=>)/);
|
||||||
|
const length = parts.length - 1;
|
||||||
|
for (let i = 0; i < length; i += 1){
|
||||||
|
documentWrite.call(this, parts[i]);
|
||||||
|
allCallback();
|
||||||
|
}
|
||||||
|
documentWriteln.call(this, parts[length]);
|
||||||
|
}, window);
|
||||||
|
Object.defineProperty(wrappedWindow.HTMLDocument.prototype, "writeln", documentWritelnDescriptor);
|
||||||
|
};
|
||||||
|
}());
|
@ -58,6 +58,7 @@
|
|||||||
|
|
||||||
"lib/lists.js",
|
"lib/lists.js",
|
||||||
"lib/check.js",
|
"lib/check.js",
|
||||||
|
"lib/iframeProtection.js",
|
||||||
|
|
||||||
"lib/frame.js"
|
"lib/frame.js"
|
||||||
]
|
]
|
||||||
|
@ -27,6 +27,7 @@ Version 0.5.9:
|
|||||||
- preventing double interception (increased performance and reduced detectability)
|
- preventing double interception (increased performance and reduced detectability)
|
||||||
- detection over navigator and DOMRect getters was possible
|
- detection over navigator and DOMRect getters was possible
|
||||||
- audio cache could break readout
|
- audio cache could break readout
|
||||||
|
- improved iFrame protection
|
||||||
|
|
||||||
known issues:
|
known issues:
|
||||||
- if a data URL is blocked the page action button does not appear
|
- if a data URL is blocked the page action button does not appear
|
||||||
|
Loading…
x
Reference in New Issue
Block a user