From 5341ccda9e580af22fe06d86cd1ced8f889733c8 Mon Sep 17 00:00:00 2001 From: ADD-SP Date: Sun, 6 Feb 2022 22:35:24 +0800 Subject: [PATCH] :bug: About directives `waf_captcha` and `waf_action`. When the `action` is CAPTCHA, the parameter `cookie_secret` does not work. I've had a lot to drink, and I don't know if there's anything wrong with this commit. --- inc/ngx_http_waf_module_type.h | 1 + src/ngx_http_waf_module_action.c | 161 +++--------------------------- src/ngx_http_waf_module_captcha.c | 3 +- src/ngx_http_waf_module_core.c | 1 + 4 files changed, 20 insertions(+), 146 deletions(-) diff --git a/inc/ngx_http_waf_module_type.h b/inc/ngx_http_waf_module_type.h index 174abc44..6a2f9b24 100644 --- a/inc/ngx_http_waf_module_type.h +++ b/inc/ngx_http_waf_module_type.h @@ -331,6 +331,7 @@ typedef struct ngx_http_waf_ctx_s { ngx_uint_t has_req_body:1; /**< 字段 req_body 是否以己经存储了请求体 */ ngx_uint_t register_content_handler:1; /**< 是否已经注册或应该注册内容处理程序 */ ngx_uint_t skip_sysguard:1; /**< 是否跳过系统监控 */ + ngx_uint_t invoke_captcha:1; /**< 是否忽略配置并强制开启 CAPTCHA(仅限本次请求) */ } ngx_http_waf_ctx_t; diff --git a/src/ngx_http_waf_module_action.c b/src/ngx_http_waf_module_action.c index 60c397dd..e767c713 100644 --- a/src/ngx_http_waf_module_action.c +++ b/src/ngx_http_waf_module_action.c @@ -3,8 +3,9 @@ typedef struct _captcha_cache_s { action_flag_e flag; - ngx_uint_t captcha_pass:1; /**< 1: 验证码通过,0: 验证码未通过 */ - ngx_uint_t error_page:1; /**< 1: 返回 403, 0: CAPTCHA */ + ngx_uint_t skip_sysguard:1; /**< 1: 验证码通过,0: 验证码未通过 */ + ngx_uint_t invoke_captcha:1; /**< 1: 需要调用 CAPTCHA,0: 不需要调用 CAPTCHA */ + ngx_uint_t error_page:1; /**< 1: 返回 403, 0: CAPTCHA */ } _captcha_cache_t; @@ -56,7 +57,8 @@ ngx_int_t ngx_http_waf_perform_action_at_access_start(ngx_http_request_t* r) { ngx_int_t ret_value = NGX_HTTP_WAF_NOT_MATCHED; action_flag_e action_flag = ACTION_FLAG_NONE; - ngx_uint_t captcha_pass = 0; + ngx_uint_t invoke_captcha = 0; + ngx_uint_t skip_sysguard = 0; ngx_slab_pool_t *shpool = (ngx_slab_pool_t *)loc_conf->action_zone_captcha->shm.addr; ngx_http_waf_dp(r, "locking shared memory"); @@ -69,156 +71,23 @@ ngx_int_t ngx_http_waf_perform_action_at_access_start(ngx_http_request_t* r) { if (result.status == NGX_HTTP_WAF_KEY_EXISTS) { ngx_http_waf_dp(r, "cache found"); _captcha_cache_t* cache_data = *((_captcha_cache_t**)(result.data)); + cache_data->invoke_captcha = 1; action_flag = cache_data->flag; if (ngx_http_waf_is_action_from_sysguard(action_flag)) { - captcha_pass = cache_data->captcha_pass; + cache_data->skip_sysguard = 1; } + + invoke_captcha = cache_data->invoke_captcha; + skip_sysguard = cache_data->skip_sysguard; } ngx_http_waf_dp(r, "unlocking shared memory") ngx_shmtx_unlock(&shpool->mutex); ngx_http_waf_dp(r, "success"); - if (captcha_pass) { - ngx_http_waf_dp(r, "captcha pass"); - - if (ngx_http_waf_is_action_from_sysguard(action_flag)) { - ngx_http_waf_dp(r, "skip sysguard"); - ctx->skip_sysguard = 1; - } - - ngx_http_waf_dp_func_end(r); - return NGX_HTTP_WAF_NOT_MATCHED; - } - - if (result.status == NGX_HTTP_WAF_KEY_EXISTS) { - ngx_http_waf_dp(r, "cache exists"); - - ngx_http_waf_dp(r, "testing captcha") - switch (ngx_http_waf_captcha_test(r)) { - case NGX_HTTP_WAF_FAULT: - ngx_http_waf_dp(r, "fault"); - ngx_http_waf_append_action_return(r, NGX_HTTP_SERVICE_UNAVAILABLE, ACTION_FLAG_NONE); - ret_value = NGX_HTTP_WAF_MATCHED; - break; - - case NGX_HTTP_WAF_CAPTCHA_CHALLENGE: - ngx_http_waf_dp(r, "challenge"); - - if (ngx_http_waf_captcha_inc_fails(r) == NGX_HTTP_WAF_MATCHED) { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "TO MANY FAILS", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - - if (ngx_is_null_str(&loc_conf->waf_block_page)) { - ngx_http_waf_append_action_return(r, NGX_HTTP_TOO_MANY_REQUESTS, ACTION_FLAG_FROM_CAPTCHA); - - } else { - ngx_http_waf_append_action_html(r, - &loc_conf->waf_block_page, - NGX_HTTP_TOO_MANY_REQUESTS, - ACTION_FLAG_FROM_CAPTCHA); - } - - - } else { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "CHALLENGE", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - ngx_http_waf_append_action_captcha(r, ACTION_FLAG_FROM_CAPTCHA); - } - - ret_value = NGX_HTTP_WAF_MATCHED; - break; - - case NGX_HTTP_WAF_CAPTCHA_BAD: - ngx_http_waf_dp(r, "bad"); - - if (ngx_http_waf_captcha_inc_fails(r) == NGX_HTTP_WAF_MATCHED) { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "TO MANY FAILS", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - - if (ngx_is_null_str(&loc_conf->waf_block_page)) { - ngx_http_waf_append_action_return(r, NGX_HTTP_TOO_MANY_REQUESTS, ACTION_FLAG_FROM_CAPTCHA); - - } else { - ngx_http_waf_append_action_html(r, - &loc_conf->waf_block_page, - NGX_HTTP_TOO_MANY_REQUESTS, - ACTION_FLAG_FROM_CAPTCHA); - } - - } else { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "bad", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - ngx_str_t* res_str = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); - ngx_str_set(res_str, "bad"); - ngx_http_waf_append_action_str(r, res_str, NGX_HTTP_OK, ACTION_FLAG_NONE); - } - - ret_value = NGX_HTTP_WAF_MATCHED; - break; - - case NGX_HTTP_WAF_CAPTCHA_PASS: - ngx_http_waf_dp(r, "pass"); - captcha_pass = 1; - ngx_str_t* res_str = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); - ngx_str_set(res_str, "good"); - ngx_http_waf_append_action_str(r, res_str, NGX_HTTP_OK, ACTION_FLAG_NONE); - ret_value = NGX_HTTP_WAF_MATCHED; - break; - - case NGX_HTTP_WAF_FAIL: - ngx_http_waf_dp(r, "fail"); - - if (ngx_http_waf_captcha_inc_fails(r) == NGX_HTTP_WAF_MATCHED) { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "TO MANY FAILS", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - - if (ngx_is_null_str(&loc_conf->waf_block_page)) { - ngx_http_waf_append_action_return(r, NGX_HTTP_TOO_MANY_REQUESTS, ACTION_FLAG_FROM_CAPTCHA); - - } else { - ngx_http_waf_append_action_html(r, - &loc_conf->waf_block_page, - NGX_HTTP_TOO_MANY_REQUESTS, - ACTION_FLAG_FROM_CAPTCHA); - } - - } else { - ngx_http_waf_set_rule_info(r, "CAPTCHA", "CHALLENGE", NGX_HTTP_WAF_TRUE, NGX_HTTP_WAF_TRUE); - ngx_http_waf_append_action_captcha(r, ACTION_FLAG_FROM_CAPTCHA); - } - - ret_value = NGX_HTTP_WAF_MATCHED; - break; - - case NGX_HTTP_WAF_ASYNC: - ngx_http_waf_dp(r, "async"); - ngx_http_waf_append_action_done(r, ACTION_FLAG_FROM_CAPTCHA); - ret_value = NGX_HTTP_WAF_MATCHED; - break; - } - - } else { - ngx_http_waf_dp(r, "cache not exists"); - } - - if (captcha_pass) { - ngx_http_waf_dp(r, "locking shared memory"); - ngx_shmtx_lock(&shpool->mutex); - ngx_http_waf_dp(r, "success"); - - if (ngx_http_waf_is_action_from_sysguard(action_flag)) { - ngx_http_waf_dp(r, "action from sysguard"); - - _captcha_cache_t* cache_data = *((_captcha_cache_t**)(result.data)); - cache_data->captcha_pass = 1; - - } else { - ngx_http_waf_dp(r, "deleting cache"); - lru_cache_delete(cache, &inx_addr, sizeof(inx_addr)); - ngx_http_waf_dp(r, "success"); - } - - ngx_http_waf_dp(r, "unlocking shared memory") - ngx_shmtx_unlock(&shpool->mutex); - ngx_http_waf_dp(r, "success"); - } + ctx->invoke_captcha = invoke_captcha; + ctx->skip_sysguard = skip_sysguard; ngx_http_waf_dp_func_end(r); return ret_value; @@ -410,7 +279,8 @@ static ngx_int_t _perform_action_html(ngx_http_request_t* r, action_t* action) { *result.data = tmp; tmp->flag = action->flag; - tmp->captcha_pass = 0; + tmp->skip_sysguard = 0; + tmp->invoke_captcha = 0; if (!ngx_http_waf_check_flag(action->flag, ACTION_FLAG_FROM_CC_DENY)) { tmp->error_page = 1; @@ -421,8 +291,9 @@ static ngx_int_t _perform_action_html(ngx_http_request_t* r, action_t* action) { _captcha_cache_t* tmp = *result.data; if (!ngx_http_waf_check_flag(action->flag, ACTION_FLAG_FROM_CC_DENY)) { - tmp->captcha_pass = 0; + tmp->skip_sysguard = 0; tmp->error_page = 0; + tmp->invoke_captcha = 0; error_page = tmp->error_page; } diff --git a/src/ngx_http_waf_module_captcha.c b/src/ngx_http_waf_module_captcha.c index 2f177155..4dd14fc1 100644 --- a/src/ngx_http_waf_module_captcha.c +++ b/src/ngx_http_waf_module_captcha.c @@ -64,7 +64,8 @@ ngx_int_t ngx_http_waf_handler_captcha(ngx_http_request_t* r) { ngx_http_waf_loc_conf_t* loc_conf = NULL; ngx_http_waf_get_ctx_and_conf(r, &loc_conf, &ctx); - if (ngx_http_waf_is_unset_or_disable_value(loc_conf->waf_captcha)) { + if (ngx_http_waf_is_unset_or_disable_value(loc_conf->waf_captcha) + && !ctx->invoke_captcha) { ngx_http_waf_dp(r, "nothing to do ... return"); return NGX_HTTP_WAF_NOT_MATCHED; } diff --git a/src/ngx_http_waf_module_core.c b/src/ngx_http_waf_module_core.c index a25cc21d..19efa742 100644 --- a/src/ngx_http_waf_module_core.c +++ b/src/ngx_http_waf_module_core.c @@ -288,6 +288,7 @@ ngx_int_t ngx_http_waf_check_all(ngx_http_request_t* r, ngx_int_t is_check_cc) { ctx->pre_content_run = 0; ctx->handler_index = 0; ctx->skip_sysguard = 0; + ctx->invoke_captcha = 0; #if (NGX_THREADS) ctx->async_captcha = 0;