Discussion:
[whatwg] WhatWG is broken
Michael A. Peters
2016-11-30 20:21:34 UTC
Permalink
https://www.w3.org/TR/html-design-principles/#priority-of-constituencies

3.2. Priority of Constituencies

In case of conflict, consider users over authors over implementors over
specifiers over theoretical purity. In other words costs or difficulties
to the user should be given more weight than costs to authors; which in
turn should be given more weight than costs to implementors; which
should be given more weight than costs to authors of the spec itself,
which should be given more weight than those proposing changes for
theoretical reasons alone. Of course, it is preferred to make things
better for multiple constituencies at once.
3.3. Secure By Design

Ensure that features work with the security model of the web.
Preferrably address security considerations directly in the specification.

Communicating between documents from different sites is useful, but an
unrestricted version could put user data at risk. Cross-document
messaging is designed to allow this without violating security constraints.

-=-=-=-=-=-=-=-

Right now the specification for window.opener() is seriously insecure,
allowing for cross-domain script access by default.

WhatWG refuses to properly address the issue.

The reason they refuse to properly address the issue is because it would
break OAuth.

Yup - an alleged security tool requires an insecure Internet. That's the
most insane logic I have ever heard but that's what the issue is.

The proposed fix - rel="noopener" - is insufficient, it is difficult to
consistently deploy and there are thousands upon thousands of archived
web pages that won't have that attribute added.

It is unrealistic to expect the end user to be aware of the issue, the
end user will be vulnerable to phishing and other attacks made possible
via window.opener() if the browsers do not protect them, but the
browsers will not protect them unless the specification calls for it,
and the specification will not call for it because the same companies
that are heavily invested in OAuth run the WhatWG.

There is a serious conflict of interest and it is resulting in a web
that does not put the user first, or the security of the user first, but
instead is putting first a protocol that has had repeated serious
security flaws and is broken by design.

If the WhatWG can't put the security of Internet users first, then it
needs to be disbanded and replaced by a working group that will put the
security of the users first.
Ian Hickson
2016-12-01 01:23:39 UTC
Permalink
Post by Michael A. Peters
Right now the specification for window.opener() is seriously insecure,
allowing for cross-domain script access by default.
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
Post by Michael A. Peters
The reason they refuse to properly address the issue is because it would
break OAuth.
I'm not sure who "they" is here, but since this is the first this topic has
come up on this list, would you mind providing us with some background?

For example, could you describe the security risk? How does it break OAuth?
Can you give an example of a page affected by this?

If there's a particular github issue where these topics have already been
discussed, then if you would like the broader WHATWG community to be aware
of these issues then I recommend linking to that issue in your e-mail to
the list. Many people following the list don't follow the github repository
closely enough to see every issue.


the browsers will not protect them unless the specification calls for it,
Post by Michael A. Peters
and the specification will not call for it because the same companies
that are heavily invested in OAuth run the WhatWG.
That's not really how the WHATWG works. I encourage you to read our FAQ:
https://wiki.whatwg.org/wiki/FAQ

One factor to bear in mind in particular is that the specification has no
power. We could put whatever we want in the spec, but if browser vendors
don't want to implement it, it doesn't really matter, they'll just ignore
it.


If the WhatWG can't put the security of Internet users first, then it
Post by Michael A. Peters
needs to be disbanded and replaced by a working group that will put the
security of the users first.
There's already plenty too many working groups working on HTML as it is...

Cheers,
--
Ian Hickson
Michael A. Peters
2016-12-01 02:21:34 UTC
Permalink
Post by Ian Hickson
Post by Michael A. Peters
Right now the specification for window.opener() is seriously insecure,
allowing for cross-domain script access by default.
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
Actually it does. Site A can link to Site B on a completely different
domain and JavaScript on Site B has access to the window for Site A and
can change the URL and other things.
Post by Ian Hickson
Post by Michael A. Peters
The reason they refuse to properly address the issue is because it would
break OAuth.
I'm not sure who "they" is here, but since this is the first this topic has
come up on this list, would you mind providing us with some background?
Yes, I apologize, this was written in frustration and I should have
calmed down.

Browsers are implementing rel="noopener" as a fix. A wrong fix, I have
never heard of an attribute on an element being used to define script
security for a window but that's how it is being addressed.

It is a fix that is not ideal. Archived web pages won't have the fix,
and anchors in web applications are created by many different processes
and plugins - both when the page is served and via ajax after the page
the served - sometimes by the main web application and sometimes by a
plugin. It is simply not realistic to ask web applications to make sure
each use of an anchor with a target attribute is accompanied by a
rel="noopener" attribute in order to be secure.

People at browsers I spoke with said they can only implement what the
WhatWG specifies, and the rel="noopener" is the specified solution.

So I went to the WhatWG github page, found an open issue on noopener and
contributed my thoughts. Was told I was off topic, and not to derail it.

So I started a new issue asking to deprecate rel="noopener" and replace
it instead with a header that websites who want to allow window.opener
to modify them including a whitelist of domains that could use it.

The issue was very quickly closed without any discussion based upon the
issue of backwards compatibility. That was more important that fixing
the insecure spec.

When digging to try and find out what was so important, a link to
another topic was given where it turns out OAuth is the application that
makes heavy use of window.opener

So I then came up with a different suggestion, one that doesn't break
backwards compatibility, but instead allows a webmaster to send a header
specifying what domains (if any) to whitelist. No header and the current
behavior would be retained, but it would allow sites to secure their
pages from window.opener() without having to add a rel tag to every link
- a simply .htaccess directive could serve the header.

Again with absolutely no discussion the issue was immediately closed by
a Google employee (and I know Google is heavily invested in OAuth)
claiming that CSP is the right place for that.

But as much as I personally love CSP, virtually every webmaster I have
talked to who has tried it has abandoned it because it was too difficult
for them to implement without problems that then take hours to figure
out. It apparently can be particularly difficult to configure on
WordPress sites or sites that use Google Adsense or Analytics.

So Content Security Policy isn't the right place.

It is very frustrating to have such a bad security flaw that is being
kept around because OAuth depends upon the flaw and have any attempt to
have the specification fixed in a sane reasonable way immediately closed
on the WhatWG github page.

And I confess, I'm not exactly a people person as it is, but it just
really felt like they didn't care about the issues and had absolutely no
interest in a solution that makes the web safer for users.

That's the history.

Something needs to be done, relying upon websites adding rel="noopener"
to every case of <a href="external" target="_blanl" they serve is just
not realistic and even many websites that try will fail.

But a header can be adding in one line to a .htaccess file and served
with every web page. It's the right solution, the secure solution.

Whether the header is required by sites that want to allow window.opener
or required by sites that want to block it - I don't really care, but a
header is the right solution and a rel tag is just so conceptually
broken I don't know how that even was accepted.

Thank you for your time, I apologize for the tone of my earlier post.
Michael A. Peters
2016-12-01 03:33:48 UTC
Permalink
Post by Michael A. Peters
On Wed, Nov 30, 2016 at 4:49 PM Michael A. Peters
Post by Michael A. Peters
Right now the specification for window.opener() is seriously insecure,
allowing for cross-domain script access by default.
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
Actually it does. Site A can link to Site B on a completely different
domain and JavaScript on Site B has access to the window for Site A and
can change the URL and other things.
Here is easy demo showing the blatant cross-domain scripting vulnerability.

<!-- put this page as a.html on foo.com -->
<html>
<head>
<title>Test target link</title>
</head>
<body>
<p><a href="https://bar.net/b.html" target="_blank">link to
different domain</a></p>
</body>
</html>

<!-- put this page as b.html on bar.net -->
<html>
<head>
<title>Test window.opener</title>
<script type="text/javascript" >
if (window.opener && !window.opener.closed)
opener.location = 'http://www.example.org/'
</script>
</head>
<body>
<p>The page on foo.com will have changed to http://www.example.org/
because this page had script access to that window. Obvious very serious
phishing concern, and probably other concerns</p>
</body>
</html>
Chris Holland
2016-12-01 06:41:05 UTC
Permalink
I guess this issue was discussed at the following thread on chromium.org,
with comment #10 offering the more interesting exploit vector that seems to
happen on sites with user-generated content (UGC):

https://bugs.chromium.org/p/chromium/issues/detail?id=168988#c10

... and Comment 11 right after it:

https://bugs.chromium.org/p/chromium/issues/detail?id=168988#c11 <--
although i guess this would only apply if the link was target="_blank" such
that it does open in a new window, which is pretty common practice on UGC
sites anyway.

... and as Michael pointed out, this bug got closed on the count of
rel="noopener"

I get Michael's point that securing an existing site with UGC content is
going to be a somewhat painful proposition, although one could craft a
one-liner piece of javascript which would use the DOM to add or augment the
"rel" attribute to anchors. This should be easily done on Wordpress sites
as a template footer, or in the header on document ready. This would
alleviate your having to modify the HTML code for every single link, as I
too would hate to liter my anchors with more unsightly attributes.

I remember using window.opener to change a parent's location since the late
90's, this behavior has been around for a *long time*, so i could see why
browser makers would be more than a little reluctant to "deny by default"
and require site makers to add an extra http header to "allow" the behavior.

But if I understand Michael's proposed behavior correctly, we would allow
sites to set a header as such:

X-Child-Context-Control-Allow-Domains: *foo.com <http://foo.com>, bar.net
<http://bar.net> * <-- some sites are allowed
X-Child-Context-Control-Allow-Domains: *none* <-- no sites are allowed
X-Child-Context-Control-Allow-Domains: ** *<-- this header is unnecessary
because it is the default behavior or all browsers

... *XCCCAD *for short (for lack of snazzier acronym)

==> when this header is not present, the current behavior applies, which
means most sites are "insecure by default".
==> sites who do wish to secure themselves could set the above header and
browsers would forbid child windows from controlling parent windows, aside
from listed exceptions.

This would:

0) complement, not replace rel="noopener"
1) retain current backward compatibility
2) allow sites to secure themselves more globally with a simple .htaccess
rule. (instead of having to modify their anchors manually or via the DOM)

The above proposition might remind you of CORS:
Access-Control-Allow-Origin: *
http://enable-cors.org/server.html

However the above proposed behavior would be exactly opposite to that of
the CORS behavior, and I think that it makes perfect sense, because the
situation we're trying to address, is the exact opposite of the situation
that the CORS behavior was looking to address:

- Sites are "secure by default" in that they don't allow their content to
be accessed by a browsing context outside of their host/domain, as this is
every browser's default behavior.
- Adding the CORS header enables sites to make themselves less secure by
instructing browsers that other sites can load their content via, say, an
XmlHttpRequest.

I think the devil would be in implementation detail. Slapping a
"rel/noopener" attribute on a specific link is very deterministic and
straightforward from a logic standpoint ---- Whichever window was created
from this link can't control the parent.

In the case of an *XCCCAD *header we need to specify when it would be in
effect. And I think it might be as simple as "it applies to all windows
opened from the HTML document which was served with this header in the
response headers".
Post by Michael A. Peters
Post by Michael A. Peters
On Wed, Nov 30, 2016 at 4:49 PM Michael A. Peters
Post by Michael A. Peters
Right now the specification for window.opener() is seriously insecure,
allowing for cross-domain script access by default.
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
Actually it does. Site A can link to Site B on a completely different
domain and JavaScript on Site B has access to the window for Site A and
can change the URL and other things.
Here is easy demo showing the blatant cross-domain scripting vulnerability.
<!-- put this page as a.html on foo.com -->
<html>
<head>
<title>Test target link</title>
</head>
<body>
<p><a href="https://bar.net/b.html" target="_blank">link to different
domain</a></p>
</body>
</html>
<!-- put this page as b.html on bar.net -->
<html>
<head>
<title>Test window.opener</title>
<script type="text/javascript" >
if (window.opener && !window.opener.closed)
opener.location = 'http://www.example.org/'
</script>
</head>
<body>
<p>The page on foo.com will have changed to http://www.example.org/
because this page had script access to that window. Obvious very serious
phishing concern, and probably other concerns</p>
</body>
</html>
--
Chris Holland
http://www.linkedin.com/in/chrisholland
310-500-7598
Boris Zbarsky
2016-12-01 06:53:18 UTC
Permalink
Post by Chris Holland
I think the devil would be in implementation detail. Slapping a
"rel/noopener" attribute on a specific link is very deterministic and
straightforward from a logic standpoint ---- Whichever window was created
from this link can't control the parent.
It's a much stronger guarantee. The guarantee is that the parent and
the created window have no way to see each other at all. Neither one
can read any state from the other, or even know the other one exists.

In particular, the idea is that rel="noopener" allows the new window to
be opened in a separate process, or even a separate browser if desired.
The only difference between it and the user copying the link and then
pasting it into some other tab or other program is that a referrer
header is sent.

Note that this guarantee makes for fairly simple implementation.

Having a header that opts in all links targeted at anything other than
_parent, _self, and _top have the noopener behavior would be doable.
Having a header that opts in some links based on the origin of the link
href or something would probably be doable. Having a header that tries
to add some sort of new mode wherein the two windows _can_ see each
other but can't do some things that they can normally do would be a
snake pit of complexity that is best avoided.

-Boris
Elliott Sprehn
2016-12-02 02:14:37 UTC
Permalink
Post by Chris Holland
I think the devil would be in implementation detail. Slapping a
"rel/noopener" attribute on a specific link is very deterministic and
straightforward from a logic standpoint ---- Whichever window was created
from this link can't control the parent.
It's a much stronger guarantee. The guarantee is that the parent and the
created window have no way to see each other at all. Neither one can read
any state from the other, or even know the other one exists.
In particular, the idea is that rel="noopener" allows the new window to be
opened in a separate process, or even a separate browser if desired. The
only difference between it and the user copying the link and then pasting
it into some other tab or other program is that a referrer header is sent.
Note that this guarantee makes for fairly simple implementation.
Having a header that opts in all links targeted at anything other than
_parent, _self, and _top have the noopener behavior would be doable. Having
a header that opts in some links based on the origin of the link href or
something would probably be doable. Having a header that tries to add some
sort of new mode wherein the two windows _can_ see each other but can't do
some things that they can normally do would be a snake pit of complexity
that is best avoided.
I would like us to think about adding a mode where you get a MessageChannel
between the two windows. There's no synchronous access, and no ability to
navigate it, but you can talk back and forth with it.
-Boris
Michael A. Peters
2016-12-02 02:43:58 UTC
Permalink
Post by Elliott Sprehn
Post by Chris Holland
I think the devil would be in implementation detail. Slapping a
"rel/noopener" attribute on a specific link is very deterministic and
straightforward from a logic standpoint ---- Whichever window was created
from this link can't control the parent.
It's a much stronger guarantee. The guarantee is that the parent and the
created window have no way to see each other at all. Neither one can read
any state from the other, or even know the other one exists.
In particular, the idea is that rel="noopener" allows the new window to be
opened in a separate process, or even a separate browser if desired. The
only difference between it and the user copying the link and then pasting
it into some other tab or other program is that a referrer header is sent.
Note that this guarantee makes for fairly simple implementation.
Having a header that opts in all links targeted at anything other than
_parent, _self, and _top have the noopener behavior would be doable. Having
a header that opts in some links based on the origin of the link href or
something would probably be doable. Having a header that tries to add some
sort of new mode wherein the two windows _can_ see each other but can't do
some things that they can normally do would be a snake pit of complexity
that is best avoided.
I would like us to think about adding a mode where you get a MessageChannel
between the two windows. There's no synchronous access, and no ability to
navigate it, but you can talk back and forth with it.
I haven't tried but I don't see why service workers couldn't be used for
that.
Domenic Denicola
2016-12-02 01:39:40 UTC
Permalink
I believe that's a bit of an overstatement. There are certainly risks involved in window.opener (they're briefly discussed in the spec itself), but it doesn't remove the origin checks.
This is the crucial point.

Whenever you are discussing a supposed security issue, you need to make clear what the threat model is. That is:

- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?

In this case, the impact on the victim (a user of a web browser) is that they could click a link from page A to page B, which opens in a new tab (tab B). Then, tab A could be navigated to a new URL, instead of staying on page A.

This is not a big impact. Notably, page B is not able to read any of the content of page A, which might be sensitive. Page B is not able to interfere with the operation of any of page B's scripts. And crucially, when page B navigates tab A to another page, the URL bar of tab A changes to indicate that.

There is no desired security guarantee on the platform that we want to prevent pages from directing users to "bad" sites. We count on users inspecting the URL bar to understand what page they are interacting with in a given tab.

So, while it might be a bit surprising that suddenly tab A is navigating somewhere else, there is no security issue here, and users are not endangered in any way---at least, not in any more danger than they already are from browsing the web without loo
Zac Spitzer
2016-12-02 01:45:22 UTC
Permalink
how about rather than requiring this on every <a> why not support a base
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Post by Ian Hickson
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of staying on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting with in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
--
Zac Spitzer
+61 405 847 168
Domenic Denicola
2016-12-02 01:48:41 UTC
Permalink
how about rather than requiring this on every <a> why not support a base tag directive  for the whole document i.e. <base rel="noopener">, similar to <base target="_blank">?
Yes, this is a good idea to include in a general framework for imposing such self-restrictions on your page, such as CSP: https://github.com/w3c/webappsec/issues/139
Michael A. Peters
2016-12-02 02:42:56 UTC
Permalink
Well if it was done as a header, I suppose it could be added as a
http-equiv meta tag for those who want to.

Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.

And I know this is conspiracy theory, but that's why I think there is
such resistance to it.

Since the flaw is required for OAuth to work, companies invested in
OAuth and that profit from OAuth solutions don't want sites behind
proxies that would break OAuth and don't want webmasters to understand
they have to reduce security in order to implement an OAuth solution.

That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why
there is such resistance to doing it the right way with a header. To me
it just doesn't make sense.
Post by Zac Spitzer
how about rather than requiring this on every <a> why not support a base
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Post by Ian Hickson
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of staying on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting with in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
Richard Maher
2016-12-02 03:23:57 UTC
Permalink
I see what you're saying Michael and also agree it's serious. Would I be
correct in thinking that MS Edge solves the problem by not returning
window.opener cross-domain? Is the UA not a logical and uniform place for
this?

BTW I've also experienced the CitHub topic-closure nazis many times :-(
Post by Michael A. Peters
Well if it was done as a header, I suppose it could be added as a
http-equiv meta tag for those who want to.
Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.
And I know this is conspiracy theory, but that's why I think there is such
resistance to it.
Since the flaw is required for OAuth to work, companies invested in OAuth
and that profit from OAuth solutions don't want sites behind proxies that
would break OAuth and don't want webmasters to understand they have to
reduce security in order to implement an OAuth solution.
That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why there
is such resistance to doing it the right way with a header. To me it just
doesn't make sense.
Post by Zac Spitzer
how about rather than requiring this on every <a> why not support a base
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Hickson
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of staying on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting with in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
Michael A. Peters
2016-12-02 03:44:35 UTC
Permalink
If window.opener() did not work cross-domain then as far as I can tell
that would be secure.
Post by Richard Maher
I see what you're saying Michael and also agree it's serious. Would I be
correct in thinking that MS Edge solves the problem by not returning
window.opener cross-domain? Is the UA not a logical and uniform place for
this?
BTW I've also experienced the CitHub topic-closure nazis many times :-(
Post by Michael A. Peters
Well if it was done as a header, I suppose it could be added as a
http-equiv meta tag for those who want to.
Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.
And I know this is conspiracy theory, but that's why I think there is such
resistance to it.
Since the flaw is required for OAuth to work, companies invested in OAuth
and that profit from OAuth solutions don't want sites behind proxies that
would break OAuth and don't want webmasters to understand they have to
reduce security in order to implement an OAuth solution.
That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why there
is such resistance to doing it the right way with a header. To me it just
doesn't make sense.
Post by Zac Spitzer
how about rather than requiring this on every <a> why not support a base
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Hickson
I believe that's a bit of an overstatement. There are certainly risks
involved in window.opener (they're briefly discussed in the spec itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of staying on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting with in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
Richard Maher
2016-12-02 06:11:20 UTC
Permalink
Thanks Michael. So to be safe one should use Edge? Who'd have thunk it?

Anyone tested Michael's example on FireFox or Safari?

It does look like Chrome is the driver of rel=noopener. Does the credential
API https://w3c.github.io/webappsec-credential-management/ rely on this
flaw?
Post by Michael A. Peters
If window.opener() did not work cross-domain then as far as I can tell
that would be secure.
Post by Richard Maher
I see what you're saying Michael and also agree it's serious. Would I be
correct in thinking that MS Edge solves the problem by not returning
window.opener cross-domain? Is the UA not a logical and uniform place for
this?
BTW I've also experienced the CitHub topic-closure nazis many times :-(
On Fri, Dec 2, 2016 at 10:42 AM, Michael A. Peters <
Well if it was done as a header, I suppose it could be added as a
Post by Michael A. Peters
http-equiv meta tag for those who want to.
Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.
And I know this is conspiracy theory, but that's why I think there is such
resistance to it.
Since the flaw is required for OAuth to work, companies invested in OAuth
and that profit from OAuth solutions don't want sites behind proxies that
would break OAuth and don't want webmasters to understand they have to
reduce security in order to implement an OAuth solution.
That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why there
is such resistance to doing it the right way with a header. To me it just
doesn't make sense.
how about rather than requiring this on every <a> why not support a base
Post by Zac Spitzer
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Hickson
I believe that's a bit of an overstatement. There are certainly risks
Post by Ian Hickson
involved in window.opener (they're briefly discussed in the spec
itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken
advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of
staying
on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting
with
in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
Jonathan Zuckerman
2016-12-02 13:01:45 UTC
Permalink
Could you elaborate on the point made earlier that CSP is too complicated
to implement? What would the fix for this particularly security hole look
like, using CSP?

On Fri, Dec 2, 2016 at 1:11 AM Richard Maher <***@googlemail.com> wrote:

Thanks Michael. So to be safe one should use Edge? Who'd have thunk it?

Anyone tested Michael's example on FireFox or Safari?

It does look like Chrome is the driver of rel=noopener. Does the credential
API https://w3c.github.io/webappsec-credential-management/ rely on this
flaw?
Post by Michael A. Peters
If window.opener() did not work cross-domain then as far as I can tell
that would be secure.
Post by Richard Maher
I see what you're saying Michael and also agree it's serious. Would I be
correct in thinking that MS Edge solves the problem by not returning
window.opener cross-domain? Is the UA not a logical and uniform place for
this?
BTW I've also experienced the CitHub topic-closure nazis many times :-(
On Fri, Dec 2, 2016 at 10:42 AM, Michael A. Peters <
Well if it was done as a header, I suppose it could be added as a
Post by Michael A. Peters
http-equiv meta tag for those who want to.
Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.
And I know this is conspiracy theory, but that's why I think there is such
resistance to it.
Since the flaw is required for OAuth to work, companies invested in OAuth
and that profit from OAuth solutions don't want sites behind proxies that
would break OAuth and don't want webmasters to understand they have to
reduce security in order to implement an OAuth solution.
That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why there
is such resistance to doing it the right way with a header. To me it just
doesn't make sense.
how about rather than requiring this on every <a> why not support a base
Post by Zac Spitzer
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Hickson
I believe that's a bit of an overstatement. There are certainly risks
Post by Ian Hickson
involved in window.opener (they're briefly discussed in the spec
itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to make
- What would be the impact on the victim if the security hole is taken
advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new tab
(tab B). Then, tab A could be navigated to a new URL, instead of
staying
on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And crucially,
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting
with
in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see where
they've ended up at.
Michael A. Peters
2016-12-02 16:01:37 UTC
Permalink
Personally I love CSP but it does not allow inline scripts or inline CSS
and over 95% of the web makes heavy use of both.

I believe there now are CSP parameters that relax those prohibitions but
from I understand they are only relaxed when a hash of the inline
scripts / CSS is declared in the head.

Google Webmaster Tools including PageSpeed also heavily encourage all
JavaScript being referenced at the end of the page so that it isn't
above the fold and because they are Google, most of the masses believe
that is best and will help with page search ranking and that too isn't
compatible with CSP where the scripts need to be defined in the head
(except for maybe with the new unsafe-inline option that requires
checksum in the head ???)

I don't know what the planned CSP option for window.opener() looks like,
I just know that most websites break as soon as a CSP header is sent and
it isn't always trivial to make them work.
Post by Jonathan Zuckerman
Could you elaborate on the point made earlier that CSP is too complicated
to implement? What would the fix for this particularly security hole look
like, using CSP?
Thanks Michael. So to be safe one should use Edge? Who'd have thunk it?
Anyone tested Michael's example on FireFox or Safari?
It does look like Chrome is the driver of rel=noopener. Does the credential
API https://w3c.github.io/webappsec-credential-management/ rely on this
flaw?
Post by Michael A. Peters
If window.opener() did not work cross-domain then as far as I can tell
that would be secure.
Post by Richard Maher
I see what you're saying Michael and also agree it's serious. Would I be
correct in thinking that MS Edge solves the problem by not returning
window.opener cross-domain? Is the UA not a logical and uniform place for
this?
BTW I've also experienced the CitHub topic-closure nazis many times :-(
On Fri, Dec 2, 2016 at 10:42 AM, Michael A. Peters <
Well if it was done as a header, I suppose it could be added as a
Post by Michael A. Peters
http-equiv meta tag for those who want to.
Header is the easiest solution to make sure it is applied everywhere
without question. It could even be added at the front-end proxy to cover
numerous web applications on many domains at once.
And I know this is conspiracy theory, but that's why I think there is such
resistance to it.
Since the flaw is required for OAuth to work, companies invested in
OAuth
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
and that profit from OAuth solutions don't want sites behind proxies
that
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
would break OAuth and don't want webmasters to understand they have to
reduce security in order to implement an OAuth solution.
That's just a suspicion of mine, but I can't think of any other logical
reason as to why a node attribute was chosen as the solution, and why there
is such resistance to doing it the right way with a header. To me it
just
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
doesn't make sense.
how about rather than requiring this on every <a> why not support a base
Post by Zac Spitzer
tag directive
for the whole document i.e. <base rel="noopener">, similar to <base
target="_blank">?
Post by Ian Hickson
Hickson
I believe that's a bit of an overstatement. There are certainly risks
Post by Ian Hickson
involved in window.opener (they're briefly discussed in the spec
itself),
but it doesn't remove the origin checks.
This is the crucial point.
Whenever you are discussing a supposed security issue, you need to
make
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
Post by Zac Spitzer
Post by Ian Hickson
- What would be the impact on the victim if the security hole is taken
advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that
they could click a link from page A to page B, which opens in a new
tab
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
Post by Zac Spitzer
Post by Ian Hickson
(tab B). Then, tab A could be navigated to a new URL, instead of
staying
on
page A.
This is not a big impact. Notably, page B is not able to read any of the
content of page A, which might be sensitive. Page B is not able to
interfere with the operation of any of page B's scripts. And
crucially,
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
Post by Zac Spitzer
Post by Ian Hickson
when page B navigates tab A to another page, the URL bar of tab A changes
to indicate that.
There is no desired security guarantee on the platform that we want to
prevent pages from directing users to "bad" sites. We count on users
inspecting the URL bar to understand what page they are interacting
with
in
a given tab.
So, while it might be a bit surprising that suddenly tab A is navigating
somewhere else, there is no security issue here, and users are not
endangered in any way---at least, not in any more danger than they already
are from browsing the web without looking at their URL bar to see
where
Post by Michael A. Peters
Post by Richard Maher
Post by Michael A. Peters
Post by Zac Spitzer
Post by Ian Hickson
they've ended up at.
Boris Zbarsky
2016-12-02 16:23:09 UTC
Permalink
Post by Michael A. Peters
Personally I love CSP but it does not allow inline scripts or inline CSS
Only if you say to not allow them. The default behavior allows them.
For example, this disallows inline scripts, because script-src is
explicitly specified without unsafe-inline, but does nothing about
inline CSS:

<!DOCTYPE html>
<meta http-equiv="content-security-policy"
content="script-src 'self'">
<style>body { color: green; }</style>
This is green
<script>alert("I am not alerted")</script>
Post by Michael A. Peters
I believe there now are CSP parameters that relax those prohibitions but
from I understand they are only relaxed when a hash of the inline
scripts / CSS is declared in the head.
That's ... not correct. Simple example; compare it to the previous one:

<!DOCTYPE html>
<meta http-equiv="content-security-policy"
content="script-src 'self' 'unsafe-inline'">
<style>body { color: green; }</style>
This is green
<script>alert("I am alerted")</script>
Post by Michael A. Peters
and that too isn't
compatible with CSP where the scripts need to be defined in the head
Uh... No, they do not. Neither of my examples above has a <script> in
the <head>
Post by Michael A. Peters
(except for maybe with the new unsafe-inline option that requires
checksum in the head ???)
unsafe-inline doesn't require a checksum. See examples above.
Post by Michael A. Peters
I just know that most websites break as soon as a CSP header is sent
That really depends on the header sent. If you send a header whose
value is the empty string, for example, it will have no effect
whatsoever. If you send a header which only has a object-src directive,
and you don't use <object>, it will have no effect whatsoever.

If you send something with very restrictive script-src and style-src,
then well, you have to work within those restrictions.
Post by Michael A. Peters
and it isn't always trivial to make them work.
If you want to impose sufficiently stringent restrictions, sure.

-Boris
Boris Zbarsky
2016-12-02 16:26:12 UTC
Permalink
Post by Boris Zbarsky
Post by Michael A. Peters
(except for maybe with the new unsafe-inline option that requires
checksum in the head ???)
unsafe-inline doesn't require a checksum. See examples above.
It's also not new. Certainly the November 2012 CR of CSP 1.0 [1] has
unsafe-inline.

-Boris

[1] https://www.w3.org/TR/2012/CR-CSP-20121115/
Michael A. Peters
2016-12-02 16:34:55 UTC
Permalink
Post by Boris Zbarsky
Post by Michael A. Peters
Personally I love CSP but it does not allow inline scripts or inline CSS
Only if you say to not allow them. The default behavior allows them.
For example, this disallows inline scripts, because script-src is
explicitly specified without unsafe-inline, but does nothing about
<!DOCTYPE html>
<meta http-equiv="content-security-policy"
content="script-src 'self'">
<style>body { color: green; }</style>
This is green
<script>alert("I am not alerted")</script>
Post by Michael A. Peters
I believe there now are CSP parameters that relax those prohibitions but
from I understand they are only relaxed when a hash of the inline
scripts / CSS is declared in the head.
It seems that CSP behavior has radically changed since the last time I
looked at it, which was to create support for it in my php class that
generates web pages using DOMDocument, so I can't comment on what the
current state of it is then.

At least historically, the on* attributes were not allowed, the style
attributes were not allowed, and any script nodes in the body were not
allowed.

They were not allowed for very good reasons - there is no way for the
browser to determine if they are intentional or are the result of a XSS
injection in the web application.

JS and CSS in external files referenced from the head was the only way
to safely determine they were intended and not injected.

If CSP now allows them by default then I am not very happy about that,
as it would greatly reduce the effective security, but it sounds like I
would have to read through the current documentation to further comment
on CSP.
Boris Zbarsky
2016-12-02 16:47:34 UTC
Permalink
Post by Michael A. Peters
It seems that CSP behavior has radically changed since the last time I
looked at it
I can't speak to when you last looked at it, but the current state
shipping in browsers is, as far as I know, no different from what
browsers shipped initially for purposes of this discussion.
Post by Michael A. Peters
At least historically, the on* attributes were not allowed, the style
attributes were not allowed, and any script nodes in the body were not
allowed.
If you specify script-src and style-src and don't include
'unsafe-inline', sure.
Post by Michael A. Peters
If CSP now allows them by default then I am not very happy about that
CSP allows the things you don't issue directives for. If you don't
issue any script-src directives (or default-src directives), then there
won't be any limitations on scripts.

-Boris
Michael A. Peters
2016-12-02 17:07:54 UTC
Permalink
Post by Boris Zbarsky
Post by Michael A. Peters
It seems that CSP behavior has radically changed since the last time I
looked at it
I can't speak to when you last looked at it, but the current state
shipping in browsers is, as far as I know, no different from what
browsers shipped initially for purposes of this discussion.
Post by Michael A. Peters
At least historically, the on* attributes were not allowed, the style
attributes were not allowed, and any script nodes in the body were not
allowed.
If you specify script-src and style-src and don't include
'unsafe-inline', sure.
Post by Michael A. Peters
If CSP now allows them by default then I am not very happy about that
CSP allows the things you don't issue directives for. If you don't
issue any script-src directives (or default-src directives), then there
won't be any limitations on scripts.
-Boris
Last time I read the specification, unsafe-inline didn't exist. Last
time I glanced at the site, unsafe-inline existed but was not supported
by all browsers and required a declared hash to work.
Tantek Çelik
2016-12-08 19:49:10 UTC
Permalink
On Fri, Dec 2, 2016 at 9:07 AM, Michael A. Peters
Post by Boris Zbarsky
Post by Michael A. Peters
It seems that CSP behavior has radically changed since the last time I
looked at it
I can't speak to when you last looked at it, but the current state
shipping in browsers is, as far as I know, no different from what
browsers shipped initially for purposes of this discussion.
Post by Michael A. Peters
At least historically, the on* attributes were not allowed, the style
attributes were not allowed, and any script nodes in the body were not
allowed.
If you specify script-src and style-src and don't include
'unsafe-inline', sure.
Post by Michael A. Peters
If CSP now allows them by default then I am not very happy about that
CSP allows the things you don't issue directives for. If you don't
issue any script-src directives (or default-src directives), then there
won't be any limitations on scripts.
-Boris
Last time I read the specification, unsafe-inline didn't exist. Last time I
glanced at the site, unsafe-inline existed but was not supported by all
browsers and required a declared hash to work.
I have been using unsafe-inline on both style and script directives in
the CSP live on my site tantek.com (home page, permalinks) for over a
year.

I have seen no problems with Firefox / Chrome / Safari, and have not
gotten any reports of problems from Edge users either.

I documented the CSP directive I'm using here: https://indieweb.org/CSP#Tantek

If you know of any specific browsers where it is "not supported", let
me know, because I have received zero such reports.

Thanks,

Tantek

Michael A. Peters
2016-12-02 02:16:45 UTC
Permalink
Post by Domenic Denicola
I believe that's a bit of an overstatement. There are certainly risks involved in window.opener (they're briefly discussed in the spec itself), but it doesn't remove the origin checks.
This is the crucial point.
- What would be the impact on the victim if the security hole is taken advantage of?
- Is this something we are trying to prevent on the web platform?
In this case, the impact on the victim (a user of a web browser) is that they could click a link from page A to page B, which opens in a new tab (tab B). Then, tab A could be navigated to a new URL, instead of staying on page A.
This is not a big impact.
It is a huge impact.

Scenario A) It can be used for protocol downgrade attack.

Site A has both https and http. JavaScript on site B reloads Site A as
HTTP - so even though the user visited A as HTTPS, now they are at A as
HTTP.

The user has no reason to suspect that the protocol changed, and on
mobile devices the URL bar is often hidden.

Scenario B) User clicks on link to Site B. Site B puts up a fake page
telling the user Google has blocked the site because of malware and asks
them to close the window.

Meanwhile JavaScript changhed Site A to a phishing page that says
Facebook (or whatever) detected a malicious cross site scripting, would
they please login again to verify their identity.

The user was just at Site A and it was genuine, just experienced a
warning they believed to be from Google that malware was attempted, and
enters their username and password.

This is an extremely serious bug and I literally do not comprehend why I
keep having to explain it.

Remember most users don't know the difference between JavaScript and
Turbo Pascal.

The best encryption in the world doesn't protect users from social
engineering attacks directly made possible by this kind of flaw.
Loading...