From 31d6a3cddd18cef447698ba2beaa7b5d9ab9dd94 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Wed, 15 Sep 2021 20:26:02 +0200 Subject: [PATCH] implemented execution depth limit --- src/php_snuffleupagus.h | 1 + src/snuffleupagus.c | 2 ++ src/sp_config.h | 2 ++ src/sp_config_keywords.c | 1 + src/sp_execute.c | 17 +++++++++++++---- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index e11f976c..0c7dc4b8 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h @@ -108,6 +108,7 @@ ZEND_BEGIN_MODULE_GLOBALS(snuffleupagus) size_t in_eval; sp_config config; int is_config_valid; // 1 = valid, 0 = invalid, -1 = none +u_long execution_depth; bool allow_broken_configuration; HashTable *disabled_functions_hook; HashTable *sp_internal_functions_hook; diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index dab5dcaf..d2f81ffd 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -251,6 +251,8 @@ static PHP_GSHUTDOWN_FUNCTION(snuffleupagus) { } PHP_RINIT_FUNCTION(snuffleupagus) { + SNUFFLEUPAGUS_G(execution_depth) = 0; + const sp_config_wrapper *const config_wrapper = SNUFFLEUPAGUS_G(config).config_wrapper; #if defined(COMPILE_DL_SNUFFLEUPAGUS) && defined(ZTS) diff --git a/src/sp_config.h b/src/sp_config.h index fd6dc159..ccf23184 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -196,6 +196,7 @@ typedef struct { sp_config_ini *config_ini; bool hook_execute; char log_media; + u_long max_execution_depth; HashTable *config_disabled_functions; HashTable *config_disabled_functions_hooked; @@ -286,6 +287,7 @@ typedef struct { #define SP_TOKEN_ENCRYPTION_KEY "secret_key" #define SP_TOKEN_ENV_VAR "cookie_env_var" #define SP_TOKEN_LOG_MEDIA "log_media" +#define SP_TOKEN_MAX_EXECUTION_DEPTH "max_execution_depth" // upload_validator #define SP_TOKEN_UPLOAD_SCRIPT "script" diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index 3b6bc0bb..632f9bd0 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -128,6 +128,7 @@ SP_PARSE_FN(parse_global) { {parse_str, SP_TOKEN_ENCRYPTION_KEY, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->encryption_key)}, {parse_str, SP_TOKEN_ENV_VAR, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)}, {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SNUFFLEUPAGUS_G(config).log_media)}, + {parse_ulong, SP_TOKEN_MAX_EXECUTION_DEPTH, &(SNUFFLEUPAGUS_G(config).max_execution_depth)}, {0, 0, 0}}; SP_PROCESS_CONFIG_KEYWORDS_ERR(); diff --git a/src/sp_execute.c b/src/sp_execute.c index 8795e5f6..41257ad1 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -112,6 +112,15 @@ zend_string *get_eval_filename(const char *const filename) { return clean_filename; } +static inline void sp_orig_execute(zend_execute_data *execute_data) { + SNUFFLEUPAGUS_G(execution_depth)++; + if (SNUFFLEUPAGUS_G(execution_depth) > SNUFFLEUPAGUS_G(config).max_execution_depth && SNUFFLEUPAGUS_G(config).max_execution_depth > 0) { + sp_log_drop("execute", "Maximum recursion limit reached. Script terminated."); + } + orig_execute_ex(execute_data); + SNUFFLEUPAGUS_G(execution_depth)--; +} + static void sp_execute_ex(zend_execute_data *execute_data) { is_in_eval_and_whitelisted(execute_data); const HashTable *config_disabled_functions = @@ -131,7 +140,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { zend_string_release(filename); SNUFFLEUPAGUS_G(in_eval)++; - orig_execute_ex(execute_data); + sp_orig_execute(execute_data); SNUFFLEUPAGUS_G(in_eval)--; return; } @@ -150,7 +159,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { .config_disabled_functions_reg->disabled_functions; if (!function_name) { - orig_execute_ex(execute_data); + sp_orig_execute(execute_data); return; } @@ -184,7 +193,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { EX(return_value) = &ret_val; } - orig_execute_ex(execute_data); + sp_orig_execute(execute_data); should_drop_on_ret_ht( EX(return_value), function_name, @@ -197,7 +206,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { EX(return_value) = NULL; } } else { - orig_execute_ex(execute_data); + sp_orig_execute(execute_data); } }