Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Issue 2190183002: Forward CSP violation reporting from RenderFrameProxy to RenderFrameImpl.

Created:
4 years, 4 months ago by Łukasz Anforowicz
Modified:
4 years, 4 months ago
CC:
chromium-reviews, mlamouri+watch-content_chromium.org, sof, creis+watch_chromium.org, eae+blinkwatch, nasko+codewatch_chromium.org, jam, blink-reviews-dom_chromium.org, dglazkov+blink, darin-cc_chromium.org, blink-reviews, kinuko+watch, blink-reviews-api_chromium.org, rwlbuis, site-isolation-reviews_chromium.org, estark
Base URL:
https://chromium.googlesource.com/chromium/src.git@master
Target Ref:
refs/pending/heads/master
Project:
chromium
Visibility:
Public.

Description

Forward CSP violation reporting from RenderFrameProxy to RenderFrameImpl. BUG=611232 CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_site_isolation

Patch Set 1 #

Patch Set 2 : Reintroduce test exception. #

Patch Set 3 : Fixing how virtual method is declared. #

Total comments: 1

Patch Set 4 : Avoid cross-site disclosure of line numbers. #

Patch Set 5 : Remove no longer applicable TODO and early exit from reportViolation method. #

Total comments: 34

Patch Set 6 : Addressed CR feedback from alexmos@. #

Patch Set 7 : Rebasing... #

Patch Set 8 : Tweak protection against navigation race. #

Total comments: 5

Patch Set 9 : More safe-guards against navigation-vs-violation race. #

Total comments: 3

Patch Set 10 : Sanitize report endpoints from IPC against actual CSP contents. #

Unified diffs Side-by-side diffs Delta from patch set Stats (+484 lines, -61 lines) Patch
M content/browser/frame_host/frame_tree_node.h View 1 2 3 4 5 6 7 8 1 chunk +5 lines, -0 lines 0 comments Download
M content/browser/frame_host/frame_tree_node.cc View 1 2 3 4 5 6 7 8 2 chunks +12 lines, -0 lines 0 comments Download
M content/browser/frame_host/render_frame_proxy_host.h View 1 2 3 4 5 6 7 8 3 chunks +16 lines, -0 lines 0 comments Download
M content/browser/frame_host/render_frame_proxy_host.cc View 1 2 3 4 5 6 7 8 2 chunks +60 lines, -0 lines 0 comments Download
M content/common/content_param_traits_macros.h View 1 chunk +2 lines, -0 lines 0 comments Download
D content/common/content_security_policy_header.h View 1 chunk +0 lines, -24 lines 0 comments Download
A + content/common/content_security_policy_structs.h View 1 2 3 2 chunks +20 lines, -3 lines 0 comments Download
A + content/common/content_security_policy_structs.cc View 1 chunk +4 lines, -4 lines 0 comments Download
M content/common/frame_messages.h View 1 2 3 4 5 6 7 4 chunks +31 lines, -1 line 0 comments Download
M content/common/frame_replication_state.h View 1 chunk +1 line, -1 line 0 comments Download
M content/content_common.gypi View 1 2 3 4 5 6 1 chunk +2 lines, -1 line 0 comments Download
M content/renderer/render_frame_impl.h View 1 2 3 4 5 6 2 chunks +3 lines, -0 lines 0 comments Download
M content/renderer/render_frame_impl.cc View 1 2 3 4 5 6 3 chunks +20 lines, -1 line 0 comments Download
M content/renderer/render_frame_proxy.h View 1 2 3 1 chunk +9 lines, -0 lines 0 comments Download
M content/renderer/render_frame_proxy.cc View 1 2 3 4 5 6 7 2 chunks +28 lines, -1 line 0 comments Download
M third_party/WebKit/LayoutTests/FlagExpectations/site-per-process View 1 2 3 4 5 6 1 chunk +1 line, -1 line 0 comments Download
M third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/frame-src-child-frame-navigates-to-blocked-origin.html View 1 chunk +8 lines, -0 lines 0 comments Download
M third_party/WebKit/LayoutTests/http/tests/security/contentSecurityPolicy/frame-src-child-frame-navigates-to-blocked-origin-expected.txt View 1 chunk +3 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/core/core.gypi View 1 2 3 4 5 6 1 chunk +1 line, -0 lines 0 comments Download
M third_party/WebKit/Source/core/dom/RemoteSecurityContext.h View 1 2 3 4 5 2 chunks +6 lines, -2 lines 0 comments Download
M third_party/WebKit/Source/core/dom/RemoteSecurityContext.cpp View 2 chunks +12 lines, -6 lines 0 comments Download
M third_party/WebKit/Source/core/frame/RemoteFrame.cpp View 1 2 3 4 5 6 1 chunk +1 line, -1 line 0 comments Download
M third_party/WebKit/Source/core/frame/RemoteFrameClient.h View 1 2 3 2 chunks +6 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.h View 1 2 3 4 5 6 7 8 9 3 chunks +8 lines, -5 lines 0 comments Download
M third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp View 1 2 3 4 5 6 7 8 9 2 chunks +11 lines, -10 lines 0 comments Download
A third_party/WebKit/Source/core/frame/csp/RemoteContentSecurityPolicy.h View 1 2 3 4 5 1 chunk +43 lines, -0 lines 0 comments Download
A third_party/WebKit/Source/core/frame/csp/RemoteContentSecurityPolicy.cpp View 1 2 3 1 chunk +52 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/web/AssertMatchingEnums.cpp View 1 2 3 4 5 6 1 chunk +4 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/web/RemoteFrameClientImpl.h View 1 2 3 1 chunk +1 line, -0 lines 0 comments Download
M third_party/WebKit/Source/web/RemoteFrameClientImpl.cpp View 1 2 3 4 5 6 2 chunks +22 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/web/WebLocalFrameImpl.h View 1 2 3 4 5 6 1 chunk +9 lines, -0 lines 0 comments Download
M third_party/WebKit/Source/web/WebLocalFrameImpl.cpp View 1 2 3 4 5 6 7 8 9 1 chunk +48 lines, -0 lines 0 comments Download
M third_party/WebKit/public/web/WebContentSecurityPolicy.h View 1 chunk +7 lines, -0 lines 0 comments Download
M third_party/WebKit/public/web/WebLocalFrame.h View 1 2 3 4 5 6 2 chunks +15 lines, -0 lines 0 comments Download
M third_party/WebKit/public/web/WebRemoteFrameClient.h View 1 2 3 2 chunks +13 lines, -0 lines 0 comments Download

Messages

Total messages: 26 (13 generated)
Łukasz Anforowicz
Mike, can you take a look please? The browser->renderer path is here for the long-term. ...
4 years, 4 months ago (2016-07-29 23:33:04 UTC) #3
Łukasz Anforowicz
Alex, could you also take a look please?
4 years, 4 months ago (2016-08-05 22:46:06 UTC) #13
alexmos
Thanks, this looks fine to me. A few questions and nits below. Re: how to ...
4 years, 4 months ago (2016-08-09 18:01:20 UTC) #14
Łukasz Anforowicz
Thanks Alex. Can you take another look please? https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc (right): https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc#newcode278 content/browser/frame_host/render_frame_proxy_host.cc:278: if ...
4 years, 4 months ago (2016-08-09 22:23:21 UTC) #16
Łukasz Anforowicz
I think I need to rebase + added some extra bits of knowledge to one ...
4 years, 4 months ago (2016-08-10 19:50:25 UTC) #17
alexmos
Adding Charlie for discussion about the BrowsingInstance check below. Other than that, LGTM. Thanks for ...
4 years, 4 months ago (2016-08-10 20:34:33 UTC) #19
Łukasz Anforowicz
Charlie, I've added some more thoughts on the remaining open issue below. https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc ...
4 years, 4 months ago (2016-08-11 17:32:36 UTC) #20
Łukasz Anforowicz
+estark@ to CC as FYI https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc (right): https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc#newcode278 content/browser/frame_host/render_frame_proxy_host.cc:278: if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance())) On 2016/08/11 ...
4 years, 4 months ago (2016-08-11 18:04:35 UTC) #21
Charlie Reis
https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc (right): https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc#newcode278 content/browser/frame_host/render_frame_proxy_host.cc:278: if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance())) On 2016/08/11 17:32:36, Łukasz Anforowicz wrote: > ...
4 years, 4 months ago (2016-08-11 18:32:15 UTC) #22
Łukasz Anforowicz
Charlie, can you take a look at the latest patchset? (for the question/concern we are ...
4 years, 4 months ago (2016-08-11 19:51:35 UTC) #23
Charlie Reis
https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc (right): https://codereview.chromium.org/2190183002/diff/80001/content/browser/frame_host/render_frame_proxy_host.cc#newcode278 content/browser/frame_host/render_frame_proxy_host.cc:278: if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance())) On 2016/08/11 19:51:35, Łukasz Anforowicz wrote: > ...
4 years, 4 months ago (2016-08-11 20:40:26 UTC) #24
Łukasz Anforowicz
Charlie, can you take another look? https://codereview.chromium.org/2190183002/diff/140001/content/browser/frame_host/render_frame_proxy_host.cc File content/browser/frame_host/render_frame_proxy_host.cc (right): https://codereview.chromium.org/2190183002/diff/140001/content/browser/frame_host/render_frame_proxy_host.cc#newcode278 content/browser/frame_host/render_frame_proxy_host.cc:278: // Verify that ...
4 years, 4 months ago (2016-08-12 18:55:04 UTC) #25
Charlie Reis
4 years, 4 months ago (2016-08-12 20:47:30 UTC) #26
A few responses below.  (Caveat: I haven't reviewed the new patch; just
responded to questions.)

https://codereview.chromium.org/2190183002/diff/140001/content/browser/frame_...
File content/browser/frame_host/render_frame_proxy_host.cc (right):

https://codereview.chromium.org/2190183002/diff/140001/content/browser/frame_...
content/browser/frame_host/render_frame_proxy_host.cc:284:
current_rfh->GetLastCommittedOrigin()))
On 2016/08/12 18:55:04, Łukasz Anforowicz wrote:
> On 2016/08/11 20:40:26, Charlie Reis (OOO soon) wrote:
> > I'm wondering if there's something better we can do here, because I'm not
very
> > happy with treating the origin as a proxy for whether we've navigated.  It
> seems
> > like there's lots of ways this could go wrong:
> > 
> > 1) The origin doesn't change, but we've committed a different page where the
> CSP
> > policy doesn't apply anymore.
> 
> Ack.  Things are a bit improved by your suggestion to cross-check CSP
contents.
> 
> > 2) The renderer lies about the origin.  (Not sure if there's a viable attack
> in
> > this case, but we have to be careful anytime we hear an origin claim from
the
> > renderer.)
> 
> If the renderer lies, then we will ignore the IPC message.  If the renderer
> sends a correct origin, then it is indistinguishable from a normal CSP
violation
> report - OTOH, your remark got me thinking more about potential abuse of the
new
> renderer->browser message (i.e. thinking about the impact of fake CSP
violation
> reports a compromised/hostile renderer can send):
> 
> 1. Since the new message contains |report_endpoints|, a hostile renderer can
> start sending CSP reports to endpoints controlled by an attacker.  This can be
> seen as a way to bypass CSRF protection (because the reports will be sent with
> the Origin header coming from the frame the report gets forwarded to).  If you
> are curious to learn more, you can start looking at code around
> PingLoader::sendViolationReport.  

I don't see any comments there, so I'll avoid digging deeper at the moment.  :)

> 
> Hmmm... I am not sure I understand the threat of CSRF - an attacker can simply
> use telnet and send a fake Origin header, instead of coercing the browser to
do
> it.  I am probably missing something - can you help me learn?

Sure.  CSRF attacks are a threat when the attacker can get a victim's machine to
make the request.  Attackers can't make the requests themselves (e.g., with
telnet) because they don't have the victim's cookies on their machine.  When the
victim's browser sends the POST submission, it carries the victim's cookies (or
other ambient authority, like intranet access).

I'm not up to speed on CSP reports being used for CSRF, but I suppose the
attacker could make up an endpoint like victim.com/do_state_change?  (I'd be
surprised if the CSP report that the browser sends could be interpreted as a
valid command other than reporting a CSP error, but maybe there are cases where
that's a problem.)

> I am comparing against the actual list of report endpoints in patchset #10 -
> this at least means that a hostile renderer doesn't control the endpoints
> (although it can still spam/forge reports send to the real endpoints).
> 
> 2. Ability to spam cross-origin console is not a new threat AFAICT - there is
> already a pair of FrameHostMsg_AddMessageToConsole and
> FrameMsg_AddMessageToConsole.
> 
> 3. A hostile renderer can raise "securitypolicyviolation" cross-origin.
> 
> I am slightly fixing #1 in the patchset #10, but I am not sure if we can
protect
> against #2 and #3 without moving CSP checks to the browser.
> 
> > 3) We have to be careful that current_rfh's origin is always correct, since
> > there are cases where we clear some of its navigation state (e.g., after an
> > ignored navigation).
> > 
> Let's follow-up on this in
> https://codereview.chromium.org/2190183002/patch/160001/170004
> 
> > From one perspective, the document sequence number is a better indication of
> > whether we've moved to a different page, but the renderer process won't know
> the
> > DSN of a remote frame (and I'm pretty sure we don't want to add that).
> 
> Ack.
> 
> > Another not perfect idea: the renderer could send up the CSP policy it was
> using
> > when it noticed the violation, and we can compare it against what the
browser
> > has in the current replication state for the frame?  We would notice if they
> > differ, which would help with case (1) where the origin doesn't change. 
> > However, that doesn't help if you go to a different page with the same CSP
> > policy, which would erroneously get an error.
> 
> Okay - I am doing this in patchset #9.  The IPC already contains the CSP
header
> that is violated - we just need to check if this header value is still present
> in FrameReplicationState (this gets reset when navigating the frame - see how
> NavigatorImpl::DidNavigate calls FrameTreeNode::ResetContentSecurityPolicy).
> 
> Is this better (or maybe good enough), or is the direction of this CL doomed?

I suppose it's good enough if we have to defend against this.  I'm just worried
about it being interpreted as a pattern for others to follow when they're
concerned about skipping an action when the frame has been navigated away. 
Maybe we can add some clear comments about what policy we'd like to have, and
why this approach is a reasonable (and necessary) tradeoff in this case.

> > I'm not sure how else to tell that we've left the page that had the CSP
> policy.
> 
> Yes, it seems to be a difficult problem.
> 
> 
> I could possibly get rid of the checks if only I could guarantee that the
> forwarding is only happening from child to parent (AFAIK this is true today). 
> Unfortunately, when ContentSecurityPolicy::reportViolation is called, it
doesn't
> know that it was checking something for a child.

I would love to leave it out if we can confirm the reports are limited to the
parent/child case.  I've emailed estark@ to see if we can confirm that.

Otherwise, I think the comments I mention above might be sufficient.

https://codereview.chromium.org/2190183002/diff/160001/content/browser/frame_...
File content/browser/frame_host/render_frame_proxy_host.cc (right):

https://codereview.chromium.org/2190183002/diff/160001/content/browser/frame_...
content/browser/frame_host/render_frame_proxy_host.cc:277: if
(!origin_declaring_violated_csp.IsSameOriginWith(
This might be a problem if the origin of the page is unique.  IsSameOriginWith
returns false in that case, even if the page hasn't navigated away.

(I have had a terrible time dealing with this in IsURLInPageNavigation, and I've
got a CL trying to clean that case up further in
https://codereview.chromium.org/2050423002/.)

https://codereview.chromium.org/2190183002/diff/160001/content/browser/frame_...
content/browser/frame_host/render_frame_proxy_host.cc:278:
current_rfh->GetLastCommittedOrigin())) {
On 2016/08/12 18:55:04, Łukasz Anforowicz wrote:
> creis@ said in another comment:
> 
> > 3) We have to be careful that current_rfh's origin is always correct, since
> > there are cases where we clear some of its navigation state (e.g., after an
> > ignored navigation).
> 
> Can you tell me more please?  Is the usage of GetLastCommittedOrigin wrong
> above?
> 
> 

Here's some of the navigation state gotchas I was referring to:

RFHI::last_committed_url_ gets cleared if the process dies, and it is sometimes
set to a cross-site (illegal) URL in the case of a network error, where the page
doesn't actually commit.

RFHI::last_successful_url_ is similar but doesn't get updated for network
errors, allowing us to account for the network error problem above.

RFHI::nav_entry_id_ is set to the NavigationEntry that this RFH is currently
showing, unless its most recent navigation was ignored by NavigationController
(in which case it gets reset).

GetLastCommittedOrigin's biggest wrinkle seems to be that it fails if you don't
call it on the current RFH, but that's not a problem here.  

As far as I can tell, it should be safe to use here, but all this might explain
why I was nervous at first glance.  :)

Powered by Google App Engine
This is Rietveld 408576698