From 8f459a139bd80d371c275b756a57c64d8f6a3d15 Mon Sep 17 00:00:00 2001 From: Daniel-Eisenberg <59121493+Daniel-Eisenberg@users.noreply.github.com> Date: Wed, 11 Jun 2025 11:35:13 +0300 Subject: [PATCH] add waf tag changes to openappsec (#35) Co-authored-by: wiaamm --- .../nginx/ngx_module/ngx_cp_hook_threads.c | 6 ++- .../nginx/ngx_module/ngx_cp_hook_threads.h | 1 + attachments/nginx/ngx_module/ngx_cp_hooks.c | 9 ++++ attachments/nginx/ngx_module/ngx_cp_io.c | 45 ++++++++++++++++++- attachments/nginx/ngx_module/ngx_cp_io.h | 4 +- .../ngx_http_cp_attachment_module.c | 15 ++++--- .../ngx_http_cp_attachment_module.h | 7 +++ 7 files changed, 78 insertions(+), 9 deletions(-) diff --git a/attachments/nginx/ngx_module/ngx_cp_hook_threads.c b/attachments/nginx/ngx_module/ngx_cp_hook_threads.c index 8f332fe..6cfb03c 100644 --- a/attachments/nginx/ngx_module/ngx_cp_hook_threads.c +++ b/attachments/nginx/ngx_module/ngx_cp_hook_threads.c @@ -223,7 +223,8 @@ ngx_http_cp_req_header_handler_thread(void *_ctx) &(request->headers_in.headers.part), REQUEST_HEADER, session_data_p->session_id, - &num_messages_sent + &num_messages_sent, + &ctx->waf_tag ); if (send_header_result != NGX_OK) { write_dbg( @@ -412,7 +413,8 @@ ngx_http_cp_res_header_filter_thread(void *_ctx) &request->headers_out.headers.part, RESPONSE_HEADER, session_data_p->session_id, - &num_messages_sent + &num_messages_sent, + &ctx->waf_tag ); if (send_header_result != NGX_OK) { write_dbg( diff --git a/attachments/nginx/ngx_module/ngx_cp_hook_threads.h b/attachments/nginx/ngx_module/ngx_cp_hook_threads.h index 2c29df1..5043ffc 100644 --- a/attachments/nginx/ngx_module/ngx_cp_hook_threads.h +++ b/attachments/nginx/ngx_module/ngx_cp_hook_threads.h @@ -44,6 +44,7 @@ struct ngx_http_cp_event_thread_ctx_t int should_return_next_filter; ngx_http_cp_modification_list *modifications; ///< Context's modification. + ngx_str_t waf_tag; ///< WAF tag value for the location block. }; /// diff --git a/attachments/nginx/ngx_module/ngx_cp_hooks.c b/attachments/nginx/ngx_module/ngx_cp_hooks.c index 9141f3d..2ecca65 100644 --- a/attachments/nginx/ngx_module/ngx_cp_hooks.c +++ b/attachments/nginx/ngx_module/ngx_cp_hooks.c @@ -407,9 +407,11 @@ ngx_http_cp_req_header_handler(ngx_http_request_t *request) ngx_http_cp_session_data *session_data_p; ngx_int_t handle_static_resource_result; ngx_http_cp_verdict_e sessions_per_minute_verdict; + ngx_cp_attachment_conf_t *conf; struct ngx_http_cp_event_thread_ctx_t ctx; struct timespec hook_time_begin; int res; + static int is_failure_state_initialized = 0; static int is_metric_data_initialized = 0; @@ -439,6 +441,12 @@ ngx_http_cp_req_header_handler(ngx_http_request_t *request) return NGX_DECLINED; } + conf = ngx_http_get_module_loc_conf(request, ngx_http_cp_attachment_module); + if (conf == NULL) { + write_dbg(DBG_LEVEL_WARNING, "Failed to get module configuration"); + return NGX_DECLINED; + } + session_data_p = init_cp_session_data(request); if (session_data_p == NULL) return NGX_DECLINED; @@ -446,6 +454,7 @@ ngx_http_cp_req_header_handler(ngx_http_request_t *request) write_dbg(DBG_LEVEL_DEBUG, "Request header filter handling session ID: %d", session_data_p->session_id); init_thread_ctx(&ctx, request, session_data_p, NULL); + ctx.waf_tag = conf->waf_tag; sessions_per_minute_verdict = enforce_sessions_rate(); if (sessions_per_minute_verdict != TRAFFIC_VERDICT_INSPECT) { diff --git a/attachments/nginx/ngx_module/ngx_cp_io.c b/attachments/nginx/ngx_module/ngx_cp_io.c index cc0bc3b..55e3003 100644 --- a/attachments/nginx/ngx_module/ngx_cp_io.c +++ b/attachments/nginx/ngx_module/ngx_cp_io.c @@ -1008,7 +1008,8 @@ ngx_http_cp_header_sender( ngx_list_part_t *headers_list, ngx_http_chunk_type_e header_type, uint32_t cur_request_id, - ngx_uint_t *num_messages_sent + ngx_uint_t *num_messages_sent, + ngx_str_t *waf_tag ) { ngx_uint_t header_idx = 0; @@ -1024,6 +1025,7 @@ ngx_http_cp_header_sender( const ngx_uint_t max_bulk_size = 10; char *fragments[HEADER_DATA_COUNT * max_bulk_size + 4]; uint16_t fragments_sizes[HEADER_DATA_COUNT * max_bulk_size + 4]; + ngx_flag_t waf_tag_found = 0; write_dbg( DBG_LEVEL_TRACE, @@ -1034,6 +1036,38 @@ ngx_http_cp_header_sender( // Sets fragments identifier to the provided body type. set_fragments_identifiers(fragments, fragments_sizes, (uint16_t *)&header_type, &cur_request_id); + // If waf_tag is provided and valid, check for existing x-waf-tag headers + if (waf_tag != NULL && waf_tag->len > 0) { + for (headers_iter = headers_list; headers_iter; headers_iter = headers_iter->next) { + headers_to_inspect = headers_iter->elts; + for (header_idx = 0; header_idx < headers_iter->nelts; ++header_idx) { + header = headers_to_inspect + header_idx; + if (header->key.len == 9 && ngx_strncasecmp(header->key.data, (u_char *)"x-waf-tag", 9) == 0) { + // Found existing x-waf-tag header, override its value + // header->value = *waf_tag; + waf_tag_found = 1; + write_dbg(DBG_LEVEL_DEBUG, "Overriding existing x-waf-tag header with value: %.*s", waf_tag->len, waf_tag->data); + break; + } + } + if (waf_tag_found) break; + } + + // If no existing x-waf-tag header found, add a new one + if (!waf_tag_found) { + ngx_table_elt_t waf_header; + waf_header.hash = 1; + ngx_str_set(&waf_header.key, "x-waf-tag"); + waf_header.value = *waf_tag; + waf_header.lowcase_key = NULL; // Not needed for sending to agent + + add_header_to_bulk(fragments, fragments_sizes, &waf_header, idx_in_bulk); + idx_in_bulk++; + part_count++; + write_dbg(DBG_LEVEL_DEBUG, "Adding new x-waf-tag header with value: %.*s", waf_tag->len, waf_tag->data); + } + } + for (headers_iter = headers_list; headers_iter ; headers_iter = headers_iter->next) { // Going over the header list. for (header_idx = 0 ; header_idx < headers_iter->nelts ; ++header_idx) { @@ -1051,7 +1085,16 @@ ngx_http_cp_header_sender( is_last_part = (headers_iter->next == NULL && header_idx + 1 == headers_iter->nelts) ? 1 : 0; // Create a header bulk to send. + if (waf_tag_found && header->key.len == 9 && ngx_strncasecmp(header->key.data, (u_char *)"x-waf-tag", 9) == 0) { + ngx_table_elt_t waf_header; + waf_header.hash = 1; + ngx_str_set(&waf_header.key, "x-waf-tag"); + waf_header.value = *waf_tag; + waf_header.lowcase_key = NULL; + add_header_to_bulk(fragments, fragments_sizes, &waf_header, idx_in_bulk); + } else { add_header_to_bulk(fragments, fragments_sizes, header, idx_in_bulk); + } idx_in_bulk++; part_count++; diff --git a/attachments/nginx/ngx_module/ngx_cp_io.h b/attachments/nginx/ngx_module/ngx_cp_io.h index 6a0ef17..071bf30 100644 --- a/attachments/nginx/ngx_module/ngx_cp_io.h +++ b/attachments/nginx/ngx_module/ngx_cp_io.h @@ -138,6 +138,7 @@ ngx_http_cp_content_length_sender( /// - #RESPONSE_HEADER /// @param[in] cur_request_id Request session's Id. /// @param[in, out] num_messages_sent Number of messages sent will be saved onto this parameter. +/// @param[in, out] waf_tag WAF tag to be sent. /// @returns ngx_int_t /// - #NGX_OK /// - #NGX_ERROR @@ -147,7 +148,8 @@ ngx_http_cp_header_sender( ngx_list_part_t *headers, ngx_http_chunk_type_e header_type, uint32_t cur_request_id, - ngx_uint_t *num_messages_sent + ngx_uint_t *num_messages_sent, + ngx_str_t *waf_tag ); /// diff --git a/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.c b/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.c index 7fc2083..a4256da 100644 --- a/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.c +++ b/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.c @@ -26,11 +26,6 @@ #include "nginx_attachment_common.h" extern ngx_uint_t current_config_version; ///< NGINX configuration version. -typedef struct { - ngx_flag_t enable; ///< Flags if the configuration enabled. - ngx_int_t num_of_workers; ///< Number of workers. - ngx_uint_t current_loc_config_version; ///< NGINX configuration version. -} ngx_cp_attachment_conf_t; /// /// @brief Creates NGINX cp attachment configuration. @@ -120,6 +115,14 @@ static ngx_command_t ngx_cp_attachment_commands[] = { offsetof(ngx_cp_attachment_conf_t, num_of_workers), NULL }, + { + ngx_string("waf_tag"), + NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_cp_attachment_conf_t, waf_tag), + NULL + }, ngx_null_command }; @@ -210,6 +213,7 @@ ngx_cp_attachment_create_conf(ngx_conf_t *conf) module_conf->enable = NGX_CONF_UNSET; module_conf->num_of_workers = 0; module_conf->current_loc_config_version = current_config_version; + ngx_str_null(&module_conf->waf_tag); write_dbg(DBG_LEVEL_TRACE, "Successfully created attachment module configuration"); return module_conf; } @@ -270,6 +274,7 @@ ngx_cp_attachment_merge_conf(ngx_conf_t *configure, void *curr, void *next) ngx_conf_merge_value(conf->enable, prev->enable, NGX_CONF_UNSET); ngx_conf_merge_value(conf->num_of_workers, prev->num_of_workers, ngx_ncpu); + ngx_conf_merge_str_value(conf->waf_tag, prev->waf_tag, ""); write_dbg(DBG_LEVEL_TRACE, "Successfully set attachment module configuration in nginx configuration chain"); return NGX_CONF_OK; diff --git a/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.h b/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.h index 9e85b9e..c3418f8 100644 --- a/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.h +++ b/attachments/nginx/ngx_module/ngx_http_cp_attachment_module.h @@ -27,6 +27,13 @@ extern ngx_http_output_body_filter_pt ngx_http_next_response_body_filter; ///< N extern ngx_module_t ngx_http_cp_attachment_module; ///< NGINX Module. +typedef struct { + ngx_flag_t enable; ///< Flags if the configuration enabled. + ngx_int_t num_of_workers; ///< Number of workers. + ngx_uint_t current_loc_config_version; ///< NGINX configuration version. + ngx_str_t waf_tag; ///< WAF tag value for the location block. +} ngx_cp_attachment_conf_t; + /// /// @brief Returns if NGINX CP attachment is disabled. /// @param[in] request NGINX request.