[whatwg] Fixing two security vulnerabilities in registerProtocolHandler

Tyler Close tyler.close at gmail.com
Mon Sep 26 11:09:49 PDT 2011


I was recently experimenting with the registerProtocolHandler (RPH)
API and came across a couple of security gotchas that make it hard to
safely use the API. One of these is already known, but AFAICT, hasn't
been fixed yet. I haven't seen the other discussed yet.

The Mozilla blog post that introduces the registerProtocolHandler API
makes use of window.parent.postMessage to send a response from the RPH
handler back to the client page. In the example code, the targetOrigin
for this postMessage invocation is '*', while also noting that this is
not secure. AFAICT, there is no API that the intent handler can
reliably use to determine the correct targetOrigin for this
postMessage invocation. I suggest fixing this problem by adding a new
readonly DOMString that contains the correct origin for the
postMessage invocation; perhaps document.origin. So the response
invocation would then be coded as:

  window.parent.postMessage('my response data', document.origin);

Perhaps a different name or location is better for this field, so I'll
defer to the editor's judgment.

The second problem with RPH is that the handler page doesn't have a
way of reliably getting the URL of the content to be handled from the
browser. In order to work in offline scenarios, the RPH handler must
put the %s placeholder in the fragment of its handler's URL.
Unfortunately, this means that other content in the browser could
modify the content URL before the handler reads it. For example, an
attacker could open a window on a victim web page. The victim web page
then opens an <iframe> on a content URL that triggers RPH. The
attacker then navigates the <iframe> so that its window.location
contains a different content URL. The intent handler sees a request
coming from the victim page, but with a content URL specified by the
attacker. A related problem is that the intent handler has no way to
distinguish whether its URL was loaded via the browser's RPH handling,
or whether the client page directly navigated to the intent handler's
URL. Both of these problems could be fixed by adding another readonly
DOMString to the API that contains the %s data for the RPH invocation.
This new field must be in a location that can only be set by the
browser, such as window.navigator.action (taking the "action" name
from the <form> element). Safe intent handler code is then:

  if (window.navigator.action) {
    // Handle navigation to the URL in window.navigator.action
    myCustomContentLoader(window.navigator.action);
    window.parent.postMessage('did it!', document.origin);
  }

Again, I defer to the editors on the best name and location for this
new readonly DOMString. I'm mostly interested in seeing these two
security issues in RPH cured.

Thanks,
--Tyler


More information about the whatwg mailing list