Web accessible secrets can be used for at most one second

Related issue:
- https://github.com/uBlockOrigin/uBlock-issues/issues/550

Related Chromium issue (I can't access it):
- https://bugs.chromium.org/p/chromium/issues/detail?id=957866

Findings so far: affects browsers based on Chromium 74.
I could not reproduce the issue with either Chromium 73 or
Google Chrome 75.

This commit is a mitigation: to prevent sites from using
uBO's internal WAR secret for tracking purpose. A secret
can be used for at most one second, after which a new secret
is generated.

The original issue related to the implementation of
secret-gated web accessible resources is:
- https://github.com/gorhill/uBlock/issues/2823
This commit is contained in:
Raymond Hill 2019-04-30 14:36:07 -04:00
parent 2cc60fb6e8
commit 9e4385243c
No known key found for this signature in database
GPG key ID: 25E1490B761470C2
2 changed files with 36 additions and 13 deletions

View file

@ -1035,22 +1035,33 @@ vAPI.messaging.broadcast = function(message) {
// https://github.com/gorhill/uBlock/issues/3474
// https://github.com/gorhill/uBlock/issues/2823
// - foil ability of web pages to identify uBO through
// Foil ability of web pages to identify uBO through
// its web accessible resources.
// https://github.com/gorhill/uBlock/issues/3497
// - prevent web pages from interfering with uBO's element picker
// Prevent web pages from interfering with uBO's element picker
// https://github.com/uBlockOrigin/uBlock-issues/issues/550
// A specific secret can be used for at most one second.
(function() {
vAPI.warSecret =
Math.floor(Math.random() * 982451653 + 982451653).toString(36) +
vAPI.warSecret = (function() {
let lastSecretTime = 0;
const generateSecret = ( ) => {
lastSecretTime = Date.now();
return Math.floor(Math.random() * 982451653 + 982451653).toString(36) +
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
};
var key = 'secret=' + vAPI.warSecret;
var root = vAPI.getURL('/');
var guard = function(details) {
if ( details.url.indexOf(key) === -1 ) {
return { redirectUrl: root };
const secrets = [ generateSecret(), generateSecret(), generateSecret() ];
const root = vAPI.getURL('/');
const guard = function(details) {
const url = details.url;
for ( let i = 0, n = secrets.length; i < n; i++ ) {
if ( url.indexOf(`?secret=${secrets[i]}`) !== -1 ) {
return;
}
}
return { redirectUrl: root };
};
chrome.webRequest.onBeforeRequest.addListener(
@ -1060,6 +1071,18 @@ vAPI.messaging.broadcast = function(message) {
},
[ 'blocking' ]
);
return ( ) => {
const n = Math.min(
Math.floor((Date.now() - lastSecretTime) / 1000),
secrets.length
);
for ( let i = 0; i < n; i++ ) {
secrets.pop();
secrets.unshift(generateSecret());
}
return `?secret=${secrets[0]}`;
};
})();
vAPI.net = {

View file

@ -64,7 +64,7 @@ const warResolve = (function() {
};
µBlock.assets.fetchText(
`/web_accessible_resources/imported.txt?secret=${vAPI.warSecret}`,
`/web_accessible_resources/imported.txt${vAPI.warSecret()}`,
onPairsLoaded
);
};
@ -105,7 +105,7 @@ RedirectEntry.prototype.toURL = function(fctxt) {
fctxt.url.startsWith('https:')
)
) {
return this.warURL + '?secret=' + vAPI.warSecret;
return `${this.warURL}${vAPI.warSecret()}`;
}
if ( this.data.startsWith('data:') === false ) {
if ( this.mime.indexOf(';') === -1 ) {