diff options
author | Michal Klocek <michal.klocek@qt.io> | 2018-08-10 12:22:39 +0200 |
---|---|---|
committer | Michal Klocek <michal.klocek@qt.io> | 2018-08-10 14:46:08 +0000 |
commit | e8b9ae61d0fc8123da8170dc8b4bdc561dcb7e32 (patch) | |
tree | ae677e6516800a92238035723c0d7437a4d0c699 | |
parent | 0cce345ee0781cda8effabf7521b9a3653c6674e (diff) |
defeat cors attacks on audio/video tags
Neutralize error messages and fire no progress events
until media metadata has been loaded for media loaded
from cross-origin locations.
Bug: 828265, 826187
Reviewed-on: https://chromium-review.googlesource.com/1015794
Change-Id: Ie8064f04c606f11bfa88a72b1d5ef82a84bdd409
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
-rw-r--r-- | chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp | 40 | ||||
-rw-r--r-- | chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h | 10 |
2 files changed, 40 insertions, 10 deletions
diff --git a/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp b/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp index c05d0a33521..1d92423de4b 100644 --- a/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp +++ b/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp @@ -1528,14 +1528,17 @@ void HTMLMediaElement::WaitForSourceChange() { GetLayoutObject()->UpdateFromElement(); } -void HTMLMediaElement::NoneSupported(const String& message) { - BLINK_MEDIA_LOG << "NoneSupported(" << (void*)this << ", message='" << message +void HTMLMediaElement::NoneSupported(const String& input_message) { + BLINK_MEDIA_LOG << "NoneSupported(" << (void*)this << ", message='" << input_message << "')"; StopPeriodicTimers(); load_state_ = kWaitingForSource; current_source_node_ = nullptr; + String empty_string; + const String& message = MediaShouldBeOpaque() ? empty_string : input_message; + // 4.8.12.5 // The dedicated media source failure steps are the following steps: @@ -1611,11 +1614,17 @@ void HTMLMediaElement::NetworkStateChanged() { } void HTMLMediaElement::MediaLoadingFailed(WebMediaPlayer::NetworkState error, - const String& message) { + const String& input_message) { BLINK_MEDIA_LOG << "MediaLoadingFailed(" << (void*)this << ", " - << static_cast<int>(error) << ", message='" << message + << static_cast<int>(error) << ", message='" << input_message << "')"; + bool should_be_opaque = MediaShouldBeOpaque(); + if (should_be_opaque) + error = WebMediaPlayer::kNetworkStateNetworkError; + String empty_string; + const String& message = should_be_opaque ? empty_string : input_message; + StopPeriodicTimers(); // If we failed while trying to load a <source> element, the movie was never @@ -1718,12 +1727,14 @@ void HTMLMediaElement::SetNetworkState(WebMediaPlayer::NetworkState state) { void HTMLMediaElement::ChangeNetworkStateFromLoadingToIdle() { progress_event_timer_.Stop(); + if (!MediaShouldBeOpaque()) { // Schedule one last progress event so we guarantee that at least one is fired // for files that load very quickly. - if (GetWebMediaPlayer() && GetWebMediaPlayer()->DidLoadingProgress()) - ScheduleEvent(EventTypeNames::progress); - ScheduleEvent(EventTypeNames::suspend); - SetNetworkState(kNetworkIdle); + if (GetWebMediaPlayer() && GetWebMediaPlayer()->DidLoadingProgress()) + ScheduleEvent(EventTypeNames::progress); + ScheduleEvent(EventTypeNames::suspend); + SetNetworkState(kNetworkIdle); + } } void HTMLMediaElement::ReadyStateChanged() { @@ -1891,6 +1902,14 @@ void HTMLMediaElement::ProgressEventTimerFired(TimerBase*) { if (network_state_ != kNetworkLoading) return; + // If this is an cross-origin request, and we haven't discovered whether + // the media is actually playable yet, don't fire any progress events as + // those may let the page know information about the resource that it's + // not supposed to know. + + if (MediaShouldBeOpaque()) + return; + double time = WTF::CurrentTime(); double timedelta = time - previous_progress_time_; @@ -4206,6 +4225,11 @@ gfx::ColorSpace HTMLMediaElement::TargetColorSpace() { return frame->GetPage()->GetChromeClient().GetScreenInfo().color_space; } +bool HTMLMediaElement::MediaShouldBeOpaque() const { + return !IsMediaDataCORSSameOrigin(GetDocument().GetSecurityOrigin()) && + ready_state_ < kHaveMetadata && !FastGetAttribute(srcAttr).IsEmpty(); +} + void HTMLMediaElement::CheckViewportIntersectionTimerFired(TimerBase*) { bool should_report_root_bounds = true; IntersectionGeometry geometry(nullptr, *this, Vector<Length>(), diff --git a/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h b/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h index 3ce50fb760b..c39178808b6 100644 --- a/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h +++ b/chromium/third_party/WebKit/Source/core/html/media/HTMLMediaElement.h @@ -258,8 +258,8 @@ class CORE_EXPORT HTMLMediaElement using HTMLElement::GetExecutionContext; bool HasSingleSecurityOrigin() const { - return GetWebMediaPlayer() && - GetWebMediaPlayer()->HasSingleSecurityOrigin(); + return GetWebMediaPlayer() ? GetWebMediaPlayer()->HasSingleSecurityOrigin() + : true; } bool IsFullscreen() const; @@ -342,6 +342,12 @@ class CORE_EXPORT HTMLMediaElement InsertionNotificationRequest InsertedInto(ContainerNode*) override; void RemovedFrom(ContainerNode*) override; + // Return true if media is cross origin from the current document + // and has not passed a cors check, meaning that we should return + // as little information as possible about it. + + bool MediaShouldBeOpaque() const; + void DidMoveToNewDocument(Document& old_document) override; virtual KURL PosterImageURL() const { return KURL(); } |