Skip to content

Commit 400d873

Browse files
Evan Stademibrunin
Evan Stade
authored andcommitted
[Backport] Security bug 1485266
Manual cherry-pick of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/4902775: Drag and drop: prevent cross-origin same-tab drags that span navigations In IsValidDragTarget, the old RenderViewHostID comparison was not necessary to distinguish between same- and different-tab drags because, contrary to the previous comment, that case is covered by the `drag_start_` check. This check was only serving to permit some drags which were same-tab, but not same-RVH, which should be disallowed. A complete rundown of the business logic and the reason for the business logic is here: https://bugs.chromium.org/p/chromium/issues/detail?id=1266953#c22 A regression test is added which is confirmed to fail without this fix, but only on Chrome OS because that's the only Aura platform where the DND interactive UI tests are not already disabled (Windows and Linux were disabled). Bug: 1485266 Change-Id: Ifdd6eec14df42372b0afc8ccba779a948cbaaaa7 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4902775 Commit-Queue: Evan Stade <[email protected]> Reviewed-by: Daniel Cheng <[email protected]> Reviewed-by: Charlie Reis <[email protected]> Cr-Commit-Position: refs/heads/main@{#1204930} Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/523704 Reviewed-by: Michal Klocek <[email protected]>
1 parent f3f1c75 commit 400d873

File tree

2 files changed

+20
-50
lines changed

2 files changed

+20
-50
lines changed

chromium/content/browser/web_contents/web_contents_view_aura.cc

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -763,13 +763,10 @@ void WebContentsViewAura::PrepareDropData(
763763
// Do not add FileContents if this is a tainted-cross-origin same-page image
764764
// (https://crbug.com/1264873).
765765
bool access_allowed =
766-
// Drag started outside blink.
767766
!drag_start_ ||
768-
// Drag began in blink, but image access is allowed.
769-
drag_start_->image_accessible_from_frame ||
770-
// Drag began in blink, but in a different WebContents.
771-
GetRenderViewHostID(web_contents_->GetRenderViewHost()) !=
772-
drag_start_->view_id;
767+
// Drag began in this top-level WebContents, and image access is allowed
768+
// (not cross-origin).
769+
drag_start_->image_accessible_from_frame;
773770
data.GetFilenames(&drop_data->filenames);
774771
if (access_allowed && drop_data->filenames.empty()) {
775772
base::FilePath filename;
@@ -885,42 +882,28 @@ bool WebContentsViewAura::IsValidDragTarget(
885882
// drags between cross-origin frames within the same page. Otherwise, a
886883
// malicious attacker could abuse drag interactions to leak information
887884
// across origins without explicit user intent.
885+
// `drag_start_` is null when the drag started outside of the browser or from
886+
// a different top-level WebContents.
888887
if (!drag_start_)
889888
return true;
890889

891890
// For site isolation, it is desirable to avoid having the renderer
892891
// perform the check unless it already has access to the starting
893892
// document's origin. If the SiteInstanceGroups match, then the process
894893
// allocation policy decided that it is OK for the source and target
895-
// frames to live in the same renderer process. Furthermore, it means that
896-
// either the source and target frame are part of the same `blink::Page` or
897-
// that there is an opener relationship and would cross tab boundaries. Allow
898-
// this drag to the renderer. Blink will perform an additional check against
894+
// frames to live in the same renderer process. Furthermore, having matching
895+
// SiteInstanceGroups means that either (1) the source and target frame are
896+
// part of the same blink::Page, or (2) that they are in the same Browsing
897+
// Context Group and the drag would cross tab boundaries (the latter of which
898+
// can't happen here since `drag_start_` is null). Allow this drag to the
899+
// renderer. Blink will perform an additional check against
899900
// `blink::DragController::drag_initiator_` to decide whether or not to
900901
// allow the drag operation. This can be done in the renderer, as the
901902
// browser-side checks only have local tree fragment (potentially with
902903
// multiple origins) granularity at best, but a drag operation eventually
903904
// targets one single frame in that local tree fragment.
904-
bool same_site_instance_group = target_rwh->GetSiteInstanceGroup()->GetId() ==
905-
drag_start_->site_instance_group_id;
906-
if (same_site_instance_group)
907-
return true;
908-
909-
// Otherwise, if the SiteInstanceGroups do not match, enforce explicit
910-
// user intent by ensuring this drag operation is crossing page boundaries.
911-
// `drag_start_->view_id` is set to the main `RenderFrameHost`'s
912-
// `RenderViewHost`'s ID when a drag starts, so if the two IDs match here,
913-
// the drag is within the same page and disallowed.
914-
//
915-
// Drags between an embedder and an inner `WebContents` will disallowed by
916-
// the above view ID check because `WebContentsViewAura` is always created
917-
// for the outermost view. Inner `WebContents` will have a
918-
// `WebContentsViewChildFrame` so when dragging between an inner
919-
// `WebContents` and its embedder the view IDs will be the same.
920-
bool cross_tab_drag =
921-
GetRenderViewHostID(web_contents_->GetRenderViewHost()) !=
922-
drag_start_->view_id;
923-
return cross_tab_drag;
905+
return target_rwh->GetSiteInstanceGroup()->GetId() ==
906+
drag_start_->site_instance_group_id;
924907
}
925908

926909
////////////////////////////////////////////////////////////////////////////////
@@ -1175,7 +1158,6 @@ void WebContentsViewAura::StartDragging(
11751158

11761159
drag_start_ =
11771160
DragStart(source_rwh->GetSiteInstanceGroup()->GetId(),
1178-
GetRenderViewHostID(web_contents_->GetRenderViewHost()),
11791161
drop_data.file_contents_image_accessible);
11801162

11811163
ui::TouchSelectionController* selection_controller = GetSelectionController();

chromium/content/browser/web_contents/web_contents_view_aura.h

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class CONTENT_EXPORT WebContentsViewAura
163163

164164
// Returns whether |target_rwh| is a valid RenderWidgetHost to be dragging
165165
// over. This enforces that same-page, cross-site drags are not allowed. See
166-
// crbug.com/666858.
166+
// crbug.com/666858, crbug.com/1266953, crbug.com/1485266.
167167
bool IsValidDragTarget(RenderWidgetHostImpl* target_rwh) const;
168168

169169
// Called from CreateView() to create |window_|.
@@ -342,7 +342,7 @@ class CONTENT_EXPORT WebContentsViewAura
342342
std::unique_ptr<WindowObserver> window_observer_;
343343

344344
// The WebContentsImpl whose contents we display.
345-
raw_ptr<WebContentsImpl> web_contents_;
345+
const raw_ptr<WebContentsImpl> web_contents_;
346346

347347
std::unique_ptr<WebContentsViewDelegate> delegate_;
348348

@@ -360,33 +360,21 @@ class CONTENT_EXPORT WebContentsViewAura
360360
// avoid sending the drag exited message after leaving the current view.
361361
GlobalRoutingID current_rvh_for_drag_;
362362

363-
// We track the IDs of the source RenderProcessHost and RenderViewHost from
364-
// which the current drag originated. These are used to ensure that drag
365-
// events do not fire over a cross-site frame (with respect to the source
366-
// frame) in the same page (see crbug.com/666858). Specifically, the
367-
// RenderViewHost is used to check the "same page" property, while the
368-
// RenderProcessHost is used to check the "cross-site" property. Note that the
369-
// reason the RenderProcessHost is tracked instead of the RenderWidgetHost is
370-
// so that we still allow drags between non-contiguous same-site frames (such
371-
// frames will have the same process, but different widgets). Note also that
372-
// the RenderViewHost may not be in the same process as the RenderProcessHost,
373-
// since the view corresponds to the page, while the process is specific to
374-
// the frame from which the drag started.
375-
// We also track whether a dragged image is accessible from its frame, so we
376-
// can disallow tainted-cross-origin same-page drag-drop.
363+
// Used to track security-salient details about a drag source. See
364+
// documentation in `IsValidDragTarget()` for `site_instance_group_id`.
365+
// See crbug.com/1264873 for `image_accessible_from_frame`.
377366
struct DragStart {
378367
DragStart(SiteInstanceGroupId site_instance_group_id,
379-
GlobalRoutingID view_id,
380368
bool image_accessible_from_frame)
381369
: site_instance_group_id(site_instance_group_id),
382-
view_id(view_id),
383370
image_accessible_from_frame(image_accessible_from_frame) {}
384371
~DragStart() = default;
385372

386373
SiteInstanceGroupId site_instance_group_id;
387-
GlobalRoutingID view_id;
388374
bool image_accessible_from_frame;
389375
};
376+
// Will hold a value when the current drag started in this page (outermost
377+
// WebContents).
390378
absl::optional<DragStart> drag_start_;
391379

392380
// Responsible for handling gesture-nav and pull-to-refresh UI.

0 commit comments

Comments
 (0)