Get rid of eval.

This commit is contained in:
kkapsner 2019-12-12 00:09:53 +01:00
parent 32f9ea7447
commit 14a4d1cdc2
10 changed files with 96 additions and 50 deletions

View File

@ -44,5 +44,31 @@
};
Object.seal(scope.message);
scope.getWrapped = function getWrapped(obj){
return obj && (obj.wrappedJSObject || obj);
};
scope.exportFunctionWithName = function exportFunctionWithName(func, context, name){
const exportedTry = exportFunction(func, context);
if (exportedTry.name === name){
return exportedTry;
}
else {
const wrappedContext = scope.getWrapped(context);
const options = {
defineAs: name
};
const oldDescriptor = Object.getOwnPropertyDescriptor(wrappedContext, name);
const exported = exportFunction(func, context, options);
if (oldDescriptor){
Object.defineProperty(wrappedContext, name, oldDescriptor);
}
else {
delete wrappedContext[name];
}
return exported;
}
};
Object.seal(scope);
}());

View File

@ -9,7 +9,6 @@
const {ask} = require("./askForPermission");
const {sha256String: hashing} = require("./hash");
const {check: originalCheck, checkStack: originalCheckStack} = require("./check");
const {getWrapped} = require("./modifiedAPIFunctions");
const extension = require("./extension");
const iframeProtection = require("./iframeProtection");
@ -133,7 +132,7 @@
try {
// eslint-disable-next-line no-unused-vars
const href = window.location.href;
wrappedTry = getWrapped(window);
wrappedTry = extension.getWrapped(window);
}
catch (error){
// we are unable to read the location due to SOP

View File

@ -13,6 +13,7 @@
}
const settings = require("./settings");
const extension = require("./extension");
const lists = require("./lists");
function isWhitelisted(url){
@ -129,40 +130,42 @@
protectionDefinition.methods.forEach(function(method){
const descriptor = Object.getOwnPropertyDescriptor(object, method);
const original = descriptor.value;
changeProperty(object, method, "value", exportFunction(eval(`(function ${method}(){
changeProperty(object, method, "value", extension.exportFunctionWithName(function method(){
const value = arguments.length?
original.apply(this, window.Array.from(arguments)):
original.call(this);
allCallback();
return value;
})`), window));
}, window, method));
});
protectionDefinition.getters.forEach(function(property){
const temp = eval(`({
get ${property}(){
const ret = this.${property};
const descriptor = Object.getOwnPropertyDescriptor(object, property);
const temp = {
get [property](){
const ret = this[property];
allCallback();
return ret;
}
})`);
changeProperty(object, property, "get", exportFunction(
};
changeProperty(object, property, "get", extension.exportFunctionWithName(
Object.getOwnPropertyDescriptor(temp, property).get,
window
window,
descriptor.get
));
});
protectionDefinition.setters.forEach(function(property){
const descriptor = Object.getOwnPropertyDescriptor(object, property);
const setter = descriptor.set;
const temp = eval(`({
set ${property}(value){
const temp = {
set [property](value){
const ret = setter.call(this, value);
// const ret = this.${property} = value;
allCallback();
return ret;
}
})`);
changeProperty(object, property, "set", exportFunction(
Object.getOwnPropertyDescriptor(temp, property).set, window
};
changeProperty(object, property, "set", extension.exportFunctionWithName(
Object.getOwnPropertyDescriptor(temp, property).set, window, setter.name
));
});
});

View File

@ -14,7 +14,6 @@
const {changedFunctions, changedGetters, setRandomSupply} = require("./modifiedAPI");
const randomSupplies = require("./randomSupplies");
const {getWrapped} = require("./modifiedAPIFunctions");
const logging = require("./logging");
const settings = require("./settings");
const extension = require("./extension");
@ -68,7 +67,7 @@
[changedFunction.object]
).map(function(name){
if (name){
const constructor = getWrapped(windowToProcess)[name];
const constructor = extension.getWrapped(windowToProcess)[name];
if (constructor){
return constructor.prototype;
}
@ -77,7 +76,7 @@
}).concat(
changedFunction.objectGetters?
changedFunction.objectGetters.map(function(objectGetter){
return objectGetter(getWrapped(windowToProcess));
return objectGetter(extension.getWrapped(windowToProcess));
}):
[]
);
@ -96,7 +95,7 @@
changedGetters.forEach(function(changedGetter){
const name = changedGetter.name;
changedGetter.objectGetters.forEach(function(changedGetter){
const object = changedGetter(getWrapped(windowToProcess));
const object = changedGetter(extension.getWrapped(windowToProcess));
if (object){
callback({name, object, objectGetter: changedGetter});
}
@ -359,7 +358,7 @@
logging.verbose("status for", changedGetter, ":", functionStatus);
if (functionStatus.active){
changedGetter.objectGetters.forEach(function(objectGetter){
const object = objectGetter(getWrapped(windowToProcess));
const object = objectGetter(extension.getWrapped(windowToProcess));
if (object){
const descriptor = Object.getOwnPropertyDescriptor(object, name);
if (descriptor && descriptor.hasOwnProperty("get")){
@ -369,15 +368,16 @@
window: windowToProcess, prefs, checkStack, ask, notify
});
const getter = changedGetter.getterGenerator(checker, original, windowToProcess);
descriptor.get = exportFunction(getter, windowToProcess);
descriptor.get = extension.exportFunctionWithName(getter, windowToProcess, original.name);
if (descriptor.hasOwnProperty("set") && changedGetter.setterGenerator){
if (descriptor.hasOwnProperty("set") && descriptor.set && changedGetter.setterGenerator){
const original = descriptor.set;
const setter = changedGetter.setterGenerator(
windowToProcess,
descriptor.set,
original,
prefs
);
descriptor.set = exportFunction(setter, windowToProcess);
descriptor.set = extension.exportFunctionWithName(setter, windowToProcess, original.name);
}
Object.defineProperty(object, name, descriptor);

View File

@ -12,10 +12,6 @@
scope = require.register("./modifiedAPIFunctions", {});
}
scope.getWrapped = function getWrapped(obj){
return obj && (obj.wrappedJSObject || obj);
};
scope.checkerWrapper = function checkerWrapper(checker, object, args, callback){
const check = checker.call(object);
if (check.allow){

View File

@ -7,8 +7,9 @@
const scope = ((typeof exports) !== "undefined")? exports: require.register("./modifiedCanvasAPI");
const colorStatistics = require("./colorStatistics");
const logging = require("./logging");
const extension = require("./extension");
const {copyCanvasToWebgl} = require("./webgl");
const {getWrapped, checkerWrapper} = require("./modifiedAPIFunctions");
const {checkerWrapper} = require("./modifiedAPIFunctions");
let randomSupply = null;
@ -23,8 +24,8 @@
let imageData;
let source;
if ((context.canvas.width || 0) * (context.canvas.height || 0) === 0){
imageData = new (getWrapped(window).ImageData)(0, 0);
source = new (getWrapped(window).ImageData)(0, 0);
imageData = new (extension.getWrapped(window).ImageData)(0, 0);
source = new (extension.getWrapped(window).ImageData)(0, 0);
}
else if (context instanceof window.CanvasRenderingContext2D){
imageData = window.CanvasRenderingContext2D.prototype.getImageData.call(
@ -35,7 +36,7 @@
source = imageData.data;
}
else {
imageData = new (getWrapped(window).ImageData)(context.canvas.width, context.canvas.height);
imageData = new (extension.getWrapped(window).ImageData)(context.canvas.width, context.canvas.height);
source = new Uint8Array(imageData.data.length);
(
context instanceof window.WebGLRenderingContext?

View File

@ -12,7 +12,8 @@
scope = require.register("./modifiedDOMRectAPI", {});
}
const {getWrapped, checkerWrapper, setProperties, getStatusByFlag} = require("./modifiedAPIFunctions");
const extension = require("./extension");
const {checkerWrapper, setProperties, getStatusByFlag} = require("./modifiedAPIFunctions");
const {byteArrayToString: hash} = require("./hash");
@ -30,7 +31,7 @@
const registeredRects = new WeakMap();
function registerDOMRect(domRect, notify, window, prefs){
registeredRects.set(getWrapped(domRect), {
registeredRects.set(extension.getWrapped(domRect), {
notify: function(){
let done = false;
return function(message){
@ -45,7 +46,7 @@
});
}
function getDOMRectRegistration(domRect){
return registeredRects.get(getWrapped(domRect));
return registeredRects.get(extension.getWrapped(domRect));
}
const cache = {};
@ -159,8 +160,8 @@
],
name: property,
getterGenerator: function(){
const temp = eval(`({
get ${property}(){
const temp = {
get [property](){
const registration = getDOMRectRegistration(this);
if (registration){
return getFakeDomRect(
@ -168,24 +169,24 @@
this,
registration.prefs,
registration.notify
).${property};
)[property];
}
return this.${property};
return this[property];
}
})`);
};
return Object.getOwnPropertyDescriptor(temp, property).get;
}
};
if (!readonly){
changedGetter.setterGenerator = function(window, original, prefs){
const temp = eval(`({
set ${property}(newValue){
const temp = {
set [property](newValue){
const registration = getDOMRectRegistration(this);
if (registration){
const fakeDomRect = getFakeDomRect(window, this, prefs, registration.notify);
registeredRects.delete(getWrapped(this));
registeredRects.delete(extension.getWrapped(this));
["x", "y", "width", "height"].forEach((prop) => {
if (prop === "${property}"){
if (prop === property){
this[prop] = newValue;
}
else {
@ -197,7 +198,7 @@
original.apply(this, window.Array.from(arguments));
}
}
})`);
};
return Object.getOwnPropertyDescriptor(temp, property).set;
};
}

View File

@ -20,19 +20,19 @@
objectGetters: [function(window){return window.Navigator && window.Navigator.prototype;}],
name: property,
getterGenerator: function(checker){
const temp = eval(`({
get ${property}(){
const temp = {
get [property](){
return checkerWrapper(checker, this, arguments, function(args, check){
const {notify, window, original} = check;
const originalValue = original.apply(this, window.Array.from(args));
const returnValue = navigator.getNavigatorValue("${property}");
const returnValue = navigator.getNavigatorValue(property);
if (originalValue !== returnValue){
notify("fakedNavigatorReadout");
}
return returnValue;
});
}
})`);
};
return Object.getOwnPropertyDescriptor(temp, property).get;
}
};

View File

@ -205,6 +205,17 @@ addTest("function name", function(log){
},
].map(checkName).some(function(b){return b;});
});
addTest("exposed getters or setters", function(log){
"use strict";
return Object.keys(window).filter(function(key){
if (/^(get|set) /.test(key)){
log("found exposed function", JSON.stringify(key));
return true;
}
return false;
}).length !== 0;
});
addTest("property descriptor", function(log){
"use strict";

View File

@ -88,7 +88,16 @@
"use strict";
document.body.innerHTML = "<iframe></iframe>";
console.log("TEST:", "innerHTML after 1000ms:", compare(test(window[0]), reference));
log("TEST:", "innerHTML after 1000ms:", compare(test(window[0]), reference));
var iFrame = document.createElement("iframe");
document.body.appendChild(iFrame);
log("TEST:", "appendChild after 1000ms:", compare(test(window[1]), reference));
var iFrame2 = document.createElement("iframe");
iFrame.replaceWith(iFrame2);
log("TEST:", "replaceWith after 1000ms:", compare(test(window[1]), reference));
document.body.innerHTML = "<h1>Iframe protection</h1>" +
"Open console (Ctrl + Shift + K) to see results. " +
"Depending on your Browser version you might have to check the \"Persist Logs\" flag and reload the page.<br>" +