Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Commit

Permalink
Block 3rd party client storage mechanisms
Browse files Browse the repository at this point in the history
Fix #313. TODO: This needs to only run if the 'Block 3rd party cookies' setting is enabled, but that is blocked on #2041.

Test page to make sure blocking is working: https://jsfiddle.net/7ke9r14a/7/

Auditors: @bbondy
  • Loading branch information
diracdeltas committed Jun 3, 2016
1 parent 9933907 commit 78f585f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 9 deletions.
78 changes: 72 additions & 6 deletions app/extensions/brave/brave-default.js
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ if (typeof KeyEvent === 'undefined') {
/**
* @return {string}
*/
function getPageScript () {
function getBlockFpPageScript () {
return '(' + Function.prototype.toString.call(function (ERROR) {
ERROR.stackTraceLimit = Infinity // collect all frames
var event_id = document.currentScript ? document.currentScript.getAttribute('data-event-id') : ''
Expand Down Expand Up @@ -1054,8 +1054,8 @@ if (typeof KeyEvent === 'undefined') {
/**
* Executes a script in the page DOM context
*
* @param text The content of the script to insert
* @param data attributes to set in the inserted script tag
* @param {string} text The content of the script to insert
* @param {Object=} data attributes to set in the inserted script tag
*/
function insertScript (text, data) {
var parent = document.documentElement
Expand All @@ -1064,8 +1064,10 @@ if (typeof KeyEvent === 'undefined') {
script.text = text
script.async = false

for (var key in data) {
script.setAttribute('data-' + key.replace('_', '-'), data[key])
if (data) {
for (var key in data) {
script.setAttribute('data-' + key.replace('_', '-'), data[key])
}
}

parent.insertBefore(script, parent.firstChild)
Expand All @@ -1084,9 +1086,73 @@ if (typeof KeyEvent === 'undefined') {
ipcRenderer.send('got-canvas-fingerprinting', e.detail)
})

insertScript(getPageScript(), {
insertScript(getBlockFpPageScript(), {
event_id: event_id
})
})
/* End canvas fingerprinting detection */

/* Begin block of third-party client-side storage */

/**
* Whether this is running in a third-party document.
*/
function is3rdPartyDoc () {
try {
// Try accessing an element that cross-origin frames aren't supposed to
window.top.document
} catch (e) {
if (e.name === 'SecurityError') {
return true
} else {
console.log('got unexpected error accessing window.top.document', e)
// Err on the safe side and assume this is a third-party frame
return true
}
}
return false
}

function blockStorage () {
console.log('blocking 3rd party storage mechanisms', window.location.href)
// Block js cookie storage
Document.prototype.__defineGetter__('cookie', () => {return ""})
Document.prototype.__defineSetter__('cookie', () => {})
// Block websql
window.openDatabase = () => { return {} }
// Block FileSystem API
window.webkitRequestFileSystem = () => { return {} }
// Block indexeddb
window.indexedDB.open = () => { return {} }

This comment has been minimized.

Copy link
@bbondy

bbondy Jun 4, 2016

Member

we may want to stub these more later.

}

function getBlockStoragePageScript () {
return '(' + Function.prototype.toString.call(blockStorage) + '());'
}

function clearStorage () {
// Clears HTML5 storage when the page is loaded/unloaded.
console.log('clearing 3rd party storage', window.location.href)
window.localStorage.clear()
window.sessionStorage.clear()
// Clear IndexedDB
var indexedDB = window.indexedDB
indexedDB.webkitGetDatabaseNames().onsuccess = (sender) => {
var dbs = sender.target.result
for (var i = 0; i < dbs.length; i++) {
// Delete each DB
indexedDB.deleteDatabase(dbs[i])
}
}
}

// TODO: This should only run if ipcRenderer sends
// block-third-party-storage. Blocked by #2041.
if (is3rdPartyDoc()) {
insertScript(getBlockStoragePageScript())
clearStorage()
window.addEventListener('unload', clearStorage)
}

/* End block of 3rd party storage */
}).apply(this)
6 changes: 3 additions & 3 deletions js/components/frame.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,9 @@ class Frame extends ImmutableComponent {
if (this.props.enableFingerprintingProtection) {
this.webview.send(messages.BLOCK_CANVAS_FINGERPRINTING)
}
if (this.props.block3rdPartyStorage) {
this.webview.send(messages.BLOCK_THIRD_PARTY_STORAGE)
}
windowActions.updateBackForwardState(
this.props.frame,
this.webview.canGoBack(),
Expand Down Expand Up @@ -507,9 +510,6 @@ class Frame extends ImmutableComponent {
})
this.webview.addEventListener('load-start', (e) => {
loadStart(e)
if (this.props.enableFingerprintingProtection) {
this.webview.send(messages.BLOCK_CANVAS_FINGERPRINTING)
}
})
this.webview.addEventListener('did-navigate', (e) => {
// only give focus focus is this is not the initial default page load
Expand Down
20 changes: 20 additions & 0 deletions js/components/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,25 @@ class Main extends ImmutableComponent {
return getSetting(settings.BLOCK_CANVAS_FINGERPRINTING) || false
}

get block3rdPartyStorage () {
if (this.activeSiteSettings) {
if (this.activeSiteSettings.get('shieldsUp') === false) {
return false
}

if (typeof this.activeSiteSettings.get('cookieControl') === 'string') {
return this.activeSiteSettings.get('cookieControl') === 'block3rdPartyCookie'
}
}

let enabled = this.props.appState.getIn(['cookieblock', 'enabled'])
if (typeof enabled !== 'boolean') {
enabled = appConfig.cookieblock.enabled
}

return enabled
}

onCloseFrame (activeFrameProps) {
windowActions.closeFrame(this.props.windowState.get('frames'), activeFrameProps)
}
Expand Down Expand Up @@ -809,6 +828,7 @@ class Main extends ImmutableComponent {
enableAds={this.enableAds}
enableNoScript={this.enableNoScript}
enableFingerprintingProtection={this.enableFingerprintingProtection}
block3rdPartyStorage={this.block3rdPartyStorage}
isPreview={frame.get('key') === this.props.windowState.get('previewFrameKey')}
isActive={FrameStateUtil.isFrameKeyActive(this.props.windowState, frame.get('key'))}
/>)
Expand Down
1 change: 1 addition & 0 deletions js/constants/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const messages = {
AUTOFILL_PASSWORD: _,
BLOCK_CANVAS_FINGERPRINTING: _,
GOT_CANVAS_FINGERPRINTING: _,
BLOCK_THIRD_PARTY_STORAGE: _,
SHOW_NOTIFICATION: _, /** @arg {string} l10n id of desktop notification message */
SET_RESOURCE_ENABLED: _,
GO_BACK: _,
Expand Down

3 comments on commit 78f585f

@bbondy
Copy link
Member

@bbondy bbondy commented on 78f585f Jun 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

++

@bbondy
Copy link
Member

@bbondy bbondy commented on 78f585f Jun 4, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to also add an issue tracked in 0.10.3 for once #2041 is done.

@diracdeltas
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.