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

Prevent tracking via alternative services (`Alt-Svc` header) #4903

Open
pes10k opened this issue Jun 13, 2019 · 5 comments
Open

Prevent tracking via alternative services (`Alt-Svc` header) #4903

pes10k opened this issue Jun 13, 2019 · 5 comments

Comments

@pes10k
Copy link
Contributor

@pes10k pes10k commented Jun 13, 2019

alt-svc by default have a 24 hour lifetime, which can be modified with the ma option.

This can be used for tracking, in a similar way to HSTS cookies.

My initial best guess is that the safest option is to never cache alt-svc values

@tomlowenthal
Copy link
Member

@tomlowenthal tomlowenthal commented Jul 9, 2019

Right now @fmarier is going to set the alt-scv TTL to zero. Our goal is to have this merged and uplift as far as we can before the channel merge around the end of the month.

@fmarier
Copy link
Member

@fmarier fmarier commented Jul 9, 2019

Also related to QUIC is #3855.

fmarier added a commit to fmarier/brave-core that referenced this issue Jul 27, 2019
…#4903)

Since cross-origin alternative services can be used to generate a
super cookie for users (much like HSTS super cookies), we restrict
their expiry to 10 seconds. This ensures that they can be used in
the immediate request and any sub-resources but that they do not
persist beyond this navigation.
@fmarier
Copy link
Member

@fmarier fmarier commented Aug 15, 2019

Here's how alternative services are implemented in Chrome.

When an Alt-Svc header or an equivalent H2 frame is seen, a new AlternativeServiceInfo object is created and eventually added via SetAlternativeServices() to an AlternativeServiceMap in HTTPServerProperties, a class used to hold information about the capabilities of HTTP servers.

Then we lookup alternative services in that data structure to verify whether the request supports priorities (also here) and to create HTTP "jobs".

Therefore, a good place to restrict this feature is at the point where we create and add the AlternativeServiceInfo object to the map:

diff --git a/chromium_src/net/http/http_server_properties_impl.cc b/chromium_src/net/http/http_server_properties_impl.cc
new file mode 100644
index 000000000..70f523ed9
--- /dev/null
+++ b/chromium_src/net/http/http_server_properties_impl.cc
@@ -0,0 +1,31 @@
+/* Copyright (c) 2019 The Brave Authors. All rights reserved.
+ * 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 https://mozilla.org/MPL/2.0/. */
+
+#include "net/http/http_server_properties_impl.h"
+
+namespace {
+
+// Override the expiry of cross-origin alternative services.
+base::Time BraveAlternativeServiceExpiration(
+    const url::SchemeHostPort& origin,
+    const net::AlternativeService& alternative_service,
+    base::Time now, base::Time expiration) {
+
+  if (origin.host() != alternative_service.host ||
+      origin.port() != alternative_service.port) {
+    expiration = std::max(expiration, now);  // Ignore dates in the past.
+    expiration = std::min(expiration, now + base::TimeDelta::FromSeconds(10));
+  }
+  return expiration;
+}
+
+}  // namespace
+
+#define BRAVE_RESTRICT_ALTERNATIVE_SERVICES_EXPIRATION \
+  expiration = BraveAlternativeServiceExpiration(origin, alternative_service,\
+                                                 clock_->Now(), expiration);
+
+#include "../../../../net/http/http_server_properties_impl.cc"
+#undef BRAVE_RESTRICT_ALTERNATIVE_SERVICES_EXPIRATION
diff --git a/patches/net-http-http_server_properties_impl.cc.patch b/patches/net-http-http_server_properties_impl.cc.patch
new file mode 100644
index 000000000..6d6ae1bd6
--- /dev/null
+++ b/patches/net-http-http_server_properties_impl.cc.patch
@@ -0,0 +1,20 @@
+diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc
+index f18530db1060bfbd09c273f695714305ea9aa90e..a24ed108a8bbd734129d155d290b6aabfcaa14b0 100644
+--- a/net/http/http_server_properties_impl.cc
++++ b/net/http/http_server_properties_impl.cc
+@@ -374,6 +374,7 @@ bool HttpServerPropertiesImpl::SetHttp2AlternativeService(
+     base::Time expiration) {
+   DCHECK_EQ(alternative_service.protocol, kProtoHTTP2);
+ 
++  BRAVE_RESTRICT_ALTERNATIVE_SERVICES_EXPIRATION
+   return SetAlternativeServices(
+       origin,
+       AlternativeServiceInfoVector(
+@@ -388,6 +389,7 @@ bool HttpServerPropertiesImpl::SetQuicAlternativeService(
+     const quic::ParsedQuicVersionVector& advertised_versions) {
+   DCHECK(alternative_service.protocol == kProtoQUIC);
+ 
++  BRAVE_RESTRICT_ALTERNATIVE_SERVICES_EXPIRATION
+   return SetAlternativeServices(
+       origin, AlternativeServiceInfoVector(
+                   /*size=*/1,
@fmarier
Copy link
Member

@fmarier fmarier commented Aug 15, 2019

Alternative services are used for the following purposes:

  1. load-balancing on the client-side without using DNS (e.g. https://example.com sends Alt-Svc: h2="other.example.com:443")
  2. upgrading an HTTP/1.1 connection to H2 (e.g. https://example.com sends Alt-Svc: h2=":443")
  3. upgrading an HTTP connection over Tor to an .onion address (e.g. https://example.com sends Alt-Svc: h2="hipejsaf3b...o2exyd.onion:443")
  4. opportunistically upgrading an HTTP connection to "encrypted HTTP" (e.g. http://example.com sends Alt-Svc: h2=":443")
  5. upgrading an HTTP/1.1 or H2 connection to QUIC (e.g. https://example.com sends Alt-Svc: quic=":443"; v="46,43,39"")

I have successfully tested cases 1-3 on Firefox and 4 is also implemented while case 5 is waiting on QUIC support.

Chrome on the other hand only supports upgrading connections to QUIC (case 5 above) on the same host. In other words, it only supports Alt-Svc: quic=":443". There is some support for H2 alternative services, including on different hosts (i.e. cases 1-3) but it's disabled by default and is completely broken in the presence of SNI.

Given that Brave doesn't enable QUIC by default (users have to enabled it via chrome://flags), in practice, Alt-Svc are not used for anything in Brave.

Should the support for H2 alternative services be fixed and enabled in Chrome, we should revisit this bug and perhaps limit the alternative services to same-origin ones only. Right now, I don't believe that this is a viable tracking mechanism in Brave.

@fmarier fmarier changed the title Ignore all alt-svc lifetimes, don't cache values Prevent tracking via alternative services (`Alt-Svc` header) Aug 15, 2019
@fmarier fmarier added blocked and removed feature/shields labels Aug 15, 2019
@fmarier fmarier removed their assignment Aug 15, 2019
@fmarier fmarier moved this from Untriaged Backlog to Important backlog (do these first!) in Security & Privacy Sep 27, 2019
@fmarier fmarier moved this from Important backlog (do these first!) to Untriaged Backlog in Security & Privacy Sep 27, 2019
@fmarier
Copy link
Member

@fmarier fmarier commented Mar 9, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Security & Privacy
  
Untriaged Backlog
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.