diff options
author | Michael BrĂ¼ning <michael.bruning@qt.io> | 2019-03-20 16:01:35 +0100 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2019-03-27 15:19:17 +0000 |
commit | c6d0023bc59f48abec48597e30bdacf498d61f13 (patch) | |
tree | 86cdff58eb0b8d5976de2a11c52ca3d6e51190ed | |
parent | a63d51633abf7cc7a6031a51addc9b7d48db10d9 (diff) | |
download | qtwebengine-chromium-c6d0023bc59f48abec48597e30bdacf498d61f13.tar.gz |
[Backport] CVE-2019-5802 (5/5)
Manual bckport of original patch by Charlie Harrison
<csharrison@chromium.org>:
Implement opener download metrics for cross-process opener navigations
Currently, the metrics only account for the same-process flow through
BeginNavigation. With this CL, we plumb the relevant information
through the RemoteFrame / RenderFrameProxy / OpenURL path.
Bug: 632514
Reviewed-on: https://chromium-review.googlesource.com/c/1380967
Change-Id: Ie4062172a52d9c329db6fa4a229689b3ed67b5ef
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
18 files changed, 72 insertions, 36 deletions
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc index 2945ef2f662..ea4250efdc2 100644 --- a/chromium/content/browser/frame_host/navigation_controller_impl.cc +++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc @@ -2004,6 +2004,7 @@ void NavigationControllerImpl::NavigateFromFrameProxy( const Referrer& referrer, ui::PageTransition page_transition, bool should_replace_current_entry, + NavigationDownloadPolicy download_policy, const std::string& method, scoped_refptr<network::ResourceRequestBody> post_body, const std::string& extra_headers, @@ -2104,7 +2105,7 @@ void NavigationControllerImpl::NavigateFromFrameProxy( CreateNavigationRequestFromLoadParams( render_frame_host->frame_tree_node(), params, override_user_agent, should_replace_current_entry, false /* has_user_gesture */, - ReloadType::NONE, *entry, frame_entry.get()); + download_policy, ReloadType::NONE, *entry, frame_entry.get()); if (!request) return; @@ -2573,8 +2574,8 @@ void NavigationControllerImpl::NavigateWithoutEntry( std::unique_ptr<NavigationRequest> request = CreateNavigationRequestFromLoadParams( node, params, override_user_agent, should_replace_current_entry, - has_user_gesture, reload_type, *pending_entry_, - pending_entry_->GetFrameEntry(node)); + has_user_gesture, NavigationDownloadPolicy::kAllow, reload_type, + *pending_entry_, pending_entry_->GetFrameEntry(node)); // If the navigation couldn't start, return immediately and discard the // pending NavigationEntry. @@ -2772,9 +2773,12 @@ NavigationControllerImpl::CreateNavigationRequestFromLoadParams( // Create the NavigationParams based on |params|. bool is_view_source_mode = virtual_url.SchemeIs(kViewSourceScheme); - NavigationDownloadPolicy download_policy = - is_view_source_mode ? NavigationDownloadPolicy::kDisallowViewSource - : NavigationDownloadPolicy::kAllow; + // Update |download_policy| if the virtual URL is view-source. Why do this + // now? Possibly the URL could be rewritten to a view-source via some URL + // handler. + if (is_view_source_mode) + download_policy = NavigationDownloadPolicy::kDisallowViewSource; + const GURL& history_url_for_data_url = params.base_url_for_data_url.is_empty() ? GURL() : virtual_url; CommonNavigationParams common_params( diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h index 6e673629d65..7cc4d81c8aa 100644 --- a/chromium/content/browser/frame_host/navigation_controller_impl.h +++ b/chromium/content/browser/frame_host/navigation_controller_impl.h @@ -111,6 +111,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController { const Referrer& referrer, ui::PageTransition page_transition, bool should_replace_current_entry, + NavigationDownloadPolicy download_policy, const std::string& method, scoped_refptr<network::ResourceRequestBody> post_body, const std::string& extra_headers, @@ -311,6 +312,7 @@ class CONTENT_EXPORT NavigationControllerImpl : public NavigationController { bool override_user_agent, bool should_replace_current_entry, bool has_user_gesture, + NavigationDownloadPolicy download_policy, ReloadType reload_type, const NavigationEntryImpl& entry, FrameNavigationEntry* frame_entry); diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h index fe5fe87f06f..fd0b9dd15fb 100644 --- a/chromium/content/browser/frame_host/navigator.h +++ b/chromium/content/browser/frame_host/navigator.h @@ -131,6 +131,7 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> { const Referrer& referrer, ui::PageTransition page_transition, bool should_replace_current_entry, + NavigationDownloadPolicy download_policy, const std::string& method, scoped_refptr<network::ResourceRequestBody> post_body, const std::string& extra_headers, diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc index c6f47ecde41..e9a8c947080 100644 --- a/chromium/content/browser/frame_host/navigator_impl.cc +++ b/chromium/content/browser/frame_host/navigator_impl.cc @@ -521,6 +521,7 @@ void NavigatorImpl::NavigateFromFrameProxy( const Referrer& referrer, ui::PageTransition page_transition, bool should_replace_current_entry, + NavigationDownloadPolicy download_policy, const std::string& method, scoped_refptr<network::ResourceRequestBody> post_body, const std::string& extra_headers, @@ -571,8 +572,9 @@ void NavigatorImpl::NavigateFromFrameProxy( controller_->NavigateFromFrameProxy( render_frame_host, url, is_renderer_initiated, source_site_instance, - referrer_to_use, page_transition, should_replace_current_entry, method, - post_body, extra_headers, std::move(blob_url_loader_factory)); + referrer_to_use, page_transition, + should_replace_current_entry, download_policy, method, post_body, + extra_headers, std::move(blob_url_loader_factory)); } void NavigatorImpl::OnBeforeUnloadACK(FrameTreeNode* frame_tree_node, diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h index b97af7081e4..c7e43d3fb5e 100644 --- a/chromium/content/browser/frame_host/navigator_impl.h +++ b/chromium/content/browser/frame_host/navigator_impl.h @@ -82,6 +82,7 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator { const Referrer& referrer, ui::PageTransition page_transition, bool should_replace_current_entry, + NavigationDownloadPolicy download_policy, const std::string& method, scoped_refptr<network::ResourceRequestBody> post_body, const std::string& extra_headers, diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.cc b/chromium/content/browser/frame_host/render_frame_proxy_host.cc index b06a4b9242d..9f9cb2dd1d3 100644 --- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc +++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc @@ -353,7 +353,8 @@ void RenderFrameProxyHost::OnOpenURL( // to PAGE_TRANSITION_FORM_SUBMIT. See https://crbug.com/829827. frame_tree_node_->navigator()->NavigateFromFrameProxy( current_rfh, validated_url, site_instance_.get(), params.referrer, - ui::PAGE_TRANSITION_LINK, params.should_replace_current_entry, + ui::PAGE_TRANSITION_LINK, + params.should_replace_current_entry, params.download_policy, params.uses_post ? "POST" : "GET", params.resource_request_body, params.extra_headers, std::move(blob_url_loader_factory)); } diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h index f36396d9feb..bfc597c92c5 100644 --- a/chromium/content/common/frame_messages.h +++ b/chromium/content/common/frame_messages.h @@ -570,6 +570,7 @@ IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params) IPC_STRUCT_MEMBER(bool, is_history_navigation_in_new_child) IPC_STRUCT_MEMBER(blink::WebTriggeringEventInfo, triggering_event_info) IPC_STRUCT_MEMBER(mojo::MessagePipeHandle, blob_url_token) + IPC_STRUCT_MEMBER(content::NavigationDownloadPolicy, download_policy) IPC_STRUCT_END() IPC_STRUCT_BEGIN(FrameHostMsg_DownloadUrl_Params) diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc index ae9a4b0a8a9..c05fba60224 100644 --- a/chromium/content/renderer/render_frame_impl.cc +++ b/chromium/content/renderer/render_frame_impl.cc @@ -490,26 +490,6 @@ WebURLRequest CreateURLRequestForNavigation( return request; } -NavigationDownloadPolicy GetDownloadPolicy( - bool prevent_sandboxed_download, - bool is_opener_navigation, - const blink::WebURLRequest& request, - const WebSecurityOrigin& current_origin) { - if (prevent_sandboxed_download) - return NavigationDownloadPolicy::kDisallowSandbox; - if (!is_opener_navigation) - return NavigationDownloadPolicy::kAllow; - bool gesture = request.HasUserGesture(); - bool cross_origin = !request.RequestorOrigin().CanAccess(current_origin); - if (!gesture && cross_origin) - return NavigationDownloadPolicy::kAllowOpenerCrossOriginNoGesture; - if (!gesture) - return NavigationDownloadPolicy::kAllowOpenerNoGesture; - if (cross_origin) - return NavigationDownloadPolicy::kAllowOpenerCrossOrigin; - return NavigationDownloadPolicy::kAllowOpener; -} - CommonNavigationParams MakeCommonNavigationParams( const WebSecurityOrigin& current_origin, const blink::WebLocalFrameClient::NavigationPolicyInfo& info, @@ -551,8 +531,10 @@ CommonNavigationParams MakeCommonNavigationParams( static_cast<RequestExtraData*>(info.url_request.GetExtraData()); DCHECK(extra_data); NavigationDownloadPolicy download_policy = - GetDownloadPolicy(prevent_sandboxed_download, info.is_opener_navigation, - info.url_request, current_origin); + prevent_sandboxed_download + ? NavigationDownloadPolicy::kDisallowSandbox + : RenderFrameImpl::GetOpenerDownloadPolicy( + info.is_opener_navigation, info.url_request, current_origin); return CommonNavigationParams( info.url_request.Url(), referrer, extra_data->transition_type(), navigation_type, download_policy, info.replaces_current_history_item, GURL(), GURL(), @@ -1432,6 +1414,24 @@ blink::WebFrame* RenderFrameImpl::ResolveOpener(int opener_frame_routing_id) { return nullptr; } +// static +NavigationDownloadPolicy RenderFrameImpl::GetOpenerDownloadPolicy( + bool is_opener_navigation, + const blink::WebURLRequest& request, + const WebSecurityOrigin& current_origin) { + if (!is_opener_navigation) + return NavigationDownloadPolicy::kAllow; + bool gesture = request.HasUserGesture(); + bool cross_origin = !request.RequestorOrigin().CanAccess(current_origin); + if (!gesture && cross_origin) + return NavigationDownloadPolicy::kAllowOpenerCrossOriginNoGesture; + if (!gesture) + return NavigationDownloadPolicy::kAllowOpenerNoGesture; + if (cross_origin) + return NavigationDownloadPolicy::kAllowOpenerCrossOrigin; + return NavigationDownloadPolicy::kAllowOpener; +} + blink::WebURL RenderFrameImpl::OverrideFlashEmbedWithHTML( const blink::WebURL& url) { return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url); @@ -6598,6 +6598,9 @@ void RenderFrameImpl::OpenURL(const NavigationPolicyInfo& info, if (is_history_navigation_in_new_child) params.is_history_navigation_in_new_child = true; + params.download_policy = RenderFrameImpl::GetOpenerDownloadPolicy( + info.is_opener_navigation, info.url_request, + frame_->GetSecurityOrigin()); Send(new FrameHostMsg_OpenURL(routing_id_, params)); } diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h index 9e9ca760952..688af98b01d 100644 --- a/chromium/content/renderer/render_frame_impl.h +++ b/chromium/content/renderer/render_frame_impl.h @@ -275,6 +275,15 @@ class CONTENT_EXPORT RenderFrameImpl // routing ID. static blink::WebFrame* ResolveOpener(int opener_frame_routing_id); + // Gets the download policy for a given navigation with regard to its opener + // status. We are trying to block downloads resulting from x-origin opener + // navigations if they do not have a gesture. See https://crbug.com/632514 for + // background. + static NavigationDownloadPolicy GetOpenerDownloadPolicy( + bool is_opener_navigation, + const blink::WebURLRequest& request, + const blink::WebSecurityOrigin& current_origin); + // Overwrites the given URL to use an HTML5 embed if possible. blink::WebURL OverrideFlashEmbedWithHTML(const blink::WebURL& url) override; diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc index f3e8c457e97..ccc734e07dd 100644 --- a/chromium/content/renderer/render_frame_proxy.cc +++ b/chromium/content/renderer/render_frame_proxy.cc @@ -769,6 +769,7 @@ void RenderFrameProxy::ForwardPostMessage( void RenderFrameProxy::Navigate(const blink::WebURLRequest& request, bool should_replace_current_entry, + bool is_opener_navigation, mojo::ScopedMessagePipeHandle blob_url_token) { FrameHostMsg_OpenURL_Params params; params.url = request.Url(); @@ -783,6 +784,8 @@ void RenderFrameProxy::Navigate(const blink::WebURLRequest& request, params.user_gesture = request.HasUserGesture(); params.triggering_event_info = blink::WebTriggeringEventInfo::kUnknown; params.blob_url_token = blob_url_token.release(); + params.download_policy = RenderFrameImpl::GetOpenerDownloadPolicy( + is_opener_navigation, request, web_frame_->GetSecurityOrigin()); Send(new FrameHostMsg_OpenURL(routing_id_, params)); } diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h index d906ad3a279..abfdabbfb27 100644 --- a/chromium/content/renderer/render_frame_proxy.h +++ b/chromium/content/renderer/render_frame_proxy.h @@ -192,6 +192,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, bool has_user_gesture) override; void Navigate(const blink::WebURLRequest& request, bool should_replace_current_entry, + bool is_opener_navigation, mojo::ScopedMessagePipeHandle blob_url_token) override; void FrameRectsChanged(const blink::WebRect& local_frame_rect, const blink::WebRect& screen_space_rect) override; diff --git a/chromium/third_party/blink/public/web/web_remote_frame_client.h b/chromium/third_party/blink/public/web/web_remote_frame_client.h index afefb61736c..acf312efcc2 100644 --- a/chromium/third_party/blink/public/web/web_remote_frame_client.h +++ b/chromium/third_party/blink/public/web/web_remote_frame_client.h @@ -41,6 +41,7 @@ class WebRemoteFrameClient { // A remote frame was asked to start a navigation. virtual void Navigate(const WebURLRequest& request, bool should_replace_current_entry, + bool is_opener_navigation, mojo::ScopedMessagePipeHandle blob_url_token) {} virtual void Reload(WebFrameLoadType, ClientRedirectPolicy) {} diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc index 7a664c13f71..f1751b4d3ed 100644 --- a/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/chromium/third_party/blink/renderer/core/exported/web_frame_test.cc @@ -9850,6 +9850,7 @@ class RemoteNavigationClient // FrameTestHelpers::TestWebRemoteFrameClient: void Navigate(const WebURLRequest& request, bool should_replace_current_entry, + bool is_opener_navigation, mojo::ScopedMessagePipeHandle) override { last_request_ = request; } diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc index ae704ae6005..f7cdd9aa904 100644 --- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc @@ -86,10 +86,12 @@ void RemoteFrame::Navigate(const FrameLoadRequest& passed_request) { FrameLoader::SetReferrerForFrameRequest(frame_request); FrameLoader::UpgradeInsecureRequest(frame_request.GetResourceRequest(), frame_request.OriginDocument()); - + Document* document = frame_request.OriginDocument(); + bool is_opener_navigation = document && document->GetFrame() && + document->GetFrame()->Client()->Opener() == this; Client()->Navigate(frame_request.GetResourceRequest(), frame_request.ReplacesCurrentItem(), - frame_request.GetBlobURLToken()); + is_opener_navigation, frame_request.GetBlobURLToken()); } void RemoteFrame::Reload(WebFrameLoadType frame_load_type, diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h index f578bbfdd7d..0b2c792a4e6 100644 --- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h +++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client.h @@ -30,6 +30,7 @@ class RemoteFrameClient : public FrameClient { virtual void Navigate(const ResourceRequest&, bool should_replace_current_entry, + bool is_opener_navigation, mojom::blink::BlobURLTokenPtr) = 0; virtual void Reload(WebFrameLoadType, ClientRedirectPolicy) = 0; unsigned BackForwardLength() override = 0; diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc index 25d988f493e..71551e25846 100644 --- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc +++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc @@ -111,11 +111,12 @@ base::UnguessableToken RemoteFrameClientImpl::GetDevToolsFrameToken() const { void RemoteFrameClientImpl::Navigate( const ResourceRequest& request, bool should_replace_current_entry, + bool is_opener_navigation, mojom::blink::BlobURLTokenPtr blob_url_token) { if (web_frame_->Client()) { - web_frame_->Client()->Navigate(WrappedResourceRequest(request), - should_replace_current_entry, - blob_url_token.PassInterface().PassHandle()); + web_frame_->Client()->Navigate( + WrappedResourceRequest(request), should_replace_current_entry, + is_opener_navigation, blob_url_token.PassInterface().PassHandle()); } } diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h index 0e9871705b3..c9c622f586d 100644 --- a/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h +++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h @@ -35,6 +35,7 @@ class RemoteFrameClientImpl final : public RemoteFrameClient { // RemoteFrameClient overrides: void Navigate(const ResourceRequest&, bool should_replace_current_entry, + bool is_opener_navigation, mojom::blink::BlobURLTokenPtr) override; void Reload(WebFrameLoadType, ClientRedirectPolicy) override; unsigned BackForwardLength() override; diff --git a/chromium/third_party/blink/renderer/core/loader/empty_clients.h b/chromium/third_party/blink/renderer/core/loader/empty_clients.h index dbb68e5e649..0387515ff18 100644 --- a/chromium/third_party/blink/renderer/core/loader/empty_clients.h +++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.h @@ -413,6 +413,7 @@ class CORE_EXPORT EmptyRemoteFrameClient : public RemoteFrameClient { // RemoteFrameClient implementation. void Navigate(const ResourceRequest&, bool should_replace_current_entry, + bool is_opener_navigation, mojom::blink::BlobURLTokenPtr) override {} void Reload(WebFrameLoadType, ClientRedirectPolicy) override {} unsigned BackForwardLength() override { return 0; } |