From 4a45ba42b609d48c8297456d67cc8d955073b567 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Tue, 14 Dec 2021 14:29:43 +0100 Subject: fix: include class name in eval whitelist matching --- src/sp_disabled_functions.c | 17 +++++------------ src/sp_execute.c | 29 +++++++++++------------------ src/sp_utils.c | 15 ++++----------- src/sp_utils.h | 8 +++++--- 4 files changed, 25 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 216f696..1d9c6c7 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -512,19 +512,13 @@ static void hook_functions(HashTable* to_hook_ht, HashTable* hooked_ht) { ZEND_FUNCTION(eval_blacklist_callback) { zif_handler orig_handler; - const char* current_function_name = get_active_function_name(TSRMLS_C); - zend_string* tmp = - zend_string_init(current_function_name, strlen(current_function_name), 0); + char* current_function_name = get_complete_function_path(EG(current_execute_data)); - if (true == check_is_in_eval_whitelist(tmp)) { - zend_string_release(tmp); + if (!current_function_name || true == check_is_in_eval_whitelist(current_function_name)) { goto whitelisted; } - zend_string_release(tmp); if (SPG(in_eval) > 0) { - // zend_string* filename = get_eval_filename(zend_get_executed_filename()); - // const int line_number = zend_get_executed_lineno(TSRMLS_C); const sp_config_eval* config_eval = &(SPCFG(eval)); if (config_eval->dump) { @@ -535,13 +529,12 @@ ZEND_FUNCTION(eval_blacklist_callback) { } else { sp_log_drop("eval", "A call to '%s' was tried in eval. dropping it.", current_function_name); } - // efree(filename); } whitelisted: - orig_handler = zend_hash_str_find_ptr( - SPG(sp_eval_blacklist_functions_hook), current_function_name, - strlen(current_function_name)); + + orig_handler = zend_hash_str_find_ptr(SPG(sp_eval_blacklist_functions_hook), current_function_name, strlen(current_function_name)); + efree(current_function_name); orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); } diff --git a/src/sp_execute.c b/src/sp_execute.c index f540119..0474fc8 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -48,8 +48,7 @@ inline static void is_builtin_matching( should_disable_ht(EG(current_execute_data), function_name, param_value, param_name, SPCFG(disabled_functions_reg).disabled_functions, ht); } -static void ZEND_HOT -is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { +static void ZEND_HOT is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { const sp_config_eval *config_eval = &(SPCFG(eval)); if (EXPECTED(0 == SPG(in_eval))) { @@ -60,35 +59,29 @@ is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { return; } - if (zend_is_executing() && !EG(current_execute_data)->func) { + if (zend_is_executing() && !EX(func)) { return; // LCOV_EXCL_LINE } - if (UNEXPECTED(!(execute_data->func->common.function_name))) { + char *function_name = get_complete_function_path(execute_data); + if (!function_name) { return; } - zend_string const *const current_function = EX(func)->common.function_name; - - if (EXPECTED(NULL != current_function)) { - if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { + if (UNEXPECTED(false == check_is_in_eval_whitelist(function_name))) { if (config_eval->dump) { sp_log_request(config_eval->dump, config_eval->textual_representation); } if (config_eval->simulation) { - sp_log_simulation( - "Eval_whitelist", - "The function '%s' isn't in the eval whitelist, logging its call.", - ZSTR_VAL(current_function)); - return; + sp_log_simulation("Eval_whitelist", "The function '%s' isn't in the eval whitelist, logging its call.", function_name); + goto out; } else { - sp_log_drop( - "Eval_whitelist", - "The function '%s' isn't in the eval whitelist, dropping its call.", - ZSTR_VAL(current_function)); + sp_log_drop("Eval_whitelist", "The function '%s' isn't in the eval whitelist, dropping its call.", function_name); } } - } + // } +out: + efree(function_name); } /* This function gets the filename in which `eval()` is called from, diff --git a/src/sp_utils.c b/src/sp_utils.c index b53ddcb..034aaf4 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -1,12 +1,5 @@ #include "php_snuffleupagus.h" -bool sp_zend_string_equals(const zend_string* s1, const zend_string* s2) { - // We can't use `zend_string_equals` here because it doesn't work on - // `const` zend_string. - return ZSTR_LEN(s1) == ZSTR_LEN(s2) && - !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); -} - static const char* default_ipaddr = "0.0.0.0"; const char* get_ipaddr() { const char* client_ip = getenv("REMOTE_ADDR"); @@ -155,8 +148,8 @@ int sp_log_request(const zend_string* restrict folder, const zend_string* restri char* const complete_path_function = get_complete_function_path(current); if (complete_path_function) { const int current_line = zend_get_executed_lineno(TSRMLS_C); - fprintf(file, "STACKTRACE: %s:%d\n", complete_path_function, - current_line); + fprintf(file, "STACKTRACE: %s:%d\n", complete_path_function, current_line); + efree(complete_path_function); } current = current->prev_execute_data; } @@ -468,7 +461,7 @@ void unhook_functions(HashTable *ht) { ZEND_HASH_FOREACH_END_DEL(); } -bool check_is_in_eval_whitelist(const zend_string* const function_name) { +bool check_is_in_eval_whitelist(const char* function_name) { const sp_list_node* it = SPCFG(eval).whitelist; if (!it) { return false; @@ -477,7 +470,7 @@ bool check_is_in_eval_whitelist(const zend_string* const function_name) { /* yes, we could use a HashTable instead, but since the list is pretty * small, it doesn't make a difference in practise. */ while (it && it->data) { - if (sp_zend_string_equals(function_name, (const zend_string*)(it->data))) { + if (sp_zend_string_equals_str((const zend_string*)(it->data), VAR_AND_LEN(function_name))) { /* We've got a match, the function is whiteslited. */ return true; } diff --git a/src/sp_utils.h b/src/sp_utils.h index a4694f2..0581363 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h @@ -85,8 +85,10 @@ void sp_log_disable_ret(const char *restrict, const zend_string *restrict, bool hook_function(const char *, HashTable *, zif_handler); void unhook_functions(HashTable *ht); int hook_regexp(const sp_pcre *, HashTable *, zif_handler); -bool check_is_in_eval_whitelist(const zend_string *const function_name); +bool check_is_in_eval_whitelist(const char* function_name); int sp_log_request(const zend_string *restrict folder, const zend_string *restrict text_repr); -bool sp_zend_string_equals(const zend_string *s1, const zend_string *s2); - +#define sp_zend_string_equals(s1, s2) zend_string_equals((zend_string*)s1, (zend_string*)s2) +static inline bool sp_zend_string_equals_str(const zend_string* s1, const char *str, size_t len) { + return (ZSTR_LEN(s1) == len && !memcmp(ZSTR_VAL(s1), str, len)); +} #endif /* SP_UTILS_H */ -- cgit v1.3