New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What to do about requests that should (maybe) preflight but don't? #567

Closed
estark37 opened this Issue Jul 19, 2017 · 6 comments

Comments

3 participants
@estark37
Contributor

estark37 commented Jul 19, 2017

Related issues:
#530
bifurcation/expect-ct#18
https://github.com/WICG/reporting/issues/41
httpwg/http-extensions#356

(Feel free to close this if you feel it's duplicative with any of those issues.)

Various specs include various types of "special" requests without CORS preflights, even though they are triggered by web content, to a URL controlled by web content, and are not safe/simple requests.

Many of the examples (CSP, Reporting API, HPKP) are reporting requests, but not all (OCSP). In Expect-CT, the spec lets the UA decide whether a preflight is needed and doesn't take a position on it.

In some cases, like CSP, the lack of preflights is basically a bug, but realistically I doubt we'd be able to require preflights any time soon because of compatibility reasons. In other cases, like OCSP, it doesn't seem likely that implementations will ever want to preflight because of layering reasons.

Should Fetch handle these requests in some way?

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Jul 20, 2017

Member

These are the bits you can potentially control in a request:

  • URL
  • method
  • headers
  • body

To make a request without a CORS preflight, you can only control a couple of headers and the method has to be either GET or POST. There's no restrictions on the body or URL in that case, but the Content-Type header can only be a couple of limited MIME types.

Now browsers sometimes go beyond those restrictions and don't issue a CORS preflight, but whenever this has happened thus far that comes with different restrictions. E.g., for reports the MIME type is fixed (and rather unique), the body is mostly controlled by the browser following the MIME type definition, and methods and headers are also fixed (and not interesting). That makes it highly unlikely those requests could be used for an attack.

It's a little unclean though as the browser effectively has some super powers that are not available (and cannot be made available) to content. And as long as it's not clearly documented it means that browsers end up issuing requests server administrators might not expect (this is also assuming there's no rogue extensions and such in play).

I think the simplest thing to do would be to embrace that it's unclean and clearly document these further same-origin policy exceptions in Fetch and encourage anyone that wants to introduce yet more to first discuss that and strongly consider abiding by the same-origin policy instead (and use CORS preflights if need be). But I'm happy to consider alternatives.

Member

annevk commented Jul 20, 2017

These are the bits you can potentially control in a request:

  • URL
  • method
  • headers
  • body

To make a request without a CORS preflight, you can only control a couple of headers and the method has to be either GET or POST. There's no restrictions on the body or URL in that case, but the Content-Type header can only be a couple of limited MIME types.

Now browsers sometimes go beyond those restrictions and don't issue a CORS preflight, but whenever this has happened thus far that comes with different restrictions. E.g., for reports the MIME type is fixed (and rather unique), the body is mostly controlled by the browser following the MIME type definition, and methods and headers are also fixed (and not interesting). That makes it highly unlikely those requests could be used for an attack.

It's a little unclean though as the browser effectively has some super powers that are not available (and cannot be made available) to content. And as long as it's not clearly documented it means that browsers end up issuing requests server administrators might not expect (this is also assuming there's no rogue extensions and such in play).

I think the simplest thing to do would be to embrace that it's unclean and clearly document these further same-origin policy exceptions in Fetch and encourage anyone that wants to introduce yet more to first discuss that and strongly consider abiding by the same-origin policy instead (and use CORS preflights if need be). But I'm happy to consider alternatives.

@estark37

This comment has been minimized.

Show comment
Hide comment
@estark37

estark37 Jul 21, 2017

Contributor

I agree that actual security risk seems minimal. @annevk what would be the process for spec authors to discuss exceptions that they might want to introduce? Just file an issue against Fetch?

If we do decide that documenting exceptions is the best way to go, I'd be happy to send a PR documenting the exceptions I know of.

Contributor

estark37 commented Jul 21, 2017

I agree that actual security risk seems minimal. @annevk what would be the process for spec authors to discuss exceptions that they might want to introduce? Just file an issue against Fetch?

If we do decide that documenting exceptions is the best way to go, I'd be happy to send a PR documenting the exceptions I know of.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Jul 21, 2017

Member

Yeah, I figured just filing an issue against Fetch would a reasonable start. Hopefully enough people see that to further spread discussion if necessary.

And your contribution would be much appreciated! (Not entirely else who needs to sign off on this plan. @mikewest, @sleevi, and @dveditz come to mind.)

Member

annevk commented Jul 21, 2017

Yeah, I figured just filing an issue against Fetch would a reasonable start. Hopefully enough people see that to further spread discussion if necessary.

And your contribution would be much appreciated! (Not entirely else who needs to sign off on this plan. @mikewest, @sleevi, and @dveditz come to mind.)

@estark37

This comment has been minimized.

Show comment
Hide comment
@estark37

estark37 Jul 21, 2017

Contributor

cc some other possibly interested parties: @juliatuttle @domenic @martinthomson

Contributor

estark37 commented Jul 21, 2017

cc some other possibly interested parties: @juliatuttle @domenic @martinthomson

@martinthomson

This comment has been minimized.

Show comment
Hide comment
@martinthomson

martinthomson Jul 25, 2017

Contributor

I think that the general approach is fine. It's unfortunate that we created these reporting mechanisms without due consideration to this, but that's happened now and there is little sense in trying to wind it back, even if we could.

My question is to what guidance we might provide to someone looking to create yet another exception. Emily has had something of a hard time with Expect-CT, which is a little unfair. If we had a clear description of the principles we intend to apply, that removes a lot of the uncertainty from this.

For instance, is there any reason that we might want to describe how POST and GET are different here? As a safe method, GET is inherently much less likely to trigger unwanted side-effects. The reporting requests generally use POST.

Or, what advice might we give regarding media types? A very specific media type is less likely to trigger adverse reactions from a server that doesn't expect a request, though anything based on JSON might still evade that kind of defense.

Contributor

martinthomson commented Jul 25, 2017

I think that the general approach is fine. It's unfortunate that we created these reporting mechanisms without due consideration to this, but that's happened now and there is little sense in trying to wind it back, even if we could.

My question is to what guidance we might provide to someone looking to create yet another exception. Emily has had something of a hard time with Expect-CT, which is a little unfair. If we had a clear description of the principles we intend to apply, that removes a lot of the uncertainty from this.

For instance, is there any reason that we might want to describe how POST and GET are different here? As a safe method, GET is inherently much less likely to trigger unwanted side-effects. The reporting requests generally use POST.

Or, what advice might we give regarding media types? A very specific media type is less likely to trigger adverse reactions from a server that doesn't expect a request, though anything based on JSON might still evade that kind of defense.

@annevk

This comment has been minimized.

Show comment
Hide comment
@annevk

annevk Jul 25, 2017

Member

I have tried to explore that boundary (see also #530), but I don't think anyone has a concrete answer and browser security teams have certainly dropped the ball a bit as of late (and don't seem to have concrete advice either).

GET and POST are both fine within the confines of <a> and <form> as that is what we allowed historically (probably for worse, but so be it). (And can be made invisible with <iframe>.) Non-GET-non-POST is tricky. We used OPTIONS for CORS preflights. I suspect we'd rather not add more there.

Unique MIME types are generally fine. But yes, if you have +json MIME type there's a risk that a permissive server might extract something from it. At that point it depends how much of the payload is controlled by the attacker.

We should probably also stress that the moment you go beyond CORS, credentials have to be disabled, including HTTP authentication. Doesn't help with intranets or IP-based authentication, but it reduces some of the damage that can be done.

Member

annevk commented Jul 25, 2017

I have tried to explore that boundary (see also #530), but I don't think anyone has a concrete answer and browser security teams have certainly dropped the ball a bit as of late (and don't seem to have concrete advice either).

GET and POST are both fine within the confines of <a> and <form> as that is what we allowed historically (probably for worse, but so be it). (And can be made invisible with <iframe>.) Non-GET-non-POST is tricky. We used OPTIONS for CORS preflights. I suspect we'd rather not add more there.

Unique MIME types are generally fine. But yes, if you have +json MIME type there's a risk that a permissive server might extract something from it. At that point it depends how much of the payload is controlled by the attacker.

We should probably also stress that the moment you go beyond CORS, credentials have to be disabled, including HTTP authentication. Doesn't help with intranets or IP-based authentication, but it reduces some of the damage that can be done.

estark37 added a commit to estark37/fetch that referenced this issue Oct 26, 2017

Document CORS safelist exceptions
As discussed in Issue whatwg#567, browsers have allowed various cross-origin requests
with non-safelisted Content-Type header values to be sent without CORS
preflights. These have occurred either by accident (and now can't be reversed
for compatibility reasons) or because of design constraints (requests that are
implemented outside of the web platform layer). These CORS exceptions are
believed to be safe, but the spec should document them so that servers know to
expect them.

I've added a note about the Content-Type exceptions, but haven't added them to
the safelist, because doing so would imply that web content can triggers
requests with these Content-Type headers and arbitrary bodies. We don't want to
allow fully attacker-controlled requests with these headers, but rather just
want to document the current state where web content can trigger the requests
but not control the headers or bodies.

estark37 added a commit to estark37/fetch that referenced this issue Oct 26, 2017

Document CORS safelist exceptions
As discussed in whatwg#567, browsers have
allowed various cross-origin requests with non-safelisted Content-Type header
values to be sent without CORS preflights. These have occurred either by
accident (and now can't be reversed for compatibility reasons) or because of
design constraints (requests that are implemented outside of the web platform
layer). These CORS exceptions are believed to be safe, but the spec should
document them so that servers know to expect them.

I've added a note about the Content-Type exceptions, but haven't added them to
the safelist, because doing so would imply that web content can triggers
requests with these Content-Type headers and arbitrary bodies. We don't want to
allow fully attacker-controlled requests with these headers, but rather just
want to document the current state where web content can trigger the requests
but not control the headers or bodies.

@annevk annevk closed this in 860ab86 Nov 21, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment