httpwg / http-extensions

HTTP Extensions in progress
https://httpwg.org/http-extensions/
439 stars 146 forks source link

Determine the status of "Upgrade: HTTP/2.0" #2737

Closed bemasc closed 2 weeks ago

bemasc commented 8 months ago

The IANA Upgrade Token Registry lists an entry for HTTP/*.*, and specifically identifies "2.0" as a possible version value, as instructed by RFC 9110 Section 18.10. However, this flow seems to have been superseded by "Upgrade: h2c", which was introduced in RFC 7540 and deprecated in RFC 9113. I am not aware of any implementations of "Upgrade: HTTP/2.0" in clients or servers.

I think we have two main options:

  1. Status Quo: Regard "HTTP/*.*" as a mechanism that is formally defined but not implemented anywhere. Provide formal analysis of its security for completeness.
  2. Deprecation: Update RFC 9110 in this draft to remove the definition of this upgrade token. Mark "HTTP" as "obsolete" in the Upgrade Tokens Registry.
MikeBishop commented 3 months ago

Moving discussion over to the issue, perhaps.

Upgrading to TLS is a defined thing that gets used; I'm not clear that we need to deprecate that.

Upgrading to future HTTP versions is a little more interesting. Certainly it's illegal to upgrade to HTTP/2.0 or HTTP/3.0 because upgrade isn't defined by those specifications. RFC 7540 defines a distinct token, RFC 9113 deprecates it, and RFC 9114 does not define an Upgrade path for obvious reasons. It certainly looks like we've decided not to use this mechanism for changing HTTP versions.

Does that mean we should eliminate it? I'm not opposed, but I'm also not certain we need to go there.

martinthomson commented 3 months ago

Moving to TLS with upgrade (i.e., RFC 2817) is now so much of a niche thing that I think that deprecation would be wise. We've heard that it is still in use, but it's certainly not inoperable in quite the same way as other parts of the protocol.

Either way, I think it would be better to write a separate document deprecating Upgrade (either completely or more narrowly) than to sneak it in here. This document can point out that it is unsafe in the ways in which it is unsafe, but it doesn't need to make the deeper cut to achieve that.

bemasc commented 3 months ago

It seems clear that we don't want to deprecate Upgrade: TLS/*.* in this document, so I've removed that text from #2818.

I've kept #2818 open to discuss the fate of Upgrade: HTTP/*.*. The WG seems to believe that this mechanism is already deprecated, if it was ever defined at all, and the IANA registry entry is just misleading or incorrect.

bemasc commented 3 months ago

I think it would be better to write a separate document deprecating Upgrade (either completely or more narrowly) than to sneak it in here.

The trouble is that Upgrade: HTTP/*.* exists in a sort of quantum superposition of standardized and deprecated, but that will collapse if we mention it in this draft in any way. The options I see are:

  1. Don't claim (as the current text does) to present an exhaustive analysis of the defined Upgrade Tokens, and silently ignore the registration of HTTP/*.*.
  2. Treat it as a live standard.
  3. Declare that it was already deprecated.
  4. Deprecate it.
DavidSchinazi commented 3 months ago

I'd say deprecating isn't particularly useful or interesting, since that doesn't impact implementations. If we can't agree on which quantum state we are in and want to be in at the same time, then I'd leave the cat in the box.

The more interesting question is: should implementations do something to protect against a dangerous Upgrade: HTTP/*.*? For h2, the PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n preface should protect against smuggling. Where do we stand for other versions, is there a risk we should warn implementers about?

bemasc commented 3 months ago

My expectation is that implementations of Upgrade: HTTP/*.* do not exist, and never will, so I don't think it's very useful to provide guidance to them.

There's a question of whether one can even speak about a "downward Upgrade" from HTTP/1.1 to 0.9-1.1. Assuming that is allowed, I think 1.0 and 1.1 are safe, if we assume that the HTTP-Version line is sent/repeated at this point. (Does Upgrade: HTTP create a new HTTP connection or re-version the existing one???) They both start with "HTTP/1", which is not a valid method name due to the "/".

HTTP/0.9 is possibly more interesting since it does not send an HTTP-Version line. I don't see a way for the server to figure out whether the client is speaking HTTP/1.1 (after the rejected upgrade) or HTTP/0.9 (optimistically). However, I don't think this poses a security threat, so long as the attacker-controlled data is the same in HTTP/1.1 as it is in HTTP/0.9. There could possibly be a problem if the client, believing it is speaking HTTP/0.9, allows untrusted code to manipulate headers that were not special in HTTP/0.9 but are special in HTTP/1.1 (e.g. Content-Length, Transfer-Encoding).

But as I said, this strikes me as counting angels on the head of a pin. "Upgrade: HTTP/0.9" is just not a thing, and we should all agree on that and move on.

DavidSchinazi commented 3 months ago

I totally agree with you. I was more thinking about guidance for intermediaries that support other Upgrades (e.g., WebSocket) for what they should do if they encounter unknown/unexpected upgrade tokens like these. If there is no such guidance, than we can just go back to pretending that HTTP/*.* doesn't exist

bemasc commented 3 months ago

HTTP intermediaries can't really do anything with unrecognized Upgrade tokens in HTTP/1.1. (Not even the useful thing, which would be to convert them to/from :protocol for Extended CONNECT.)