-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
[BUG] Semicolon unduly acts as separator for query parameters (thereby creating a parser differential) #781
Comments
One more thing... What I'm proposing here is to bring gorilla/mux in line with the URL Living Standard. However, it's worth pointing out that net/url (even modern versions, from v1.17.0 up to v1.24.x) still is not fully compliant with the URL Living Standard insofar as it ignores query-param pairs that contain semicolons; see golang/go#50034. Therefore, even if #782 (or my more extreme option, numbered 4) got merged, a parser differential between gorilla/mux and net/url would persist, one which could allow adversaries to smuggle (past net/url and to gorilla/mux) a query-param pair whose value contains a semicolon. Consider, for instance, query string
This leads me to wonder whether gorilla/mux
|
I am not against this change in gorilla/mux, but IMO it really ought to be considered an API break, and require /v2. The change in the golang side caused a lot of damage, we need to go over with a fine comb on everything that goes from go < 1.17 to go >= 1.17 because of that. So consider this a vote AGAINST changing the default behavior in gorilla/mux v1, and a vote FOR changing the default behaviour in an eventual gorilla/mux v2 to match net/url and net/http. Note that I have absolutely nothing against adding a non-default way for gorilla/mux v1 to stop accepting ";" as a URL query parameter separator: it won't break existing code. |
Is there an existing issue for this?
Current Behavior
The
(*Router).Queries
method splits query-parameter pairs on both ampersands and semicolons.Expected Behavior
Up to (excl.) commit 75dcda0, gorilla/mux to relied on net/url (Go 1.12, at that time of that commit) for parsing the query string. That commit introduced a query-string parser based on net/url but modified for performance.
net/url used to split query params on both ampersands and semicolons, but it now (since Go 1.17) only splits query-param pairs on ampersands, in compliance with the URL Living Standard.
I expect gorilla/mux to follow suit, and the sooner the better.
Steps To Reproduce
Run the following server locally:
Then run the following command in your shell:
curl -v 'localhost:8080/?foo=foo;bar=bar'
Actual output:
Expected output:
Anything else?
Although splitting query-param pairs on both ampersands and semicolons is harmless in isolation, it creates interoperability issues when gorilla/mux is used in conjunction with other tools that only split query-param pairs on ampersands (and not on semicolons). Such a parser differential can indeed open the door to security vulnerabilities, such as Web cache poisoning (via query-parameter cloacking) and broken access control.
Broken access control, in particular, is a real risk for programmes that rely on both net/url and mux.Vars for parsing the query string; you may believe that such programmes are rare, but take a look at the Minio project, which does rely on such a mix. For instance, consider the simple server below:
Here, the intention is to only allow access to the resource identified by
1
. Let's try it:So far, so good. But an attacker could delete a resource he or she doesn't own (e.g. the resource of ID
42
) like this:The problem is that
r.URL.Query().Get("id") == "1"
, whereasmux.Vars(r)["id"] == "42"
. 😬Reasons why I'm not reporting this as a security vulnerability:
Regarding remediation, you have several possible approaches:
StrictQueryParamSep
) for only using ampersands (as opposed to ampersands and semicolons) as query-param separators. Usefalse
as the default value for the time being. Give gorilla/mux users some time to migrate their clients (to no longer rely on semicolons as a query-param separators). Then, in a subsequent minor version, switch the option's default value totrue
.true
as the option's default value straight away, without any transition period.I think option 4 is safest, but breaking existing clients that rely on this behaviour is a risk; similar remark about option 3. On the other hand, option 1 seems callous. The best compromise may be option 2; I have implemented the latter in my local clone of the project and I'm ready to fire a PR.
The only element that gives me pause is that gorilla/mux lacks a changelog. If we go through with this fix, how are users going to be notified that the new version comes with a behavioural change?
The text was updated successfully, but these errors were encountered: