-
Notifications
You must be signed in to change notification settings - Fork 5.3k
http filter: add CSRF filter #6470
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
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
2181c8f
add csrf filter
4b38d65
add csrf and csrfpolicy to spelling dict
6c82dc8
fix doc warning
02fe24d
move csrf to use per_route_config
da0f9f7
update doc links
cb323b1
updates from feedback
08cb1fd
test fixes
31b0328
change test expects and comparison types
aad1f0a
use auto for header entry
1f2b4b6
refactor tests
372f6ee
fix asan and tsan errors
83a96bd
feedback updates
2ee011a
Merge branch 'master' into xsrf-filter
935c7f2
move stats and policy functions into anonymous namespace
0a581ca
fix format
c321cb2
change modifyMethod function name and remove string_view as references
54533c1
update documentation on source origin
7cb713c
add real life example to documentation
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| load("@envoy_api//bazel:api_build_system.bzl", "api_proto_library_internal") | ||
|
|
||
| licenses(["notice"]) # Apache 2 | ||
|
|
||
| api_proto_library_internal( | ||
| name = "csrf", | ||
| srcs = ["csrf.proto"], | ||
| deps = ["//envoy/api/v2/core:base"], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| syntax = "proto3"; | ||
|
|
||
| package envoy.config.filter.http.csrf.v2; | ||
|
|
||
| option java_outer_classname = "CsrfPolicyProto"; | ||
| option java_multiple_files = true; | ||
| option java_package = "io.envoyproxy.envoy.config.filter.http.csrf.v2"; | ||
| option go_package = "v2"; | ||
|
|
||
| import "envoy/api/v2/core/base.proto"; | ||
|
|
||
| import "validate/validate.proto"; | ||
| import "gogoproto/gogo.proto"; | ||
|
|
||
| // [#protodoc-title: CSRF] | ||
| // Cross-Site Request Forgery :ref:`configuration overview <config_http_filters_csrf>`. | ||
|
|
||
| // CSRF filter config. | ||
| message CsrfPolicy { | ||
| // Specify if CSRF is enabled. | ||
| // | ||
| // More information on how this can be controlled via runtime can be found | ||
| // :ref:`here <csrf-runtime>`. | ||
| // | ||
| // .. note:: | ||
| // | ||
| // This field defaults to 100/:ref:`HUNDRED | ||
| // <envoy_api_enum_type.FractionalPercent.DenominatorType>`. | ||
| envoy.api.v2.core.RuntimeFractionalPercent filter_enabled = 1 | ||
| [(validate.rules).message.required = true]; | ||
|
|
||
| // Specifies that CSRF policies will be evaluated and tracked, but not enforced. | ||
| // This is intended to be used when filter_enabled is off. | ||
| // | ||
| // More information on how this can be controlled via runtime can be found | ||
| // :ref:`here <csrf-runtime>`. | ||
| // | ||
| // .. note:: | ||
| // | ||
| // This field defaults to 100/:ref:`HUNDRED | ||
| // <envoy_api_enum_type.FractionalPercent.DenominatorType>`. | ||
| envoy.api.v2.core.RuntimeFractionalPercent shadow_enabled = 2; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| .. _config_http_filters_csrf: | ||
|
|
||
| CSRF | ||
| ==== | ||
|
|
||
| This is a filter which prevents Cross-Site Request Forgery based on a route or virtual host settings. | ||
| At it's simplest, CSRF is an attack that occurs when a malicious third-party | ||
| exploits a vulnerability that allows them to submit an undesired request on the | ||
| user's behalf. | ||
|
|
||
| A real-life example is cited in section 1 of `Robust Defenses for Cross-Site Request Forgery <https://seclab.stanford.edu/websec/csrf/csrf.pdf>`_: | ||
|
|
||
| "For example, in late 2007 [42], Gmail had a CSRF vulnerability. When a Gmail user visited | ||
| a malicious site, the malicious site could generate a request to Gmail that Gmail treated | ||
| as part of its ongoing session with the victim. In November 2007, a web attacker exploited | ||
| this CSRF vulnerability to inject an email filter into David Airey’s Gmail account [1]." | ||
|
|
||
| There are many ways to mitigate CSRF, some of which have been outlined in the | ||
| `OWASP Prevention Cheat Sheet <https://github.com/OWASP/CheatSheetSeries/blob/5a1044e38778b42a19c6adbb4dfef7a0fb071099/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.md>`_. | ||
| This filter employs a stateless mitigation pattern known as origin verification. | ||
|
|
||
| This pattern relies on two pieces of information used in determining if | ||
| a request originated from the same host. | ||
| * The origin that caused the user agent to issue the request (source origin). | ||
| * The origin that the request is going to (target origin). | ||
|
|
||
| When the filter is evaluating a request, it ensures both pieces of information are present | ||
| and compares their values. If the source origin is missing or the origins do not match | ||
| the request is rejected. | ||
|
|
||
| .. note:: | ||
| Due to differing functionality between browsers this filter will determine | ||
| a request's source origin from the Host header. If that is not present it will | ||
| fall back to the host and port value from the requests Referer header. | ||
|
|
||
|
|
||
| For more information on CSRF please refer to the pages below. | ||
|
|
||
| * https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29 | ||
| * https://seclab.stanford.edu/websec/csrf/csrf.pdf | ||
| * :ref:`v2 API reference <envoy_api_msg_config.filter.http.csrf.v2.CsrfPolicy>` | ||
|
|
||
| .. note:: | ||
|
|
||
| This filter should be configured with the name *envoy.csrf*. | ||
|
|
||
| .. _csrf-runtime: | ||
|
|
||
| Runtime | ||
| ------- | ||
|
|
||
| The CSRF filter supports the following RuntimeFractionalPercent settings: | ||
|
|
||
| filter_enabled | ||
| The % of requests for which the filter is enabled. The default is | ||
| 100/:ref:`HUNDRED <envoy_api_enum_type.FractionalPercent.DenominatorType>`. | ||
|
|
||
| To utilize runtime to enabled/disable the CSRF filter set the | ||
| :ref:`runtime_key <envoy_api_msg_core.runtimefractionalpercent>` | ||
| value of the :ref:`filter_enabled <envoy_api_msg_config.filter.http.csrf.v2.CsrfPolicy>` | ||
| field. | ||
|
|
||
| shadow_enabled | ||
| The % of requests for which the filter is enabled in shadow only mode. Default is 0. | ||
| If present, this will evaluate a request's *Origin* and *Destination* to determine | ||
| if the request is valid but will not enforce any policies. | ||
|
|
||
| To utilize runtime to enabled/disable the CSRF filter's shadow mode set the | ||
| :ref:`runtime_key <envoy_api_msg_core.runtimefractionalpercent>` | ||
| value of the :ref:`shadow_enabled <envoy_api_msg_config.filter.http.csrf.v2.CsrfPolicy>` | ||
| field. | ||
|
|
||
| To determine if the filter and/or shadow mode are enabled you can check the runtime | ||
| values via the admin panel at :http:get:`/runtime`. | ||
|
|
||
| .. note:: | ||
|
|
||
| If both ``filter_enabled`` and ``shadow_enabled`` are on, the ``filter_enabled`` | ||
| flag will take precedence. | ||
|
|
||
| .. _csrf-statistics: | ||
|
|
||
| Statistics | ||
| ---------- | ||
|
|
||
| The CSRF filter outputs statistics in the <stat_prefix>.csrf.* namespace. | ||
|
|
||
| .. csv-table:: | ||
| :header: Name, Type, Description | ||
| :widths: 1, 1, 2 | ||
|
|
||
| missing_source_origin, Counter, Number of requests that are missing a source origin header. | ||
| request_invalid, Counter, Number of requests whose source and target origins do not match. | ||
| request_valid, Counter, Number of requests whose source and target origins match. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ HTTP filters | |
|
|
||
| buffer_filter | ||
| cors_filter | ||
| csrf_filter | ||
| dynamodb_filter | ||
| ext_authz_filter | ||
| fault_filter | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| licenses(["notice"]) # Apache 2 | ||
|
|
||
| # L7 HTTP filter which implements CSRF processing (https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) | ||
| # Public docs: docs/root/configuration/http_filters/csrf_filter.rst | ||
|
|
||
| load( | ||
| "//bazel:envoy_build_system.bzl", | ||
| "envoy_cc_library", | ||
| "envoy_package", | ||
| ) | ||
|
|
||
| envoy_package() | ||
|
|
||
| envoy_cc_library( | ||
| name = "csrf_filter_lib", | ||
| srcs = ["csrf_filter.cc"], | ||
| hdrs = ["csrf_filter.h"], | ||
| deps = [ | ||
| "//include/envoy/http:filter_interface", | ||
| "//source/common/buffer:buffer_lib", | ||
| "//source/common/http:header_map_lib", | ||
| "//source/common/http:headers_lib", | ||
| "//source/common/http:utility_lib", | ||
| "//source/extensions/filters/http:well_known_names", | ||
| "@envoy_api//envoy/config/filter/http/csrf/v2:csrf_cc", | ||
| ], | ||
| ) | ||
|
|
||
| envoy_cc_library( | ||
| name = "config", | ||
| srcs = ["config.cc"], | ||
| hdrs = ["config.h"], | ||
| deps = [ | ||
| "//include/envoy/registry", | ||
| "//source/extensions/filters/http:well_known_names", | ||
| "//source/extensions/filters/http/common:factory_base_lib", | ||
| "//source/extensions/filters/http/csrf:csrf_filter_lib", | ||
| ], | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| #include "extensions/filters/http/csrf/config.h" | ||
|
|
||
| #include "envoy/config/filter/http/csrf/v2/csrf.pb.validate.h" | ||
| #include "envoy/registry/registry.h" | ||
|
|
||
| #include "extensions/filters/http/csrf/csrf_filter.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace HttpFilters { | ||
| namespace Csrf { | ||
|
|
||
| Http::FilterFactoryCb CsrfFilterFactory::createFilterFactoryFromProtoTyped( | ||
| const envoy::config::filter::http::csrf::v2::CsrfPolicy& policy, | ||
| const std::string& stats_prefix, Server::Configuration::FactoryContext& context) { | ||
| CsrfFilterConfigSharedPtr config = | ||
| std::make_shared<CsrfFilterConfig>(policy, stats_prefix, context.scope(), context.runtime()); | ||
| return [config](Http::FilterChainFactoryCallbacks& callbacks) -> void { | ||
| callbacks.addStreamDecoderFilter(std::make_shared<CsrfFilter>(config)); | ||
| }; | ||
| } | ||
|
|
||
| Router::RouteSpecificFilterConfigConstSharedPtr | ||
| CsrfFilterFactory::createRouteSpecificFilterConfigTyped( | ||
| const envoy::config::filter::http::csrf::v2::CsrfPolicy& policy, | ||
| Server::Configuration::FactoryContext& context) { | ||
| return std::make_shared<const Csrf::CsrfPolicy>(policy, context.runtime()); | ||
| } | ||
|
|
||
| /** | ||
| * Static registration for the CSRF filter. @see RegisterFactory. | ||
| */ | ||
| REGISTER_FACTORY(CsrfFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory); | ||
|
|
||
| } // namespace Csrf | ||
| } // namespace HttpFilters | ||
| } // namespace Extensions | ||
| } // namespace Envoy |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| #pragma once | ||
|
|
||
| #include "envoy/config/filter/http/csrf/v2/csrf.pb.h" | ||
| #include "envoy/config/filter/http/csrf/v2/csrf.pb.validate.h" | ||
|
|
||
| #include "extensions/filters/http/common/factory_base.h" | ||
| #include "extensions/filters/http/well_known_names.h" | ||
|
|
||
| namespace Envoy { | ||
| namespace Extensions { | ||
| namespace HttpFilters { | ||
| namespace Csrf { | ||
|
|
||
| /** | ||
| * Config registration for the CSRF filter. @see NamedHttpFilterConfigFactory. | ||
| */ | ||
| class CsrfFilterFactory | ||
| : public Common::FactoryBase<envoy::config::filter::http::csrf::v2::CsrfPolicy> { | ||
| public: | ||
| CsrfFilterFactory() : FactoryBase(HttpFilterNames::get().Csrf) {} | ||
|
|
||
| private: | ||
| Http::FilterFactoryCb | ||
| createFilterFactoryFromProtoTyped(const envoy::config::filter::http::csrf::v2::CsrfPolicy& policy, | ||
| const std::string& stats_prefix, | ||
| Server::Configuration::FactoryContext& context) override; | ||
| Router::RouteSpecificFilterConfigConstSharedPtr createRouteSpecificFilterConfigTyped( | ||
| const envoy::config::filter::http::csrf::v2::CsrfPolicy& policy, | ||
| Server::Configuration::FactoryContext& context) override; | ||
| }; | ||
|
|
||
| } // namespace Csrf | ||
| } // namespace HttpFilters | ||
| } // namespace Extensions | ||
| } // namespace Envoy |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.