Skip to content

Commit

Permalink
Deny access to web accessible resources w/o secret
Browse files Browse the repository at this point in the history
  • Loading branch information
ghostwords committed Sep 20, 2021
1 parent 924f859 commit 6770b50
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 9 deletions.
3 changes: 3 additions & 0 deletions src/data/web_accessible_resources/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
While the scripts here are exposed to websites (as per the web_accessible_resources manifest key), access is controlled by Privacy Badger via per-request single-use secret tokens. This means Privacy Badger alone controls whether a website has access to these resources.

Search for `warAccessTokens` for the exact implementation.
8 changes: 6 additions & 2 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,17 @@ Badger.prototype = {
},
frames: {
<frame_id>: {
url: {String},
url: {String}
host: {String}
warAccessTokens: {
<extension_resource_URL>: {String} access token
...
}
},
...
},
origins: {
domain.tld: {String} action taken for this domain
<third_party_fqdn>: {String} action taken for this domain
...
}
},
Expand Down
8 changes: 5 additions & 3 deletions src/js/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
* along with Privacy Badger. If not, see <http://www.gnu.org/licenses/>.
*/

require.scopes.constants = (function() {
require.scopes.constants = (function () {

var exports = {
let exports = {

// Tracking status constants
NO_TRACKING: "noaction",
Expand All @@ -30,6 +30,7 @@ var exports = {
USER_COOKIEBLOCK: "user_cookieblock",

// URLS
WEBEXT_SCHEME: chrome.runtime.getURL(''),
CNAME_DOMAINS_LOCAL_URL: chrome.runtime.getURL('data/cname_domains.json'),
DNT_POLICIES_URL: "https://www.eff.org/files/dnt-policies.json",
DNT_POLICIES_LOCAL_URL: chrome.runtime.getURL('data/dnt-policies.json'),
Expand All @@ -52,4 +53,5 @@ exports.BLOCKED_ACTIONS = new Set([
]);

return exports;
})();

}());
5 changes: 3 additions & 2 deletions src/js/surrogates.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@

require.scopes.surrogates = (function () {

const db = require('surrogatedb');
const constants = require('constants'),
db = require('surrogatedb');

/**
* @return {(String|Boolean)} The surrogate script pattern token
Expand Down Expand Up @@ -97,7 +98,7 @@ function getSurrogateUri(script_url, script_hostname) {
}

// extension URL
if (code.startsWith(chrome.runtime.getURL(''))) {
if (code.startsWith(constants.WEBEXT_SCHEME)) {
return code;
}

Expand Down
44 changes: 44 additions & 0 deletions src/js/webrequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ function onBeforeRequest(details) {
if (type == 'script') {
let surrogate = getSurrogateUri(url, request_host);
if (surrogate) {
if (surrogate.startsWith(constants.WEBEXT_SCHEME)) {
let frameData = badger.getFrameData(tab_id, frame_id),
tokens = frameData.warAccessTokens;
if (!tokens) {
tokens = {};
frameData.warAccessTokens = tokens;
}
let secret = (+(("" + Math.random()).slice(2))).toString(16);
tokens[surrogate] = secret;
surrogate = surrogate + '?key=' + secret;
}
return {redirectUrl: surrogate};
}
}
Expand Down Expand Up @@ -132,6 +143,33 @@ function onBeforeRequest(details) {
return {cancel: true};
}

/**
* Guards against web_accessible_resources abuse.
*
* @param {Object} details webRequest request details object
*
* @returns {Object|undefined} Can cancel requests
*/
function filterWarRequests(details) {
let url = details.url,
frameData = badger.getFrameData(details.tabId, details.frameId),
tokens = frameData && frameData.warAccessTokens;

if (!tokens) {
return { cancel: true };
}

let qs_start = url.indexOf('?'),
url_no_qs = qs_start && url.slice(0, qs_start),
secret = url_no_qs && tokens[url_no_qs];

if (!secret || url != `${url_no_qs}?key=${secret}`) {
return { cancel: true };
}

delete tokens[url_no_qs];
}

/**
* Filters outgoing cookies and referer
* Injects DNT
Expand Down Expand Up @@ -1374,6 +1412,12 @@ function startListeners() {

chrome.webRequest.onBeforeRequest.addListener(onBeforeRequest, {urls: ["http://*/*", "https://*/*"]}, ["blocking"]);

chrome.webRequest.onBeforeRequest.addListener(filterWarRequests, {
urls: [
chrome.runtime.getURL('/data/web_accessible_resources/') + '*',
]
}, ["blocking"]);

let extraInfoSpec = ['requestHeaders', 'blocking'];
if (chrome.webRequest.OnBeforeSendHeadersOptions.hasOwnProperty('EXTRA_HEADERS')) {
extraInfoSpec.push('extraHeaders');
Expand Down
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
"background": {
"scripts": [
"js/bootstrap.js",
"js/constants.js",
"lib/publicSuffixList.js",
"lib/basedomain.js",
"data/surrogates.js",
"js/multiDomainFirstParties.js",
"js/utils.js",
"js/surrogates.js",
"js/incognito.js",
"js/constants.js",
"js/storage.js",
"js/heuristicblocking.js",
"js/socialwidgetloader.js",
Expand Down
2 changes: 1 addition & 1 deletion src/tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@
<script src="lib/vendor/sinon-2.0.0.js"></script>

<script src="../js/bootstrap.js"></script>
<script src="../js/constants.js"></script>
<script src="../js/multiDomainFirstParties.js"></script>
<script src="../js/utils.js"></script>
<script src="../data/surrogates.js"></script>
<script src="../js/surrogates.js"></script>
<script src="../js/storage.js"></script>
<script src="../js/constants.js"></script>
<script src="../js/incognito.js"></script>
<script src="../js/heuristicblocking.js"></script>

Expand Down

0 comments on commit 6770b50

Please sign in to comment.