Added protection for history.length

As requested by #231.
This commit is contained in:
kkapsner 2018-08-27 00:30:48 +02:00
parent 4c7b83aca6
commit fd7c4fabbd
12 changed files with 161 additions and 19 deletions

View File

@ -18,6 +18,7 @@ Geschützte "Fingerprinting"-APIs:
<li>canvas 2d</li> <li>canvas 2d</li>
<li>webGL</li> <li>webGL</li>
<li>audio</li> <li>audio</li>
<li>history</li>
</ul> </ul>
Falls Sie Fehler finden oder Verbesserungsvorschläge haben, teilen Sie mir das bitte auf https://github.com/kkapsner/CanvasBlocker/issues mit. Falls Sie Fehler finden oder Verbesserungsvorschläge haben, teilen Sie mir das bitte auf https://github.com/kkapsner/CanvasBlocker/issues mit.

View File

@ -18,6 +18,7 @@ Protected "fingerprinting" APIs:
<li>canvas 2d</li> <li>canvas 2d</li>
<li>webGL</li> <li>webGL</li>
<li>audio</li> <li>audio</li>
<li>history</li>
</ul> </ul>
Please report issues and feature requests at https://github.com/kkapsner/CanvasBlocker/issues Please report issues and feature requests at https://github.com/kkapsner/CanvasBlocker/issues

View File

@ -93,6 +93,10 @@
"message": "Audio API", "message": "Audio API",
"description": "" "description": ""
}, },
"section_history-api":{
"message": "History API",
"description": ""
},
"displayAdvancedSettings_title": { "displayAdvancedSettings_title": {
"message": "Expertenmodus", "message": "Expertenmodus",
@ -177,6 +181,18 @@
"message": "Wollen Sie das Auslesen über die Audio-API erlauben?", "message": "Wollen Sie das Auslesen über die Audio-API erlauben?",
"description": "" "description": ""
}, },
"askForHistoryPermission": {
"message": "Wollen Sie die History-API erlauben?",
"description": ""
},
"askForHistoryInputPermission": {
"message": "Wollen Sie das Schreiben in über die History-API erlauben?",
"description": ""
},
"askForHistoryReadoutPermission": {
"message": "Wollen Sie das Auslesen über die History-API erlauben?",
"description": ""
},
"askOnlyOnce_title": { "askOnlyOnce_title": {
"message": "Nur einmal nachfragen", "message": "Nur einmal nachfragen",
"description": "" "description": ""
@ -500,6 +516,10 @@
"message": "Audioauslese vorgetäuscht auf {url}", "message": "Audioauslese vorgetäuscht auf {url}",
"description": "" "description": ""
}, },
"fakedHistoryReadout": {
"message": "History-Auslese vorgetäuscht auf {url}",
"description": ""
},
"fakedInput": { "fakedInput": {
"message": "Bei Ausgabe vorgetäuscht auf {url}", "message": "Bei Ausgabe vorgetäuscht auf {url}",
"description": "" "description": ""
@ -804,6 +824,15 @@
"description": "" "description": ""
}, },
"historyLengthThreshold_title": {
"message": "History-Längenschwellwert",
"description": ""
},
"historyLengthThreshold_description": {
"message": "Maximale Länge der Browser-History, die der Web-Seite mitgeteilt wird.",
"description": ""
},
"theme_title": { "theme_title": {
"message": "Theme", "message": "Theme",
"description": "" "description": ""

View File

@ -93,6 +93,10 @@
"message": "Audio API", "message": "Audio API",
"description": "" "description": ""
}, },
"section_history-api":{
"message": "History API",
"description": ""
},
"displayAdvancedSettings_title": { "displayAdvancedSettings_title": {
"message": "Expert mode", "message": "Expert mode",
@ -177,6 +181,18 @@
"message": "Do you want to allow audio readout?", "message": "Do you want to allow audio readout?",
"description": "" "description": ""
}, },
"askForHistoryPermission": {
"message": "Do you want to allow the history API?",
"description": ""
},
"askForHistoryInputPermission": {
"message": "Do you want to allow history-API input?",
"description": ""
},
"askForHistoryReadoutPermission": {
"message": "Do you want to allow history readout?",
"description": ""
},
"askOnlyOnce_title": { "askOnlyOnce_title": {
"message": "Ask only once", "message": "Ask only once",
"description": "" "description": ""
@ -500,6 +516,10 @@
"message": "Faked audio readout on {url}", "message": "Faked audio readout on {url}",
"description": "" "description": ""
}, },
"fakedHistoryReadout": {
"message": "Faked history readout on {url}",
"description": ""
},
"fakedInput": { "fakedInput": {
"message": "Faked at input on {url}", "message": "Faked at input on {url}",
"description": "" "description": ""
@ -803,6 +823,15 @@
"description": "" "description": ""
}, },
"historyLengthThreshold_title": {
"message": "History length threshold",
"description": ""
},
"historyLengthThreshold_description": {
"message": "Maximal length of the history that is reported to the web site.",
"description": ""
},
"theme_title": { "theme_title": {
"message": "Theme", "message": "Theme",
"description": "" "description": ""

View File

@ -86,7 +86,8 @@
visible: _("askForVisiblePermission"), visible: _("askForVisiblePermission"),
invisible: _("askForInvisiblePermission"), invisible: _("askForInvisiblePermission"),
nocanvas: _("askForPermission"), nocanvas: _("askForPermission"),
audio: _("askForAudioPermission") audio: _("askForAudioPermission"),
history: _("askForHistoryPermission"),
}, },
askStatus: { askStatus: {
alreadyAsked: {}, alreadyAsked: {},
@ -98,7 +99,8 @@
visible: _("askForVisibleInputPermission"), visible: _("askForVisibleInputPermission"),
invisible: _("askForInvisibleInputPermission"), invisible: _("askForInvisibleInputPermission"),
nocanvas: _("askForInputPermission"), nocanvas: _("askForInputPermission"),
audio: _("askForAudioInputPermission") audio: _("askForAudioInputPermission"),
history: _("askForHistoryInputPermission"),
}, },
askStatus: { askStatus: {
alreadyAsked: {}, alreadyAsked: {},
@ -110,7 +112,8 @@
visible: _("askForVisibleReadoutPermission"), visible: _("askForVisibleReadoutPermission"),
invisible: _("askForInvisibleReadoutPermission"), invisible: _("askForInvisibleReadoutPermission"),
nocanvas: _("askForReadoutPermission"), nocanvas: _("askForReadoutPermission"),
audio: _("askForAudioReadoutPermission") audio: _("askForAudioReadoutPermission"),
history: _("askForHistoryReadoutPermission"),
}, },
askStatus: { askStatus: {
alreadyAsked: {}, alreadyAsked: {},

View File

@ -486,4 +486,5 @@
}); });
} }
appendModified(modifiedAudioAPI); appendModified(modifiedAudioAPI);
appendModified(require("./modifiedHistoryAPI"));
}()); }());

56
lib/modifiedHistoryAPI.js Normal file
View File

@ -0,0 +1,56 @@
/* 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";
var scope;
if ((typeof exports) !== "undefined"){
scope = exports;
}
else {
window.scope.modifiedHistoryAPI = {};
scope = window.scope.modifiedHistoryAPI;
}
const {hasType, checkerWrapper} = require("./modifiedAPIFunctions");
scope.changedGetters = [
{
objectGetters: [function(window){return window.History.prototype;}],
name: "length",
getterGenerator: function(checker){
const temp = {
get length(){
return checkerWrapper(checker, this, arguments, function(args, check){
const {prefs, notify, window, original} = check;
const originalLength = original.apply(this, window.Array.from(args));
const threshold = prefs("historyLengthThreshold", window.location);
if (originalLength > threshold){
notify("fakedHistoryReadout");
return threshold;
}
else {
return originalLength;
}
});
}
};
return Object.getOwnPropertyDescriptor(temp, "length").get;
}
}
];
function getStatus(obj, status){
status = Object.create(status);
status.active = hasType(status, "readout");
return status;
}
scope.changedGetters.forEach(function(changedGetter){
changedGetter.type = "readout";
changedGetter.getStatus = getStatus;
changedGetter.api = "history";
});
}());

View File

@ -89,7 +89,9 @@
{name: "Audio-API", level: 1}, {name: "Audio-API", level: 1},
"getFloatFrequencyData", "getByteFrequencyData", "getFloatTimeDomainData", "getByteTimeDomainData", "getFloatFrequencyData", "getByteFrequencyData", "getFloatTimeDomainData", "getByteTimeDomainData",
"getChannelData", "copyFromChannel", "getChannelData", "copyFromChannel",
"getFrequencyResponse" "getFrequencyResponse",
{name: "History-API", level: 1},
"length",
], ],
defaultKeyValue: false defaultKeyValue: false
}, },
@ -188,6 +190,7 @@
keys: [ keys: [
"canvas", "canvas",
"audio", "audio",
"history",
], ],
defaultKeyValue: false defaultKeyValue: false
}, },
@ -236,6 +239,10 @@
return Math.floor(Math.random() * 30).toString(10); return Math.floor(Math.random() * 30).toString(10);
} }
}, },
{
name: "historyLengthThreshold",
defaultValue: 2
},
{ {
name: "blockDataURLs", name: "blockDataURLs",
defaultValue: true defaultValue: true

View File

@ -37,6 +37,7 @@
"lib/hash.js", "lib/hash.js",
"lib/modifiedAPIFunctions.js", "lib/modifiedAPIFunctions.js",
"lib/modifiedAudioAPI.js", "lib/modifiedAudioAPI.js",
"lib/modifiedHistoryAPI.js",
"lib/modifiedAPI.js", "lib/modifiedAPI.js",
"lib/randomSupplies.js", "lib/randomSupplies.js",
"lib/intercept.js", "lib/intercept.js",

View File

@ -390,6 +390,13 @@
} }
] ]
}, },
"History-API",
{
"name": "historyLengthThreshold",
"displayDependencies": {
"displayAdvancedSettings": [true]
}
},
"misc", "misc",
{ {
"name": "theme" "name": "theme"

View File

@ -11,6 +11,7 @@ Version 0.5.3:
- added theme for browser action popup - added theme for browser action popup
- added badge - added badge
- added option to ignore APIs - added option to ignore APIs
- added protection for history length
fixes: fixes:
- CSP did not work properly for worker-src - CSP did not work properly for worker-src

View File

@ -96,22 +96,28 @@ addTest("function length", function(log){
addTest("function code", function(log){ addTest("function code", function(log){
"use strict"; "use strict";
var codeDetected = false; var codeDetected = false;
if ( function checkFunctionCode(func, expectedName){
!CanvasRenderingContext2D.prototype.getImageData.toString().match( log("checking", expectedName);
/^\s*function getImageData\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/ if (!func.toString().match(
) new RegExp("^\\s*function " + expectedName + "\\s*\\(\\)\\s*\\{\\s*\\[native code\\]\\s*\\}\\s*$")
){ )){
log("unexpected function code:", CanvasRenderingContext2D.prototype.getImageData.toString()); log("unexpected function code:", func.toString());
codeDetected = true; return true;
} }
if ( return false;
!HTMLCanvasElement.prototype.toDataURL.toString().match(
/^\s*function toDataURL\s*\(\)\s*\{\s*\[native code\]\s*\}\s*$/
)
){
log("unexpected function code:", HTMLCanvasElement.prototype.toDataURL.toString());
codeDetected = true;
} }
codeDetected = checkFunctionCode(
CanvasRenderingContext2D.prototype.getImageData,
"getImageData"
) || codeDetected;
codeDetected = checkFunctionCode(
HTMLCanvasElement.prototype.toDataURL,
"toDataURL"
) || codeDetected;
codeDetected = checkFunctionCode(
history.__lookupGetter__("length"),
"get length"
) || codeDetected;
return codeDetected; return codeDetected;
}); });
addTest("toString modified", function(log){ addTest("toString modified", function(log){