diff options
| author | Ben Fuhrmannek | 2021-12-14 14:29:43 +0100 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-12-14 14:29:43 +0100 |
| commit | 4a45ba42b609d48c8297456d67cc8d955073b567 (patch) | |
| tree | 947bd03955cd9e8c141f133ab12d3a84bd62611e /src | |
| parent | 1746eb1013af60d8524a42fb3431446a5933a646 (diff) | |
fix: include class name in eval whitelist matching
Diffstat (limited to 'src')
| -rw-r--r-- | src/sp_disabled_functions.c | 17 | ||||
| -rw-r--r-- | src/sp_execute.c | 29 | ||||
| -rw-r--r-- | src/sp_utils.c | 15 | ||||
| -rw-r--r-- | src/sp_utils.h | 8 |
4 files changed, 25 insertions, 44 deletions
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) { | |||
| 512 | 512 | ||
| 513 | ZEND_FUNCTION(eval_blacklist_callback) { | 513 | ZEND_FUNCTION(eval_blacklist_callback) { |
| 514 | zif_handler orig_handler; | 514 | zif_handler orig_handler; |
| 515 | const char* current_function_name = get_active_function_name(TSRMLS_C); | 515 | char* current_function_name = get_complete_function_path(EG(current_execute_data)); |
| 516 | zend_string* tmp = | ||
| 517 | zend_string_init(current_function_name, strlen(current_function_name), 0); | ||
| 518 | 516 | ||
| 519 | if (true == check_is_in_eval_whitelist(tmp)) { | 517 | if (!current_function_name || true == check_is_in_eval_whitelist(current_function_name)) { |
| 520 | zend_string_release(tmp); | ||
| 521 | goto whitelisted; | 518 | goto whitelisted; |
| 522 | } | 519 | } |
| 523 | zend_string_release(tmp); | ||
| 524 | 520 | ||
| 525 | if (SPG(in_eval) > 0) { | 521 | if (SPG(in_eval) > 0) { |
| 526 | // zend_string* filename = get_eval_filename(zend_get_executed_filename()); | ||
| 527 | // const int line_number = zend_get_executed_lineno(TSRMLS_C); | ||
| 528 | const sp_config_eval* config_eval = &(SPCFG(eval)); | 522 | const sp_config_eval* config_eval = &(SPCFG(eval)); |
| 529 | 523 | ||
| 530 | if (config_eval->dump) { | 524 | if (config_eval->dump) { |
| @@ -535,13 +529,12 @@ ZEND_FUNCTION(eval_blacklist_callback) { | |||
| 535 | } else { | 529 | } else { |
| 536 | sp_log_drop("eval", "A call to '%s' was tried in eval. dropping it.", current_function_name); | 530 | sp_log_drop("eval", "A call to '%s' was tried in eval. dropping it.", current_function_name); |
| 537 | } | 531 | } |
| 538 | // efree(filename); | ||
| 539 | } | 532 | } |
| 540 | 533 | ||
| 541 | whitelisted: | 534 | whitelisted: |
| 542 | orig_handler = zend_hash_str_find_ptr( | 535 | |
| 543 | SPG(sp_eval_blacklist_functions_hook), current_function_name, | 536 | orig_handler = zend_hash_str_find_ptr(SPG(sp_eval_blacklist_functions_hook), current_function_name, strlen(current_function_name)); |
| 544 | strlen(current_function_name)); | 537 | efree(current_function_name); |
| 545 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 538 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 546 | } | 539 | } |
| 547 | 540 | ||
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( | |||
| 48 | should_disable_ht(EG(current_execute_data), function_name, param_value, param_name, SPCFG(disabled_functions_reg).disabled_functions, ht); | 48 | should_disable_ht(EG(current_execute_data), function_name, param_value, param_name, SPCFG(disabled_functions_reg).disabled_functions, ht); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static void ZEND_HOT | 51 | static void ZEND_HOT is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { |
| 52 | is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { | ||
| 53 | const sp_config_eval *config_eval = &(SPCFG(eval)); | 52 | const sp_config_eval *config_eval = &(SPCFG(eval)); |
| 54 | 53 | ||
| 55 | if (EXPECTED(0 == SPG(in_eval))) { | 54 | if (EXPECTED(0 == SPG(in_eval))) { |
| @@ -60,35 +59,29 @@ is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { | |||
| 60 | return; | 59 | return; |
| 61 | } | 60 | } |
| 62 | 61 | ||
| 63 | if (zend_is_executing() && !EG(current_execute_data)->func) { | 62 | if (zend_is_executing() && !EX(func)) { |
| 64 | return; // LCOV_EXCL_LINE | 63 | return; // LCOV_EXCL_LINE |
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | if (UNEXPECTED(!(execute_data->func->common.function_name))) { | 66 | char *function_name = get_complete_function_path(execute_data); |
| 67 | if (!function_name) { | ||
| 68 | return; | 68 | return; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | zend_string const *const current_function = EX(func)->common.function_name; | 71 | if (UNEXPECTED(false == check_is_in_eval_whitelist(function_name))) { |
| 72 | |||
| 73 | if (EXPECTED(NULL != current_function)) { | ||
| 74 | if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { | ||
| 75 | if (config_eval->dump) { | 72 | if (config_eval->dump) { |
| 76 | sp_log_request(config_eval->dump, config_eval->textual_representation); | 73 | sp_log_request(config_eval->dump, config_eval->textual_representation); |
| 77 | } | 74 | } |
| 78 | if (config_eval->simulation) { | 75 | if (config_eval->simulation) { |
| 79 | sp_log_simulation( | 76 | sp_log_simulation("Eval_whitelist", "The function '%s' isn't in the eval whitelist, logging its call.", function_name); |
| 80 | "Eval_whitelist", | 77 | goto out; |
| 81 | "The function '%s' isn't in the eval whitelist, logging its call.", | ||
| 82 | ZSTR_VAL(current_function)); | ||
| 83 | return; | ||
| 84 | } else { | 78 | } else { |
| 85 | sp_log_drop( | 79 | sp_log_drop("Eval_whitelist", "The function '%s' isn't in the eval whitelist, dropping its call.", function_name); |
| 86 | "Eval_whitelist", | ||
| 87 | "The function '%s' isn't in the eval whitelist, dropping its call.", | ||
| 88 | ZSTR_VAL(current_function)); | ||
| 89 | } | 80 | } |
| 90 | } | 81 | } |
| 91 | } | 82 | // } |
| 83 | out: | ||
| 84 | efree(function_name); | ||
| 92 | } | 85 | } |
| 93 | 86 | ||
| 94 | /* This function gets the filename in which `eval()` is called from, | 87 | /* 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 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | bool sp_zend_string_equals(const zend_string* s1, const zend_string* s2) { | ||
| 4 | // We can't use `zend_string_equals` here because it doesn't work on | ||
| 5 | // `const` zend_string. | ||
| 6 | return ZSTR_LEN(s1) == ZSTR_LEN(s2) && | ||
| 7 | !memcmp(ZSTR_VAL(s1), ZSTR_VAL(s2), ZSTR_LEN(s1)); | ||
| 8 | } | ||
| 9 | |||
| 10 | static const char* default_ipaddr = "0.0.0.0"; | 3 | static const char* default_ipaddr = "0.0.0.0"; |
| 11 | const char* get_ipaddr() { | 4 | const char* get_ipaddr() { |
| 12 | const char* client_ip = getenv("REMOTE_ADDR"); | 5 | const char* client_ip = getenv("REMOTE_ADDR"); |
| @@ -155,8 +148,8 @@ int sp_log_request(const zend_string* restrict folder, const zend_string* restri | |||
| 155 | char* const complete_path_function = get_complete_function_path(current); | 148 | char* const complete_path_function = get_complete_function_path(current); |
| 156 | if (complete_path_function) { | 149 | if (complete_path_function) { |
| 157 | const int current_line = zend_get_executed_lineno(TSRMLS_C); | 150 | const int current_line = zend_get_executed_lineno(TSRMLS_C); |
| 158 | fprintf(file, "STACKTRACE: %s:%d\n", complete_path_function, | 151 | fprintf(file, "STACKTRACE: %s:%d\n", complete_path_function, current_line); |
| 159 | current_line); | 152 | efree(complete_path_function); |
| 160 | } | 153 | } |
| 161 | current = current->prev_execute_data; | 154 | current = current->prev_execute_data; |
| 162 | } | 155 | } |
| @@ -468,7 +461,7 @@ void unhook_functions(HashTable *ht) { | |||
| 468 | ZEND_HASH_FOREACH_END_DEL(); | 461 | ZEND_HASH_FOREACH_END_DEL(); |
| 469 | } | 462 | } |
| 470 | 463 | ||
| 471 | bool check_is_in_eval_whitelist(const zend_string* const function_name) { | 464 | bool check_is_in_eval_whitelist(const char* function_name) { |
| 472 | const sp_list_node* it = SPCFG(eval).whitelist; | 465 | const sp_list_node* it = SPCFG(eval).whitelist; |
| 473 | if (!it) { | 466 | if (!it) { |
| 474 | return false; | 467 | return false; |
| @@ -477,7 +470,7 @@ bool check_is_in_eval_whitelist(const zend_string* const function_name) { | |||
| 477 | /* yes, we could use a HashTable instead, but since the list is pretty | 470 | /* yes, we could use a HashTable instead, but since the list is pretty |
| 478 | * small, it doesn't make a difference in practise. */ | 471 | * small, it doesn't make a difference in practise. */ |
| 479 | while (it && it->data) { | 472 | while (it && it->data) { |
| 480 | if (sp_zend_string_equals(function_name, (const zend_string*)(it->data))) { | 473 | if (sp_zend_string_equals_str((const zend_string*)(it->data), VAR_AND_LEN(function_name))) { |
| 481 | /* We've got a match, the function is whiteslited. */ | 474 | /* We've got a match, the function is whiteslited. */ |
| 482 | return true; | 475 | return true; |
| 483 | } | 476 | } |
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, | |||
| 85 | bool hook_function(const char *, HashTable *, zif_handler); | 85 | bool hook_function(const char *, HashTable *, zif_handler); |
| 86 | void unhook_functions(HashTable *ht); | 86 | void unhook_functions(HashTable *ht); |
| 87 | int hook_regexp(const sp_pcre *, HashTable *, zif_handler); | 87 | int hook_regexp(const sp_pcre *, HashTable *, zif_handler); |
| 88 | bool check_is_in_eval_whitelist(const zend_string *const function_name); | 88 | bool check_is_in_eval_whitelist(const char* function_name); |
| 89 | int sp_log_request(const zend_string *restrict folder, const zend_string *restrict text_repr); | 89 | int sp_log_request(const zend_string *restrict folder, const zend_string *restrict text_repr); |
| 90 | bool sp_zend_string_equals(const zend_string *s1, const zend_string *s2); | 90 | #define sp_zend_string_equals(s1, s2) zend_string_equals((zend_string*)s1, (zend_string*)s2) |
| 91 | 91 | static inline bool sp_zend_string_equals_str(const zend_string* s1, const char *str, size_t len) { | |
| 92 | return (ZSTR_LEN(s1) == len && !memcmp(ZSTR_VAL(s1), str, len)); | ||
| 93 | } | ||
| 92 | #endif /* SP_UTILS_H */ | 94 | #endif /* SP_UTILS_H */ |
