From 04eeec09e9ad0dbfce8627db5d7602af88242c1e Mon Sep 17 00:00:00 2001 From: Raphael Kiefmann Date: Tue, 3 Jun 2025 10:52:28 +0200 Subject: [PATCH 1/2] initial commit to skip the body inspection --- README.md | 56 +++++++++++++++++++++++++- src/ngx_http_modsecurity_body_filter.c | 19 +++++++-- src/ngx_http_modsecurity_common.h | 2 + src/ngx_http_modsecurity_module.c | 20 +++++++++ src/ngx_http_modsecurity_pre_access.c | 7 ++++ 5 files changed, 99 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d638a0c..c73df3b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Further information about nginx third-party add-ons support are available [here] # Usage ModSecurity for nginx extends your nginx configuration directives. -It adds four new directives and they are: +It adds six new directives and they are: modsecurity ----------- @@ -175,6 +175,60 @@ using the same unique identificator. String can contain variables. +modsecurity_skip_req_body_filter +----------------- +**syntax:** *modsecurity_skip_req_body_filter on | off* + +**context:** *http, server, location* + +**default:** *off* + +Allows to skip the caching of the request body and subsequently its inspection. +Useful in cases, where `SecRequestBodyAccess` or `ctl:requestBodyAccess` is set, due to, e.g. encrypted data, as the caching causes an unneeded memory overhead. + + +```nginx +server { + modsecurity on; + modsecurity_rules_file /etc/my_modsecurity_rules.conf; + + location / { + root /var/www/html; + } + + location = /special/unchecked/path { + # skip the inspection of the request body + modsecurity_skip_req_body_filter on; + } +} +``` + +modsecurity_skip_res_body_filter +----------------- +**syntax:** *modsecurity_skip_res_body_filter on | off* + +**context:** *http, server, location* + +**default:** *off* + +Allows to skip the caching of the request body and subsequently its inspection. +Useful in cases, where `SecResponseBodyAccess` is set, due to, e.g. encrypted data, as the caching causes an unneeded memory overhead. + +```nginx +server { + modsecurity on; + modsecurity_rules_file /etc/my_modsecurity_rules.conf; + + location / { + root /var/www/html; + } + + location = /special/unchecked/path { + # skip the inspection of the response body + modsecurity_skip_res_body_filter on; + } +} +``` # Contributing diff --git a/src/ngx_http_modsecurity_body_filter.c b/src/ngx_http_modsecurity_body_filter.c index 0c28e3c..6231bf1 100644 --- a/src/ngx_http_modsecurity_body_filter.c +++ b/src/ngx_http_modsecurity_body_filter.c @@ -39,8 +39,8 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_chain_t *chain = in; ngx_http_modsecurity_ctx_t *ctx = NULL; + ngx_http_modsecurity_conf_t *mcf = NULL; #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - ngx_http_modsecurity_conf_t *mcf; ngx_list_part_t *part = &r->headers_out.headers.part; ngx_table_elt_t *data = part->elts; ngx_uint_t i = 0; @@ -50,7 +50,19 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return ngx_http_next_body_filter(r, in); } - ctx = ngx_http_modsecurity_get_module_ctx(r); + mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module); + + if (mcf == NULL){ + dd("failed to get configuration"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (mcf->skip_res_body_filter) { + dd("Skipping response body filter"); + return ngx_http_next_body_filter(r, in); + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity_module); dd("body filter, recovering ctx: %p", ctx); @@ -63,8 +75,7 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) } #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) - mcf = ngx_http_get_module_loc_conf(r, ngx_http_modsecurity_module); - if (mcf != NULL && mcf->sanity_checks_enabled != NGX_CONF_UNSET) + if (mcf->sanity_checks_enabled != NGX_CONF_UNSET) { #if 0 dd("dumping stored ctx headers"); diff --git a/src/ngx_http_modsecurity_common.h b/src/ngx_http_modsecurity_common.h index a4687e8..15f7e5d 100644 --- a/src/ngx_http_modsecurity_common.h +++ b/src/ngx_http_modsecurity_common.h @@ -123,6 +123,8 @@ typedef struct { #endif ngx_http_complex_value_t *transaction_id; + ngx_flag_t skip_req_body_filter; + ngx_flag_t skip_res_body_filter; } ngx_http_modsecurity_conf_t; diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index e8a5f4b..60e828c 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -513,6 +513,22 @@ static ngx_command_t ngx_http_modsecurity_commands[] = { 0, NULL }, + { + ngx_string("modsecurity_skip_req_body_filter"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, skip_req_body_filter), + NULL + }, + { + ngx_string("modsecurity_skip_res_body_filter"), + NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_modsecurity_conf_t, skip_res_body_filter), + NULL + }, ngx_null_command }; @@ -724,6 +740,8 @@ ngx_http_modsecurity_create_conf(ngx_conf_t *cf) conf->rules_set = msc_create_rules_set(); conf->pool = cf->pool; conf->transaction_id = NGX_CONF_UNSET_PTR; + conf->skip_req_body_filter = NGX_CONF_UNSET; + conf->skip_res_body_filter = NGX_CONF_UNSET; #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) conf->sanity_checks_enabled = NGX_CONF_UNSET; #endif @@ -763,6 +781,8 @@ ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(c->enable, p->enable, 0); ngx_conf_merge_ptr_value(c->transaction_id, p->transaction_id, NULL); + ngx_conf_merge_value(c->skip_req_body_filter, p->skip_req_body_filter, 0); + ngx_conf_merge_value(c->skip_res_body_filter, p->skip_res_body_filter, 0); #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) ngx_conf_merge_value(c->sanity_checks_enabled, p->sanity_checks_enabled, 0); #endif diff --git a/src/ngx_http_modsecurity_pre_access.c b/src/ngx_http_modsecurity_pre_access.c index 75ac45d..8de522d 100644 --- a/src/ngx_http_modsecurity_pre_access.c +++ b/src/ngx_http_modsecurity_pre_access.c @@ -58,6 +58,13 @@ ngx_http_modsecurity_pre_access_handler(ngx_http_request_t *r) dd("ModSecurity not enabled... returning"); return NGX_DECLINED; } + + if(mcf->skip_req_body_filter == 1) + { + dd("Skipping request body filter"); + return NGX_DECLINED; + } + /* * FIXME: * In order to perform some tests, let's accept everything. From 5b6773fc238b63a2bb1aa6c2b55bb70ec2feb72b Mon Sep 17 00:00:00 2001 From: Raphael Kiefmann Date: Mon, 16 Jun 2025 14:43:23 +0200 Subject: [PATCH 2/2] corrected abbreviation used for response --- README.md | 6 +++--- src/ngx_http_modsecurity_body_filter.c | 2 +- src/ngx_http_modsecurity_common.h | 2 +- src/ngx_http_modsecurity_module.c | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c73df3b..ddf548a 100644 --- a/README.md +++ b/README.md @@ -203,9 +203,9 @@ server { } ``` -modsecurity_skip_res_body_filter +modsecurity_skip_resp_body_filter ----------------- -**syntax:** *modsecurity_skip_res_body_filter on | off* +**syntax:** *modsecurity_skip_resp_body_filter on | off* **context:** *http, server, location* @@ -225,7 +225,7 @@ server { location = /special/unchecked/path { # skip the inspection of the response body - modsecurity_skip_res_body_filter on; + modsecurity_skip_resp_body_filter on; } } ``` diff --git a/src/ngx_http_modsecurity_body_filter.c b/src/ngx_http_modsecurity_body_filter.c index 6231bf1..320c77e 100644 --- a/src/ngx_http_modsecurity_body_filter.c +++ b/src/ngx_http_modsecurity_body_filter.c @@ -57,7 +57,7 @@ ngx_http_modsecurity_body_filter(ngx_http_request_t *r, ngx_chain_t *in) return NGX_HTTP_INTERNAL_SERVER_ERROR; } - if (mcf->skip_res_body_filter) { + if (mcf->skip_resp_body_filter) { dd("Skipping response body filter"); return ngx_http_next_body_filter(r, in); } diff --git a/src/ngx_http_modsecurity_common.h b/src/ngx_http_modsecurity_common.h index 15f7e5d..54fba46 100644 --- a/src/ngx_http_modsecurity_common.h +++ b/src/ngx_http_modsecurity_common.h @@ -124,7 +124,7 @@ typedef struct { ngx_http_complex_value_t *transaction_id; ngx_flag_t skip_req_body_filter; - ngx_flag_t skip_res_body_filter; + ngx_flag_t skip_resp_body_filter; } ngx_http_modsecurity_conf_t; diff --git a/src/ngx_http_modsecurity_module.c b/src/ngx_http_modsecurity_module.c index 60e828c..da68519 100644 --- a/src/ngx_http_modsecurity_module.c +++ b/src/ngx_http_modsecurity_module.c @@ -522,11 +522,11 @@ static ngx_command_t ngx_http_modsecurity_commands[] = { NULL }, { - ngx_string("modsecurity_skip_res_body_filter"), + ngx_string("modsecurity_skip_resp_body_filter"), NGX_HTTP_LOC_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_modsecurity_conf_t, skip_res_body_filter), + offsetof(ngx_http_modsecurity_conf_t, skip_resp_body_filter), NULL }, ngx_null_command @@ -741,7 +741,7 @@ ngx_http_modsecurity_create_conf(ngx_conf_t *cf) conf->pool = cf->pool; conf->transaction_id = NGX_CONF_UNSET_PTR; conf->skip_req_body_filter = NGX_CONF_UNSET; - conf->skip_res_body_filter = NGX_CONF_UNSET; + conf->skip_resp_body_filter = NGX_CONF_UNSET; #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) conf->sanity_checks_enabled = NGX_CONF_UNSET; #endif @@ -782,7 +782,7 @@ ngx_http_modsecurity_merge_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_value(c->enable, p->enable, 0); ngx_conf_merge_ptr_value(c->transaction_id, p->transaction_id, NULL); ngx_conf_merge_value(c->skip_req_body_filter, p->skip_req_body_filter, 0); - ngx_conf_merge_value(c->skip_res_body_filter, p->skip_res_body_filter, 0); + ngx_conf_merge_value(c->skip_resp_body_filter, p->skip_resp_body_filter, 0); #if defined(MODSECURITY_SANITY_CHECKS) && (MODSECURITY_SANITY_CHECKS) ngx_conf_merge_value(c->sanity_checks_enabled, p->sanity_checks_enabled, 0); #endif