Closed Bug 515460 Opened 15 years ago Closed 14 years ago

(CSP) Enforce policies during redirects

Categories

(Core :: DOM: Core & HTML, enhancement, P1)

enhancement

Tracking

()

RESOLVED FIXED

People

(Reporter: geekboy, Assigned: bsterne)

References

(Blocks 1 open bug, )

Details

Attachments

(12 files, 5 obsolete files)

23.08 KB, patch
joe
: review+
Details | Diff | Splinter Review
2.01 KB, patch
jst
: review+
Details | Diff | Splinter Review
2.18 KB, patch
jst
: review+
Details | Diff | Splinter Review
1.73 KB, patch
jst
: review+
Details | Diff | Splinter Review
2.76 KB, patch
jst
: review+
Details | Diff | Splinter Review
2.02 KB, patch
jst
: review+
Details | Diff | Splinter Review
2.21 KB, patch
jst
: review+
Details | Diff | Splinter Review
1.95 KB, patch
jtd
: review+
Details | Diff | Splinter Review
1.94 KB, patch
jst
: review+
Details | Diff | Splinter Review
2.20 KB, patch
jst
: review+
Details | Diff | Splinter Review
13.64 KB, patch
Details | Diff | Splinter Review
621 bytes, patch
geekboy
: review+
Details | Diff | Splinter Review
Any URI requested into a document with a CSP should be subject to the CSP at all stages of redirection.

For example, consider a site A with CSP P[A] contains a reference to an image at URI B.  When B is resolved, it is redirected via HTTP redirects to C and then D.
  B->C->D
All B, C and D should be subject to P[A]'s img-src directive before the requests for those URIs go out.  If any B, C or D are disallowed, that specific request (B, C or D) is aborted, breaking the redirect chain, and failing to load the resource at the end of the chain.

This redirect checking should be done for all types of resources protected by CSP.
Depends on: 515797
Attached patch image-redir-v1 (obsolete) — Splinter Review
Attached patch script-redir-v1 (obsolete) — Splinter Review
Lets channel redirects for script call into content policy
Attachment #405118 - Attachment description: Lets image redirects call into content policy → image-redir-v1
Attached patch media-redir-v1 (obsolete) — Splinter Review
Channel redirects for video/audio to call into content policy.
Attached patch object-redir-v1 (obsolete) — Splinter Review
Channel redirects for objects (plugin content) to call into content policy.
Attached patch frame-redir-v1 (obsolete) — Splinter Review
puts policy info into channels created to load iframes.
Depends on: 523239
Attachment #405118 - Attachment is obsolete: true
Attachment #405119 - Attachment is obsolete: true
Attachment #405176 - Attachment is obsolete: true
Attachment #406086 - Attachment is obsolete: true
Correct subframe-redirect-handling patch for CSP.
Attachment #406322 - Attachment is obsolete: true
I've cleaned up all the redirect handling patches I have to use the non-renamed necko API (bug 515797).  I'm using the following tests to verify these changes:
http://hackmill.com/csp/tests/test-harness.html

The last thing I need to do for this bug is to check all callers of NS_CheckContentLoadPolicy to see if there are content load types that CSP should be restricting but isn't.
(In reply to comment #11)
> see if there are content load types that CSP should be restricting but isn't.

Right, like CSSLoaderImpl::CheckLoadAllowed.  Well, there's at least one more piece needed to fix this bug...
There's a NS_CheckContentLoadPolicy check in nsExpatDriver::OpenInputStreamFromExternalDTD before we do a NS_OpenURI, which is basically a wrapper for NS_NewChannel.

Do we think it's necessary for CSP to work with XML documents and specifically requests generated by external DTD files?  If so, I'll need to add code to NS_OpenURI to take a nsIChannelPolicy to pass down to NS_NewChannel.
Attached patch csp-xhr-redir-v1Splinter Review
I think I've patched all the necessary places now.  I went through all the callers of NS_CheckContentLoadPolicy and made sure the redirects-to-check-with-ContentPolicy pattern is in place where appropriate.

The only call sites where I didn't add the code were in XML and XSLT documents which I don't believe we intend to work with CSP, though the pattern could easily be added there if we change our mind.

The callers of NS_CheckContentLoadPolicythat didn't get the patch are:
nsExpatDriver::OpenInputStreamFromExternalDTD
CheckPingURI (nsDocShell)
nsDocShell::InternalLoad (Content Policy checks done downstream)
txCompileObserver::loadURI
TX_LoadSheet
txSyncCompileObserver::loadURI
nsXMLContentSink::ProcessStyleLink
Attachment #421165 - Flags: review?(jst)
Attachment #421166 - Flags: review?(jst)
Attachment #421167 - Flags: review?(jst)
Attachment #421168 - Flags: review?(jst)
Attachment #421363 - Flags: review?(jst)
Attachment #421543 - Flags: review?(jst)
Attachment #422414 - Flags: review?(jst)
Attachment #422566 - Flags: review?(jst)
Attachment #422568 - Flags: review?(jst)
Comment on attachment 421165 [details] [diff] [review]
csp-script-redir-v2

+  rv = mDocument->NodePrincipal()->GetCsp(getter_AddRefs(csp));
+  NS_ENSURE_SUCCESS(rv, rv);

Seems like all our GetCsp() implementations unconditionally return NS_OK, maybe remove this NS_ENSURE_SUCcESS() here? If there's reason to keep it, I'm fine with doing so as well, but it seems like an unnecessary check to me.

Same applies to most (all?) other patches in this bug.
Attachment #421165 - Flags: review?(jst) → review+
Comment on attachment 421166 [details] [diff] [review]
csp-media-redir-v2

   nsCOMPtr<nsHTMLMediaElement> mElement;
   PRUint32 mLoadID;
 };
 
+#include "IContentSecurityPolicy.h"
+#include "nsIChannelPolicy.h"
+#include "nsChannelPolicy.h"

Move these to the top of the file where all other #includes are.
Attachment #421166 - Flags: review?(jst) → review+
Attachment #421167 - Flags: review?(jst) → review+
Comment on attachment 421168 [details] [diff] [review]
csp-frame-redir-v2

- In nsDocShell::DoURILoad():

+    // check for Content Security Policy to pass along with the
+    // new channel we are creating
+    nsCOMPtr<nsIChannelPolicy> channelPolicy = 
+        do_CreateInstance("@mozilla.org/nschannelpolicy;1");

The other patches here seem to only create the channel policy object if there's a csp in the principal, so the do_CreateInstance() should move down inside the if (csp) check below.

+    if (IsFrame()) {
+        // check the parent docshell for a CSP
+        nsCOMPtr<IContentSecurityPolicy> csp;
+        nsCOMPtr<nsIDocShellTreeItem> parentItem;
+        GetSameTypeParent(getter_AddRefs(parentItem));
+        if (parentItem) {
+            nsCOMPtr<nsIDOMDocument> domDoc(do_GetInterface(parentItem));

do_GetInterface() is null safe, so remove the if (parentItem) check.

+            if (domDoc) {
+                nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);

... as is do_QueryInterface(), so remove the if (domDoc) check.
Attachment #421168 - Flags: review?(jst) → review+
Attachment #421363 - Flags: review?(jst) → review+
Attachment #421543 - Flags: review?(jst) → review+
Comment on attachment 422414 [details] [diff] [review]
csp-font-face-redir-v1

- In nsUserFontSet::StartLoad():

+  principal->GetCsp(getter_AddRefs(csp));

The code above here that gets the principal asserts that it's not null, but if it is, it allows the load, and this change would make us crash (in a safe way! :). This code looks like it's all jdaggett's, so requesting review from him to decided one way or another here, but personally I think we should just make this code refuse to load a font if there's no principal.
Attachment #422414 - Flags: review?(jst) → review?(jdaggett)
Comment on attachment 422566 [details] [diff] [review]
csp-external-resource-map-redir-v1

+  doc->NodePrincipal()->GetCsp(getter_AddRefs(csp));

No check for whether this succeeds or not here, either take my advice to never check (from an earlier patch), or add the same check here.
Attachment #422566 - Flags: review?(jst) → review+
Attachment #422568 - Flags: review?(jst) → review+
(In reply to comment #16)
> Created an attachment (id=422414) [details]
> csp-font-face-redir-v1

+  principal->GetCsp(getter_AddRefs(csp));
+  NS_ENSURE_SUCCESS(rv, rv);

Hmmm, don't you need to assign the return value of GetCsp to rv?
(In reply to comment #25)
> Hmmm, don't you need to assign the return value of GetCsp to rv?

I certainly do.  Fixed.
Comment on attachment 422414 [details] [diff] [review]
csp-font-face-redir-v1

Assuming rv is correctly returned, looks good.  Looks like csp-external-resource-map-redir-v1 and csp-xhr-redir-v1 have the same issue.
Attachment #422414 - Flags: review?(jdaggett) → review+
Comment on attachment 421164 [details] [diff] [review]
csp-image-redir-v2

Stuart, you're probably the best person to review this patch.  I'm happy to provide you with background/context if needed.
Attachment #421164 - Flags: review?(pavlov)
Comment on attachment 421164 [details] [diff] [review]
csp-image-redir-v2

joe has looked at this stuff more than I have
Attachment #421164 - Flags: review?(pavlov) → review?(joe)
Looks like you're missing a result value check:

 1.1 --- a/content/base/src/nsXMLHttpRequest.cpp
 1.2 +++ b/content/base/src/nsXMLHttpRequest.cpp
1.13 @@ -1751,8 +1754,22 @@ nsXMLHttpRequest::OpenRequest(const nsAC
1.14} else {
1.15  loadFlags = nsIRequest::LOAD_BACKGROUND;
1.16}
1.17 -  rv = NS_NewChannel(getter_AddRefs(mChannel), uri, nsnull, loadGroup, nsnull,
1.18 - loadFlags);
1.19 +  // get Content Security Policy from principal to pass into channel
1.20 +  nsCOMPtr<nsIChannelPolicy> channelPolicy;
1.21 +  nsCOMPtr<nsIContentSecurityPolicy> csp;
1.22 +  mPrincipal->GetCsp(getter_AddRefs(csp));
1.23 +  if (csp) {
1.24 +channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
1.25 +channelPolicy->SetContentSecurityPolicy(csp);
1.26 +channelPolicy->SetLoadType(nsIContentPolicy::TYPE_XMLHTTPREQUEST);
1.27 +  }

I think you want:

rv = mPrincipal->GetCsp(getter_AddRefs(csp));
Attached patch Fixes comment 32Splinter Review
Missed a return value check.
Attachment #441509 - Flags: review?(sstamm)
Attachment #441509 - Flags: review?(sstamm) → review+
Joe, any update on the review?  We really need to get this last piece landed?  Thanks.
Don't know how I missed that comment yesterday! I plan on getting to this review early next week.
Comment on attachment 421164 [details] [diff] [review]
csp-image-redir-v2

>diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp

>@@ -2452,16 +2455,30 @@ nsContentUtils::LoadImage(nsIURI* aURI, 

>   // We don't use aLoadingPrincipal for anything here yet... but we
>   // will.  See bug 377092.

This comment can probably go now :)

>diff --git a/modules/libpr0n/public/imgILoader.idl b/modules/libpr0n/public/imgILoader.idl

Need to rev imgILoader uuid.

>diff --git a/modules/libpr0n/src/imgLoader.cpp b/modules/libpr0n/src/imgLoader.cpp

> static nsresult NewImageChannel(nsIChannel **aResult,
>                                 nsIURI *aURI,
>                                 nsIURI *aInitialDocumentURI,
>                                 nsIURI *aReferringURI,
>                                 nsILoadGroup *aLoadGroup,
>                                 const nsCString& aAcceptHeader,
>-                                nsLoadFlags aLoadFlags)
>+                                nsLoadFlags aLoadFlags,
>+                                nsIChannelPolicy *channelPolicy)

As much as I dislike it, aPolicy is the standard naming for function parameter names. You'll need to sweep through this file to make sure you get it on all the functions you've added an nsIChannelPolicy parameter to in this file.

>diff --git a/toolkit/system/gnome/nsAlertsIconListener.cpp b/toolkit/system/gnome/nsAlertsIconListener.cpp

>@@ -262,19 +262,21 @@ nsAlertsIconListener::StartRequest(const

>+  // XXXbsterne currently passing in null for channel policy
>+  // I don't have a testcase that triggers this code
>   return il->LoadImage(imageUri, nsnull, nsnull, nsnull, this,
>                        nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
>-                       getter_AddRefs(mIconRequest));
>+                       nsnull, getter_AddRefs(mIconRequest));

Did you end up writing such a testcase?

>diff --git a/widget/src/cocoa/nsMenuItemIconX.mm b/widget/src/cocoa/nsMenuItemIconX.mm

>@@ -336,19 +355,23 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconU

>+  // XXXbsterne I'm not sure passing in channelPolicy is actually necessary
>+  // here.  I can trigger this code, for example, by clicking on menu items
>+  // but nsMenuItemIconX::LoadIcon always seems to be called with either
>+  // chrome:// or moz-anno:favicon URIs.
>   rv = loader->LoadImage(aIconURI, nsnull, nsnull, loadGroup, this,
>-                         nsnull, nsIRequest::LOAD_NORMAL, nsnull,
>-                         nsnull, getter_AddRefs(mIconRequest));
>+                         nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull,
>+                         channelPolicy, getter_AddRefs(mIconRequest));

You should probably decide one way or the other, and either remove the comment and pass the channelPolicy, or modify the comment slightly (remove the XXXbsterne for one) and pass nsnull.
Attachment #421164 - Flags: review?(joe) → review+
http://hg.mozilla.org/mozilla-central/rev/30443a0a2394
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: