Skip to content
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

Path normalization controls #6589

Open
htuch opened this issue Apr 15, 2019 · 17 comments
Open

Path normalization controls #6589

htuch opened this issue Apr 15, 2019 · 17 comments

Comments

@htuch
Copy link
Member

htuch commented Apr 15, 2019

The fix for CVE-2019-9900, provided a coarse grained ability to opt-in/out of path normalization. That is, you could either normalize, in which case both normalization was used for matching and transforming the path to the upstream, or not normalize.

Ideally we provide finer grained controls similar to Nginx, where users can opt to normalize for match independent of transforming the path to the upstream.

CC @PiotrSikora

Action item for CVE-2019-9901

@htuch
Copy link
Member Author

htuch commented Jan 21, 2020

Bumping priority, since today we still have normalization disabled by default.

@htuch
Copy link
Member Author

htuch commented Jan 21, 2020

Once we have this, we should ensure that normalization occurs by default.

@twghu
Copy link
Contributor

twghu commented Jan 23, 2020

Looking at this along with #6588

@twghu
Copy link
Contributor

twghu commented Jan 23, 2020

Work on finding a library for normalisation progessed on #6588 seems tied to the solution for this. Will monitor and action pending outcome of same.

@htuch
Copy link
Member Author

htuch commented Jan 24, 2020

@twghu related but not dependent, I think we can add in the controls with the existing PathUtil interface.

@jonnysgomes
Copy link

jonnysgomes commented Feb 21, 2020

Hi @htuch , I'm using Istio and I'm having an issue related with path traversal. The Envoy version is 1.12. Istio brings the normalize path configuration enabled by default, as we can see here. Even with that configuration enabled, I still can navigate through the url path, for instance:

https://my.domain.net/myservice/../otherplace

According with this link, Envoy already has fixed that. I've checked out the normalize_path flag and it's enabled. By my understanding, the url above should be resolved as https://my.domain.net/myservice/. So, Could it be a bad Envoy behavior or am I missing something?

@PiotrSikora
Copy link
Contributor

@jonnysgomes normalized https://my.domain.net/myservice/../otherplace is https://my.domain.net/otherplace, not https://my.domain.net/myservice.

Without normalization, /myservice/../otherplace is matched against /myservice prefix, which is potentially a security issue, since you're really accessing /otherplace.

With normalization, /myservice/../otherplace is matched against /otherplace prefix, which is correct.

@twghu
Copy link
Contributor

twghu commented Apr 29, 2020

Implementation:

Requirements:

  1. All existing behavior will be preserved.
  2. Normalization should occur by default ( following previous comment htuch 22/1 ).
  3. Code changes will be restricted to the upstream connection only with no changes to routing code to eliminate introduction of new security/function bugs.

Changes:

  1. Add a configuration option to HttpConnectionManager normalize_path_for_upstream with default to value of normalize_path (support existing behavior).
  2. Add a new header entry OriginalPathForUpstream, This will default to Path() as per current functionality. If normalize_path_for_upstream is false only then will OriginalPathForUpstream be passed to upstream non-normalized. This allows Envoy the option to use a normalized path from downstream to perform route matching while optionally allowing the non-normalized path to be passed through to upstream. The header entry is not forwarded to upstream and is private to Envoy. The addition of this new entry provides visibility to other internal functionality that may have an interest in the upstream path while minimizing code changes in the code base.
  3. If the normalize_path configuration is false, then no normalization occurs for upstream (support existing behavior) by default. If normalize_path_for_upstream is set to true then the upstream path can be normalized independently.

@htuch
Copy link
Member Author

htuch commented Apr 30, 2020

This seems like a good design to me. @PiotrSikora @mattklein123 thoughts?

You'll need to be careful about dumping OriginalPathForUpstream on the wire by accident, or reaching upstream code with it not set (e.g. from an sync client).

@mattklein123
Copy link
Member

Sorry I'm having a hard time wrapping my head around ^ without seeing it in context with the existing config. Can you potentially do a config/docs only PR and we can discuss the proposal there?

@twghu
Copy link
Contributor

twghu commented May 8, 2020

Hey @mattklein123 See #11111

@howardjohn
Copy link
Contributor

Is this only about path? Or would something like #14491 fall in scope? Essentially allowing the original Host header (with port) to be forwarded while routing without the port internally. The current behavior forwards the modified host header, much like the path normalization

@howardjohn
Copy link
Contributor

Another similar question as above: Is header case normalization in scope? I can open a new issue if its both desired and out of scope. istio/istio#30579 for reference

@htuch
Copy link
Member Author

htuch commented Feb 3, 2021

I think #8463 is tracking this one @howardjohn.

@asraa
Copy link
Contributor

asraa commented Feb 26, 2021

For observability, if we split this path we may want to default log the original path (that contains the most information, normalized paths can be recovered from the original). We should add formatters like %UPSTREAM_PATH% or %NORMALIZED_PATH% in case users want a way to view the upstream or internal normalization for matching.

@htuch
Copy link
Member Author

htuch commented Feb 26, 2021

Yes, I think original path should be default as anyone doing audit logging will want to see that.

@wrowe
Copy link
Contributor

wrowe commented Sep 27, 2021

For observability, if we split this path we may want to default log the original path (that contains the most information, normalized paths can be recovered from the original). We should add formatters like %UPSTREAM_PATH% or %NORMALIZED_PATH% in case users want a way to view the upstream or internal normalization for matching.

I was considering this upstream as well. While there is always a risk passing on an unsanitized, unnormalized URI, there might be security applications which want to know the original URI. It would make sense to be able to pass these as an x-original-uri header field (with appropriate header value quoting and escaping, obviously.)

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

No branches or pull requests

9 participants