From 04c1f65bcb13d0e3baac201d9ddd826a4ddb4013 Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Mon, 19 Dec 2022 12:55:37 +0200 Subject: [PATCH 1/8] Use "least restrictive" directive instead of `prefetch-src` When prefetching a resource (or preconnecting to an origin), the destination of the request is unknown and also not important. e.g. if this resource is a script and would be disallowed by `script-src`, the directive would be invoked again when the response is about to be consumed and would be rejected then. The only security measure valid for prefetch/preconnect is to avoid exfiltration - i.e. block the request when the default directive blocks this URL and no other directive allows it. Closes #542 --- index.bs | 101 +++++++++++++++---------------------------------------- 1 file changed, 28 insertions(+), 73 deletions(-) diff --git a/index.bs b/index.bs index 5850b784be..b174b66fe1 100644 --- a/index.bs +++ b/index.bs @@ -2156,7 +2156,6 @@ this algorithm returns normally if compilation is allowed, and throws a img-src 'self'; manifest-src 'self'; media-src 'self'; - prefetch-src 'self'; object-src 'self'; script-src-elem 'self'; script-src-attr 'self'; @@ -2186,7 +2185,6 @@ this algorithm returns normally if compilation is allowed, and throws a img-src 'self'; manifest-src 'self'; media-src 'self'; - prefetch-src 'self'; object-src 'self'; script-src-elem https://example.com; script-src-attr 'self'; @@ -2703,74 +2701,6 @@ this algorithm returns normally if compilation is allowed, and throws a 4. Return "`Allowed`". -

`prefetch-src`

- - The prefetch-src directive restricts the URLs from which resources may be - prefetched or prerendered. The syntax for the directive's name and value is described by the - following ABNF: - -
-    directive-name  = "prefetch-src"
-    directive-value = serialized-source-list
-  
- -
- Given a page with the following Content Security Policy: - -
-      Content-Security-Policy: prefetch-src https://example.com/
-    
- - Fetches for the following code will return network errors, as the URLs provided do not match - `prefetch-src`'s source list: - -
-      <link rel="prefetch" src="https://example.org/"></link>
-      <link rel="prerender" src="https://example.org/"></link>
-    
-
- -
- `prefetch-src` Pre-request check -
- - This directive's pre-request check is as follows: - - Given a request (|request|) and a policy (|policy|): - - 1. Let |name| be the result of executing [[#effective-directive-for-a-request]] - on |request|. - - 2. If the result of executing [[#should-directive-execute]] on |name|, - `prefetch-src` and |policy| is "`No`", return "`Allowed`". - - 3. If the result of executing [[#match-request-to-source-list]] on |request|, - this directive's [=directive/value=], and |policy|, - is "`Does Not Match`", return "`Blocked`". - - 4. Return "`Allowed`". - -
- `prefetch-src` Post-request check -
- - This directive's post-request check is as follows: - - Given a request (|request|), a response (|response|), and a - policy (|policy|): - - 1. Let |name| be the result of executing [[#effective-directive-for-a-request]] - on |request|. - - 2. If the result of executing [[#should-directive-execute]] on |name|, - `prefetch-src` and |policy| is "`No`", return "`Allowed`". - - 3. If the result of executing [[#match-response-to-source-list]] on |response|, - |request|, this directive's [=directive/value=], and |policy|, - is "`Does Not Match`", return "`Blocked`". - - 4. Return "`Allowed`". -

`script-src`

The script-src directive restricts the locations from which scripts @@ -3794,16 +3724,41 @@ this algorithm returns normally if compilation is allowed, and throws a algorithm returns the violated directive if the request violates the policy, and "`Does Not Violate`" otherwise. - 1. Let |violates| be "`Does Not Violate`". + 1. If |request|'s [=request/initiator=] is "`prefetch`", then return the result of executing + [[#does-resource-hint-violate-policy]] on |request| and |policy|. - 2. For each |directive| of |policy|: + 2. Let |violates| be "`Does Not Violate`". + + 3. For each |directive| of |policy|: 1. Let |result| be the result of executing |directive|'s pre-request check on |request| and |policy|. 2. If |result| is "`Blocked`", then let |violates| be |directive|. - 3. Return |violates|. + 4. Return |violates|. + +
+ Does resource hint |request| violate |policy|? +
+ + Given a request (|request|) and a policy (|policy|), this + algorithm returns the default directive if the resource-hint request violates all the + policies, and "`Does Not Violate`" otherwise. + + 1. Let |defaultDirective| be |policy|'s first [=directive=] whose [=directive/name=] is + "`default-src`". + + 2. If |defaultDirective| does not exist, return "`Does Not Violate`". + + 3. For each |directive| of |policy|: + + 1. Let |result| be the result of executing |directive|'s + pre-request check on |request| and |policy|. + + 2. If |result| is "`Allowed`", then return "`Does Not Violate`". + + 4. Return "`Blocked`".
Does |nonce| match |source list|? From 8325f78919f91b5309a74c294c045ec8209d6d05 Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Mon, 19 Dec 2022 15:51:47 +0200 Subject: [PATCH 2/8] Add some prose --- index.bs | 52 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index b174b66fe1..29b06a23b7 100644 --- a/index.bs +++ b/index.bs @@ -2140,6 +2140,14 @@ this algorithm returns normally if compilation is allowed, and throws a out in more detail in the [[#should-block-request]] and [[#should-block-response]] algorithms. +
+ In the case of resource hint such as [^link/rel/prefetch^] and [^link/rel/dns-prefetch^], + default-src can be used as a way to restrict fetching the resource, as a means to prevent + exfiltration. Resource hints don't have their own [=directive=] and they rely on + default-src and follow the least-restrictive [=directive=]. +
+ +
The following header: @@ -4288,11 +4296,11 @@ this algorithm returns normally if compilation is allowed, and throws a `null` or the name of the request's effective directive: - 1. If |request|'s initiator is "`fetch`" or its - destination is "", return `connect-src`. + 1. If |request|'s [=request/initiator=] is "`prefetch`" or "`prerender`", + return `default-src`. - 2. If |request|'s [=request/initiator=] is "`prefetch`" or "`prerender`", - return `prefetch-src`. + 2. If |request|'s initiator is "`fetch`" or its + destination is "", return `connect-src`. 3. Switch on |request|'s destination, and execute the associated steps: @@ -4415,10 +4423,6 @@ this algorithm returns normally if compilation is allowed, and throws a :: 1. Return `<< "manifest-src", "default-src" >>`. - : "`prefetch-src`" - :: - 1. Return `<< "prefetch-src", "default-src" >>`. - : "`object-src`" :: 1. Return `<< "object-src", "default-src" >>`. @@ -4970,8 +4974,40 @@ this algorithm returns normally if compilation is allowed, and throws a
+
+

+ Exfiltration +

+ + Data exfiltration can occur when the contents of the request, such as the URL, contain + information about the user or page that should be restricted and not shared. + + To prevent exfiltration with CSP, it is important to set the default-src directive, to + avoid a situation where a specific directive is omitted, and to ensure that other directives + don't relax that restriction in a way that can allow exfiltration. + +
+ In the following example, a page that has only images, fonts and scripts, can still + exfiltrate, e.g. by a [^link/rel/prefetch^]. Add
default-src 'none'
to avoid it. + +
+        Content-Security-Policy: img-src 'none' script-src 'none' font-src 'none'
+      
+
+ +
+ In the following example, the default-src directive appears to protect from + exfiltration, however the img-src directive relaxes it, which allows data to exfiltrate + either via an image or via resource hint. + +
+        Content-Security-Policy: default-src 'none' img-src *;
+      
+
+ +

Implementation Considerations

From b4e05e62fc5ef363060adf28cae5750c32d77199 Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Thu, 22 Dec 2022 10:17:55 +0200 Subject: [PATCH 3/8] Update index.bs Co-authored-by: Mike West --- index.bs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.bs b/index.bs index 29b06a23b7..dc4df1e467 100644 --- a/index.bs +++ b/index.bs @@ -2141,10 +2141,10 @@ this algorithm returns normally if compilation is allowed, and throws a [[#should-block-response]] algorithms.
- In the case of resource hint such as [^link/rel/prefetch^] and [^link/rel/dns-prefetch^], - default-src can be used as a way to restrict fetching the resource, as a means to prevent - exfiltration. Resource hints don't have their own [=directive=] and they rely on - default-src and follow the least-restrictive [=directive=]. + Resource hints such as [^link/rel/prefetch^] and [^link/rel/dns-prefetch^] generate requests that + aren't tied to any specific [=fetch directive=], but are instead governed by the union of servers + allowed in all of a policy's directives' [=source lists=]. If default-src is not specified, these + requests will always be allowed. For more information, see [[#exfiltration]].
From e67c50b83f336669a57a82c6cc537d58d06c49bc Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Thu, 22 Dec 2022 10:18:03 +0200 Subject: [PATCH 4/8] Update index.bs Co-authored-by: Mike West --- index.bs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.bs b/index.bs index dc4df1e467..d44baf8b5f 100644 --- a/index.bs +++ b/index.bs @@ -4982,9 +4982,10 @@ this algorithm returns normally if compilation is allowed, and throws a Data exfiltration can occur when the contents of the request, such as the URL, contain information about the user or page that should be restricted and not shared. - To prevent exfiltration with CSP, it is important to set the default-src directive, to - avoid a situation where a specific directive is omitted, and to ensure that other directives - don't relax that restriction in a way that can allow exfiltration. + Content Security Policy can mitigate data exfiltration if used to create allowlists of servers + with which a page is allowed to communicate. Note that a policy which lacks the default-src + directive cannot mitigate exfiltration, as there are kinds of requests that are not addressable + through a more-specific directive ([^link/rel/prefetch^], for example).
In the following example, a page that has only images, fonts and scripts, can still From 4ca12173b88b7dfe6e72833cfe8d5054da15efa6 Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Thu, 22 Dec 2022 10:18:09 +0200 Subject: [PATCH 5/8] Update index.bs Co-authored-by: Mike West --- index.bs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index d44baf8b5f..ff790f6ea5 100644 --- a/index.bs +++ b/index.bs @@ -4988,8 +4988,8 @@ this algorithm returns normally if compilation is allowed, and throws a through a more-specific directive ([^link/rel/prefetch^], for example).
- In the following example, a page that has only images, fonts and scripts, can still - exfiltrate, e.g. by a [^link/rel/prefetch^]. Add
default-src 'none'
to avoid it. + In the following example, a policy with draconian restrictions on images, fonts, and scripts + can still allow data exfiltration via other request types (`fetch()`, [^link/rel/prefetch^], etc):
         Content-Security-Policy: img-src 'none' script-src 'none' font-src 'none'

From c93a49859fb993e89421440bcb575843d1cc6964 Mon Sep 17 00:00:00 2001
From: Noam Rosenthal 
Date: Thu, 22 Dec 2022 10:18:15 +0200
Subject: [PATCH 6/8] Update index.bs

Co-authored-by: Mike West 
---
 index.bs | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/index.bs b/index.bs
index ff790f6ea5..5afbd7d293 100644
--- a/index.bs
+++ b/index.bs
@@ -4994,6 +4994,9 @@ this algorithm returns normally if compilation is allowed, and throws a
       
         Content-Security-Policy: img-src 'none' script-src 'none' font-src 'none'
       
+ + Supplementing this policy with `default-src 'none'` would improve the page's robustness + against this kind of attack.
From 707f99131f325532c816f5e00163e7b46e2355c0 Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Thu, 22 Dec 2022 10:18:20 +0200 Subject: [PATCH 7/8] Update index.bs Co-authored-by: Mike West --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 5afbd7d293..0dee083bb3 100644 --- a/index.bs +++ b/index.bs @@ -5005,7 +5005,7 @@ this algorithm returns normally if compilation is allowed, and throws a either via an image or via resource hint.
-        Content-Security-Policy: default-src 'none' img-src *;
+        Content-Security-Policy: default-src 'none'; img-src *
       
From f9f3047b5dacc1ec13d63bbb224dd5f0425dcc2c Mon Sep 17 00:00:00 2001 From: Noam Rosenthal Date: Thu, 22 Dec 2022 10:18:26 +0200 Subject: [PATCH 8/8] Update index.bs Co-authored-by: Mike West --- index.bs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.bs b/index.bs index 0dee083bb3..862e6cab8b 100644 --- a/index.bs +++ b/index.bs @@ -5001,8 +5001,9 @@ this algorithm returns normally if compilation is allowed, and throws a
In the following example, the default-src directive appears to protect from - exfiltration, however the img-src directive relaxes it, which allows data to exfiltrate - either via an image or via resource hint. + exfiltration, however the img-src directive relaxes this restriction by using a + wildcard, which allows data exfiltration to arbitrary endpoints. A policy's exfiltration + mitigation ability depends upon the least-restrictive directive allowlist:
         Content-Security-Policy: default-src 'none'; img-src *