Make WordPress Core

Opened 9 years ago

Closed 9 years ago

#34831 closed defect (bug) (fixed)

WP oEmbed: Validate the "Secret" When Used in `document.querySelectorAll()`

Reported by: mdawaffe's profile mdawaffe Owned by: mdawaffe's profile mdawaffe
Milestone: 4.4 Priority: normal
Severity: normal Version: 4.4
Component: Embeds Keywords: has-patch
Focuses: javascript Cc:

Description

In the data sent to us from the embedded iframe by postMessage(), the secret value is being used directly in a document.querySelectorAll() call without first being validated or escaped.

In theory, this could lead to some broken embeds.

Suggested hardening patch attached: There's no reason to try and escape this data correctly. Let's just reject if the secret does not conform to the format we expect.

Attachments (3)

34831.diff (972 bytes) - added by mdawaffe 9 years ago.
34831.2.diff (532 bytes) - added by mdawaffe 9 years ago.
TobiasBg's patch
34831.3.diff (767 bytes) - added by mdawaffe 9 years ago.
Compare window objects

Download all attachments as: .zip

Change History (13)

@mdawaffe
9 years ago

#1 @TobiasBg
9 years ago

How about just prepending

if ( /[^a-zA-Z0-9]/.test( data.secret ) ) { 
    return; 
}

if we return anyways? Would make for a simpler logic, IMO.

@mdawaffe
9 years ago

TobiasBg's patch

#2 @mdawaffe
9 years ago

Works for me. Updated patch: attachment:34831.2.diff

#3 @swissspidy
9 years ago

  • Owner set to pento
  • Status changed from new to assigned

+1 to this enhancement and the second patch.

#4 @wonderboymusic
9 years ago

  • Keywords commit added

Looks good.

#5 follow-up: @pento
9 years ago

Is /[^a-zA-Z0-9]/.test( data.secret ) or data.secret.match( /[^a-zA-Z0-9]/ ) better?

#6 in reply to: ↑ 5 @swissspidy
9 years ago

Replying to pento:

Is /[^a-zA-Z0-9]/.test( data.secret ) or data.secret.match( /[^a-zA-Z0-9]/ ) better?

test() returns a bool, whereas match() returns all the matches. For that reason, test() is much faster.

MDN recommends using search() if you need to know if a string matches a regular expression. search() returns the index of the first match or -1.

This comparison between all those functions shows that search() and test() are both much, much faster than the other methods.

#7 @pento
9 years ago

  • Owner changed from pento to mdawaffe

Well, I'm convinced. Let's commit it.

@mdawaffe
9 years ago

Compare window objects

#8 @mdawaffe
9 years ago

  • Keywords commit removed

Another piece of hardening: We can't do the normal postMessage() origin checks (sandboxed iframes have sandboxed origins), but we can ensure that the message event's source (a window object) is the same as the iframe's window.

This protects against some potential, weird information disclosure bug with the secret. That is, with this extra check, the secret does not need to be private; it just becomes a unique ID.

Combined patch attached: attachment:34831.3.diff.

#9 @swissspidy
9 years ago

I've tested the latest patch, even by embedding from different domains as well. Works as advertised!

#10 @wonderboymusic
9 years ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 35761:

WP oEmbed: validate the secret send via postMessage in wp.receiveEmbedMessage. Also, compare window instances.

In the data sent to us from the embedded iframe by postMessage(), the secret value is being used directly in a document.querySelectorAll() call without first being validated or escaped.

In theory, this could lead to some broken embeds.

Props mdawaffe.
Fixes #34831.

Note: See TracTickets for help on using tickets.