Commit 90f87878 authored by Andy Paicu's avatar Andy Paicu Committed by Commit Bot

Prevent sandboxed documents from reusing the default window

Bug: 377995
Change-Id: Iff66c6d214dfd0cb7ea9c80f83afeedfff703541
Reviewed-on: https://chromium-review.googlesource.com/983558
Commit-Queue: Andy Paicu <andypaicu@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567663}
parent 3476f410
......@@ -16,7 +16,7 @@
}
</script>
<iframe src="support/sandboxed-post-message-to-parent.sub.html?sandbox=allow-scripts"></iframe>
<iframe src="support/sandboxed-post-message-to-parent.html?sandbox=allow-scripts"></iframe>
</body>
</html>
\ No newline at end of file
<script>
window.opener.postMessage(window.testProperty, "*");
</script>
\ No newline at end of file
<script>
window.opener.postMessage(window.testProperty, "*");
</script>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
var t = async_test("Window object should not be reused");
window.onmessage = t.step_func_done(function(e) {
assert_equals(e.data, undefined);
});
w = window.open("support/sandboxed-post-property-to-opener.html?sandbox=allow-scripts","","width=400,height=400");
w.testProperty = "test";
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
var t = async_test("Window object should be reused");
window.onmessage = t.step_func_done(function(e) {
assert_equals(e.data, "test");
});
w = window.open("support/unsandboxed-post-property-to-opener.html","","width=400,height=400");
w.testProperty = "test";
</script>
</body>
</html>
\ No newline at end of file
......@@ -3569,7 +3569,10 @@ void Document::DispatchUnloadEvents() {
bool keep_event_listeners =
frame_->Loader().GetProvisionalDocumentLoader() &&
frame_->ShouldReuseDefaultView(
frame_->Loader().GetProvisionalDocumentLoader()->Url());
frame_->Loader().GetProvisionalDocumentLoader()->Url(),
frame_->Loader()
.GetProvisionalDocumentLoader()
->GetContentSecurityPolicy());
if (!keep_event_listeners)
RemoveAllEventListenersRecursively();
}
......
......@@ -79,7 +79,12 @@ class CORE_EXPORT SecurityContext : public GarbageCollectedMixin {
virtual void DidUpdateSecurityOrigin() = 0;
SandboxFlags GetSandboxFlags() const { return sandbox_flags_; }
bool IsSandboxed(SandboxFlags mask) const { return sandbox_flags_ & mask; }
bool IsSandboxed(SandboxFlags mask) const {
return IsSandboxed(mask, sandbox_flags_);
}
static bool IsSandboxed(SandboxFlags mask, SandboxFlags sandbox_flags) {
return sandbox_flags & mask;
}
virtual void EnforceSandboxFlags(SandboxFlags mask);
void SetAddressSpace(mojom::IPAddressSpace space) { address_space_ = space; }
......
......@@ -455,6 +455,12 @@ class CORE_EXPORT ContentSecurityPolicy
// perform these checks in NavigationRequest::CheckContentSecurityPolicy.
WebContentSecurityPolicyList ExposeForNavigationalChecks() const;
// Retrieves the parsed sandbox flags. A lot of the time the execution
// context will be used for all sandbox checks but there are situations
// (before installing the document that this CSP will bind to) when
// there is no execution context to enforce the sandbox flags.
SandboxFlags GetSandboxMask() const { return sandbox_mask_; }
private:
FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceInline);
FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceSinglePolicy);
......
......@@ -822,12 +822,24 @@ Document* LocalFrame::DocumentAtPoint(const LayoutPoint& point_in_root_frame) {
return result.InnerNode() ? &result.InnerNode()->GetDocument() : nullptr;
}
bool LocalFrame::ShouldReuseDefaultView(const KURL& url) const {
bool LocalFrame::ShouldReuseDefaultView(
const KURL& url,
const ContentSecurityPolicy* csp) const {
// Secure transitions can only happen when navigating from the initial empty
// document.
if (!Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
return false;
// The Window object should only be re-used if it is same-origin.
// Since sandboxing turns the origin into an opaque origin it needs to also
// be considered when deciding whether to reuse it.
// Spec:
// https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object
if (csp &&
SecurityContext::IsSandboxed(kSandboxOrigin, csp->GetSandboxMask())) {
return false;
}
return GetDocument()->IsSecureTransitionTo(url);
}
......
......@@ -230,7 +230,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
PositionForPoint(const LayoutPoint& frame_point);
Document* DocumentAtPoint(const LayoutPoint&);
bool ShouldReuseDefaultView(const KURL&) const;
bool ShouldReuseDefaultView(const KURL&, const ContentSecurityPolicy*) const;
void RemoveSpellingMarkersUnderWords(const Vector<String>& words);
bool ShouldThrottleRendering() const;
......
......@@ -711,12 +711,13 @@ void DocumentLoader::CommitNavigation(const AtomicString& mime_type,
if (!Document::ThreadedParsingEnabledForTesting())
parsing_policy = kForceSynchronousParsing;
InstallNewDocument(Url(), owner_document,
frame_->ShouldReuseDefaultView(Url())
? WebGlobalObjectReusePolicy::kUseExisting
: WebGlobalObjectReusePolicy::kCreateNew,
mime_type, encoding, InstallNewDocumentReason::kNavigation,
parsing_policy, overriding_url);
InstallNewDocument(
Url(), owner_document,
frame_->ShouldReuseDefaultView(Url(), GetContentSecurityPolicy())
? WebGlobalObjectReusePolicy::kUseExisting
: WebGlobalObjectReusePolicy::kCreateNew,
mime_type, encoding, InstallNewDocumentReason::kNavigation,
parsing_policy, overriding_url);
parser_->SetDocumentWasLoadedAsPartOfNavigation();
if (request_.WasDiscarded())
frame_->GetDocument()->SetWasDiscarded(true);
......
......@@ -252,6 +252,13 @@ class CORE_EXPORT DocumentLoader
void BlockParser();
void ResumeParser();
// Returns the currently stored content security policy, if this is called
// after the document has been installed it will return nullptr as the
// CSP belongs to the document at that point.
const ContentSecurityPolicy* GetContentSecurityPolicy() const {
return content_security_policy_.Get();
}
protected:
DocumentLoader(LocalFrame*,
const ResourceRequest&,
......
......@@ -365,8 +365,12 @@ void FrameLoader::ReplaceDocumentWhileExecutingJavaScriptURL(
// Compute this before clearing the frame, because it may need to inherit an
// aliased security context.
// The document CSP is the correct one as it is used for CSP checks
// done previously before getting here:
// HTMLFormElement::ScheduleFormSubmission
// HTMLFrameElementBase::OpenURL
WebGlobalObjectReusePolicy global_object_reuse_policy =
frame_->ShouldReuseDefaultView(url)
frame_->ShouldReuseDefaultView(url, document->GetContentSecurityPolicy())
? WebGlobalObjectReusePolicy::kUseExisting
: WebGlobalObjectReusePolicy::kCreateNew;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment