Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fingerprinting protection #44

Merged
merged 4 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions common/render_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
// user's content settings.
IPC_MESSAGE_ROUTED1(BraveViewHostMsg_JavaScriptBlocked,
base::string16 /* details on blocked content */)

IPC_MESSAGE_ROUTED1(BraveViewHostMsg_FingerprintingBlocked,
base::string16 /* details on blocked content */)
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ bool BraveShieldsWebContentsObserver::OnMessageReceived(
message, render_frame_host)
IPC_MESSAGE_HANDLER(BraveViewHostMsg_JavaScriptBlocked,
OnJavaScriptBlockedWithDetail)
IPC_MESSAGE_HANDLER(BraveViewHostMsg_FingerprintingBlocked,
OnFingerprintingBlockedWithDetail)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
Expand All @@ -149,6 +151,18 @@ void BraveShieldsWebContentsObserver::OnJavaScriptBlockedWithDetail(
base::UTF16ToUTF8(details), web_contents);
}

void BraveShieldsWebContentsObserver::OnFingerprintingBlockedWithDetail(
RenderFrameHost* render_frame_host,
const base::string16& details) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
if (!web_contents) {
return;
}
DispatchBlockedEventForWebContents(brave_shields::kFingerprinting,
base::UTF16ToUTF8(details), web_contents);
}

// static
void BraveShieldsWebContentsObserver::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterUint64Pref(kAdsBlocked, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class BraveShieldsWebContentsObserver : public content::WebContentsObserver,
void OnJavaScriptBlockedWithDetail(
content::RenderFrameHost* render_frame_host,
const base::string16& details);
void OnFingerprintingBlockedWithDetail(
content::RenderFrameHost* render_frame_host,
const base::string16& details);

DISALLOW_COPY_AND_ASSIGN(BraveShieldsWebContentsObserver);
};
Expand Down
15 changes: 15 additions & 0 deletions patches/chrome-browser-chrome_content_browser_client.cc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 8d132058b6ee5ec856a183933ffd389816885619..35ff2e225d6196364ba79d086fef0abe527c259f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -713,6 +713,10 @@ void GetGuestViewDefaultContentSettingRules(
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
content_settings::ContentSettingToValue(CONTENT_SETTING_BLOCK),
std::string(), incognito));
+ rules->fingerprinting_rules.push_back(ContentSettingPatternSource(
+ ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
+ content_settings::ContentSettingToValue(CONTENT_SETTING_ALLOW),
+ std::string(), incognito));
}

AppLoadedInTabSource ClassifyAppLoadedInTabSource(
27 changes: 27 additions & 0 deletions patches/chrome-renderer-content_settings_observer.cc.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc
index f3947e48b3a67f534772366ce3ff45bdcc13eb39..c4b62d9087eb65a31085c61306de13eb70ecdce2 100644
--- a/chrome/renderer/content_settings_observer.cc
+++ b/chrome/renderer/content_settings_observer.cc
@@ -71,10 +71,12 @@ GURL GetOriginOrURL(const WebFrame* frame) {
return top_origin.GetURL();
}

+} // namespace
+
// Allow passing both WebURL and GURL here, so that we can early return without
// allocating a new backing string if only the default rule matches.
template <typename URL>
-ContentSetting GetContentSettingFromRules(
+ContentSetting ContentSettingsObserver::GetContentSettingFromRules(
const ContentSettingsForOneType& rules,
const WebFrame* frame,
const URL& secondary_url) {
@@ -97,6 +99,8 @@ ContentSetting GetContentSettingFromRules(
return CONTENT_SETTING_DEFAULT;
}

+namespace {
+
bool IsScriptDisabledForPreview(const content::RenderFrame* render_frame) {
return render_frame->GetPreviewsState() & content::NOSCRIPT_ON;
}
25 changes: 25 additions & 0 deletions patches/chrome-renderer-content_settings_observer.h.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
diff --git a/chrome/renderer/content_settings_observer.h b/chrome/renderer/content_settings_observer.h
index 8030dcd98b1fc0e227fe07258c4f7f4ecf7fc46f..6532c1de6fc3fbd0f88d6fdcd4ed3bfcd7528b6d 100644
--- a/chrome/renderer/content_settings_observer.h
+++ b/chrome/renderer/content_settings_observer.h
@@ -103,6 +103,7 @@ class ContentSettingsObserver
}

private:
+ friend class BraveContentSettingsObserver;
FRIEND_TEST_ALL_PREFIXES(ContentSettingsObserverTest, WhitelistedSchemes);
FRIEND_TEST_ALL_PREFIXES(ContentSettingsObserverBrowserTest,
ContentSettingsInterstitialPages);
@@ -149,6 +150,12 @@ class ContentSettingsObserver
const blink::WebSecurityOrigin& origin,
const blink::WebURL& document_url);

+ template <typename URL>
+ ContentSetting GetContentSettingFromRules(
+ const ContentSettingsForOneType& rules,
+ const blink::WebFrame* frame,
+ const URL& secondary_url);
+
#if BUILDFLAG(ENABLE_EXTENSIONS)
// Owned by ChromeContentRendererClient and outlive us.
extensions::Dispatcher* const extension_dispatcher_;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc
index 991543e4c6f23831957909b5e60a143c1dd8f091..e40942011faa75a41c8cfaebad2439a172b48a24 100644
--- a/components/content_settings/core/browser/content_settings_utils.cc
+++ b/components/content_settings/core/browser/content_settings_utils.cc
@@ -143,6 +143,10 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map,
map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_CLIENT_HINTS,
ResourceIdentifier(),
&(rules->client_hints_rules));
+ map->GetSettingsForOneType(
+ CONTENT_SETTINGS_TYPE_PLUGINS,
+ "fingerprinting",
+ &(rules->fingerprinting_rules));
}

bool IsMorePermissive(ContentSetting a, ContentSetting b) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h
index 8fa4e4bef9be06e1cb742a732fb9774f2159c06c..210fad8853b3d17e44270f4151dd62b8cab101bc 100644
--- a/components/content_settings/core/common/content_settings.h
+++ b/components/content_settings/core/common/content_settings.h
@@ -72,6 +72,7 @@ struct RendererContentSettingRules {
ContentSettingsForOneType script_rules;
ContentSettingsForOneType autoplay_rules;
ContentSettingsForOneType client_hints_rules;
+ ContentSettingsForOneType fingerprinting_rules;
};

namespace content_settings {
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom
index 6766c161ab2345d2cac339d2633ee27ec86d4abe..e2be9fb1bd60a0b2a8633d9220d91b366e94eef0 100644
--- a/components/content_settings/core/common/content_settings.mojom
+++ b/components/content_settings/core/common/content_settings.mojom
@@ -72,4 +72,5 @@ struct RendererContentSettingRules {
array<ContentSettingPatternSource> script_rules;
array<ContentSettingPatternSource> autoplay_rules;
array<ContentSettingPatternSource> client_hints_rules;
+ array<ContentSettingPatternSource> fingerprinting_rules;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
diff --git a/components/content_settings/core/common/content_settings_struct_traits.cc b/components/content_settings/core/common/content_settings_struct_traits.cc
index f3426ddeea0df91b395a039fc87d7db04b51e8ba..ac5c3679b605feb1ddca2314b3ac86bd55b7b30d 100644
--- a/components/content_settings/core/common/content_settings_struct_traits.cc
+++ b/components/content_settings/core/common/content_settings_struct_traits.cc
@@ -100,6 +100,7 @@ bool StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
return data.ReadImageRules(&out->image_rules) &&
data.ReadScriptRules(&out->script_rules) &&
data.ReadAutoplayRules(&out->autoplay_rules) &&
+ data.ReadFingerprintingRules(&out->fingerprinting_rules) &&
data.ReadClientHintsRules(&out->client_hints_rules);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
diff --git a/components/content_settings/core/common/content_settings_struct_traits.h b/components/content_settings/core/common/content_settings_struct_traits.h
index f36bdde91be3f6d44f53fd042b707ec2b83b908e..ec7725fcdd2207323d7fc4a8c05b27d3bb961b16 100644
--- a/components/content_settings/core/common/content_settings_struct_traits.h
+++ b/components/content_settings/core/common/content_settings_struct_traits.h
@@ -141,6 +141,11 @@ struct StructTraits<
return r.client_hints_rules;
}

+ static const std::vector<ContentSettingPatternSource>& fingerprinting_rules(
+ const RendererContentSettingRules& r) {
+ return r.fingerprinting_rules;
+ }
+
static bool Read(
content_settings::mojom::RendererContentSettingRulesDataView data,
RendererContentSettingRules* out);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
diff --git a/third_party/WebKit/Source/core/frame/ContentSettingsClient.cpp b/third_party/WebKit/Source/core/frame/ContentSettingsClient.cpp
index fde957a1ab1e63c9b5fc66f69015641e42fb10e9..6356ba58c5f77b9c8486023f41c7faf460516bd3 100644
--- a/third_party/WebKit/Source/core/frame/ContentSettingsClient.cpp
+++ b/third_party/WebKit/Source/core/frame/ContentSettingsClient.cpp
@@ -59,6 +59,12 @@ bool ContentSettingsClient::AllowScriptFromSource(bool enabled_per_settings,
return enabled_per_settings;
}

+bool ContentSettingsClient::AllowFingerprinting(bool enabled_per_settings) {
+ if (client_)
+ return client_->AllowFingerprinting(enabled_per_settings);
+ return enabled_per_settings;
+}
+
void ContentSettingsClient::GetAllowedClientHintsFromSource(
const KURL& url,
WebEnabledClientHints* client_hints) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diff --git a/third_party/WebKit/Source/core/frame/ContentSettingsClient.h b/third_party/WebKit/Source/core/frame/ContentSettingsClient.h
index 54a5a3dd5f92e263b42c265befca66087eaadef7..d78521d2ace8a54b1692dfdfe20df436754f5b10 100644
--- a/third_party/WebKit/Source/core/frame/ContentSettingsClient.h
+++ b/third_party/WebKit/Source/core/frame/ContentSettingsClient.h
@@ -51,6 +51,9 @@ class CORE_EXPORT ContentSettingsClient {
// Controls whether scripts loaded from the given URL are allowed to execute.
bool AllowScriptFromSource(bool enabled_per_settings, const KURL&);

+ // Controls whether fingerprinting is allowed for this frame.
+ bool AllowFingerprinting(bool enabled_per_settings);
+
// Retrieves the client hints that should be attached to the request for the
// given URL.
void GetAllowedClientHintsFromSource(const KURL&, WebEnabledClientHints*);
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
diff --git a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
index 8f5c621ca932513988e143ad5b0863f5b2af381f..24449d804c4da8e8a7a0e0a90a4f3c05935a6256 100644
--- a/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
+++ b/third_party/WebKit/Source/core/html/canvas/HTMLCanvasElement.cpp
@@ -35,6 +35,7 @@
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptController.h"
+#include "brave/renderer/brave_content_settings_observer_helper.h"
#include "build/build_config.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/StyleEngine.h"
@@ -820,6 +821,9 @@ String HTMLCanvasElement::ToDataURLInternal(
String HTMLCanvasElement::toDataURL(const String& mime_type,
const ScriptValue& quality_argument,
ExceptionState& exception_state) const {
+ if (!AllowFingerprinting(GetDocument().GetFrame()))
+ return String();
+
if (!OriginClean()) {
exception_state.ThrowSecurityError("Tainted canvases may not be exported.");
return String();
@@ -839,6 +843,9 @@ void HTMLCanvasElement::toBlob(V8BlobCallback* callback,
const String& mime_type,
const ScriptValue& quality_argument,
ExceptionState& exception_state) {
+ if (!AllowFingerprinting(GetDocument().GetFrame()))
+ return;
+
if (!OriginClean()) {
exception_state.ThrowSecurityError("Tainted canvases may not be exported.");
return;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
diff --git a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
index 0cd5644ddaf02669ed5bb452ee89d558ea6a6399..c0b86e4cbf9a7283ef3ff0b87ab9bd438f23dbc3 100644
--- a/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGPathElement.cpp
@@ -20,6 +20,7 @@

#include "core/svg/SVGPathElement.h"

+#include "brave/renderer/brave_content_settings_observer_helper.h"
#include "core/css/StyleChangeReason.h"
#include "core/layout/svg/LayoutSVGPath.h"
#include "core/svg/SVGMPathElement.h"
@@ -65,6 +66,9 @@ Path SVGPathElement::AsPath() const {
}

float SVGPathElement::getTotalLength() {
+ if (!AllowFingerprinting(GetDocument().GetFrame())) {
+ return 0.0f;
+ }
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
return SVGPathQuery(PathByteStream()).GetTotalLength();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
diff --git a/third_party/WebKit/Source/core/svg/SVGTextContentElement.cpp b/third_party/WebKit/Source/core/svg/SVGTextContentElement.cpp
index d8b1e5b163a7d1663ef692a2e5a3393711784b0d..d5762fb3b08e8acb51196bcae94849ec3d73874d 100644
--- a/third_party/WebKit/Source/core/svg/SVGTextContentElement.cpp
+++ b/third_party/WebKit/Source/core/svg/SVGTextContentElement.cpp
@@ -22,6 +22,7 @@

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
+#include "brave/renderer/brave_content_settings_observer_helper.h"
#include "core/CSSPropertyNames.h"
#include "core/CSSValueKeywords.h"
#include "core/editing/FrameSelection.h"
@@ -103,6 +104,9 @@ unsigned SVGTextContentElement::getNumberOfChars() {
}

float SVGTextContentElement::getComputedTextLength() {
+ if (!AllowFingerprinting(GetDocument().GetFrame())) {
+ return 0.0f;
+ }
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
return SVGTextQuery(GetLayoutObject()).TextLength();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
index d40e8da53aa03c00ef27fb22141105db0b9bad6b..43dfa8385661dc93c4e071a65430e8c43fe6bccc 100644
--- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
+++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
@@ -6,9 +6,11 @@

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
+#include "brave/renderer/brave_content_settings_observer_helper.h"
#include "core/css/cssom/CSSURLImageValue.h"
#include "core/css/parser/CSSParser.h"
#include "core/dom/ExecutionContext.h"
+#include "core/frame/LocalDOMWindow.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/canvas/HTMLCanvasElement.h"
#include "core/html/canvas/ImageData.h"
@@ -349,7 +351,12 @@ void BaseRenderingContext2D::setShadowColor(const String& color_string) {
ModifiableState().SetShadowColor(color.Rgb());
}

-const Vector<double>& BaseRenderingContext2D::getLineDash() const {
+const Vector<double>& BaseRenderingContext2D::getLineDash(ScriptState* script_state) const {
Copy link
Member Author

Choose a reason for hiding this comment

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

Per slack discussion with @bridiver, move canvas blocking into BaseRenderingContext2D to cover OffscreenCanvasRenderingContext2D & PaintRenderingContext2D.

+ static const Vector<double> emptyVector;
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) {
+ return emptyVector;
+ }
return GetState().LineDash();
}

@@ -744,16 +751,26 @@ void BaseRenderingContext2D::clip(Path2D* dom_path,
ClipInternal(dom_path->GetPath(), winding_rule_string);
}

-bool BaseRenderingContext2D::isPointInPath(const double x,
+bool BaseRenderingContext2D::isPointInPath(ScriptState* script_state,
+ const double x,
const double y,
const String& winding_rule_string) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) {
+ return false;
+ }
return IsPointInPathInternal(path_, x, y, winding_rule_string);
}

-bool BaseRenderingContext2D::isPointInPath(Path2D* dom_path,
+bool BaseRenderingContext2D::isPointInPath(ScriptState* script_state,
+ Path2D* dom_path,
const double x,
const double y,
const String& winding_rule_string) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) {
+ return false;
+ }
return IsPointInPathInternal(dom_path->GetPath(), x, y, winding_rule_string);
}

@@ -778,13 +795,22 @@ bool BaseRenderingContext2D::IsPointInPathInternal(
SkFillTypeToWindRule(ParseWinding(winding_rule_string)));
}

-bool BaseRenderingContext2D::isPointInStroke(const double x, const double y) {
+bool BaseRenderingContext2D::isPointInStroke(ScriptState* script_state, const double x, const double y) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) {
+ return false;
+ }
return IsPointInStrokeInternal(path_, x, y);
}

-bool BaseRenderingContext2D::isPointInStroke(Path2D* dom_path,
+bool BaseRenderingContext2D::isPointInStroke(ScriptState* script_state,
+ Path2D* dom_path,
const double x,
const double y) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) {
+ return false;
+ }
return IsPointInStrokeInternal(dom_path->GetPath(), x, y);
}

@@ -1520,11 +1546,14 @@ ImageData* BaseRenderingContext2D::createImageData(
}

ImageData* BaseRenderingContext2D::getImageData(
+ ScriptState* script_state,
int sx,
int sy,
int sw,
int sh,
ExceptionState& exception_state) {
+ LocalDOMWindow* window = LocalDOMWindow::From(script_state);
+ if (window && !AllowFingerprinting(window->GetFrame())) return nullptr;
if (!WTF::CheckMul(sw, sh).IsValid<int>()) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
Loading