diff options
| author | jvoisin | 2017-11-29 11:36:57 +0100 |
|---|---|---|
| committer | GitHub | 2017-11-29 11:36:57 +0100 |
| commit | 10437787b0e8ede80976de4a1c22775fc1282f36 (patch) | |
| tree | 1ab911ab000989b98449475eda655a797e278049 | |
| parent | 8df77884f38e7a7334b56aafe2f441567f175af8 (diff) | |
Implement eval hooking
It's not possible to hook the `eval` builtin like other functions.
| -rw-r--r-- | src/snuffleupagus.c | 2 | ||||
| -rw-r--r-- | src/sp_config.h | 1 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 6 | ||||
| -rw-r--r-- | src/sp_disabled_functions.c | 153 | ||||
| -rw-r--r-- | src/sp_disabled_functions.h | 2 | ||||
| -rw-r--r-- | src/sp_execute.c | 79 | ||||
| -rw-r--r-- | src/sp_execute.h | 1 | ||||
| -rw-r--r-- | src/sp_utils.c | 2 | ||||
| -rw-r--r-- | src/tests/config/config_disabled_functions_eval_filename.ini | 1 | ||||
| -rw-r--r-- | src/tests/config/disabled_functions.ini | 1 | ||||
| -rw-r--r-- | src/tests/config/disabled_functions_eval.ini | 1 | ||||
| -rw-r--r-- | src/tests/config/disabled_functions_eval_simulation.ini | 1 | ||||
| -rw-r--r-- | src/tests/deny_writable_execution.phpt | 5 | ||||
| -rw-r--r-- | src/tests/disabled_functions_eval.phpt | 9 | ||||
| -rw-r--r-- | src/tests/disabled_functions_eval_filename.phpt | 14 | ||||
| -rw-r--r-- | src/tests/disabled_functions_eval_simulation.phpt | 15 | ||||
| -rw-r--r-- | src/tests/disabled_functions_require.phpt | 2 | ||||
| -rw-r--r-- | src/tests/disabled_functions_require_simulation.phpt | 2 |
18 files changed, 203 insertions, 94 deletions
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index 9467a5d..bf18588 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -75,6 +75,7 @@ PHP_GINIT_FUNCTION(snuffleupagus) { | |||
| 75 | SP_INIT(snuffleupagus_globals->config.config_disabled_constructs); | 75 | SP_INIT(snuffleupagus_globals->config.config_disabled_constructs); |
| 76 | 76 | ||
| 77 | snuffleupagus_globals->config.config_disabled_constructs->construct_include = sp_list_new(); | 77 | snuffleupagus_globals->config.config_disabled_constructs->construct_include = sp_list_new(); |
| 78 | snuffleupagus_globals->config.config_disabled_constructs->construct_eval = sp_list_new(); | ||
| 78 | snuffleupagus_globals->config.config_disabled_functions->disabled_functions = sp_list_new(); | 79 | snuffleupagus_globals->config.config_disabled_functions->disabled_functions = sp_list_new(); |
| 79 | snuffleupagus_globals->config.config_disabled_functions_ret->disabled_functions = sp_list_new(); | 80 | snuffleupagus_globals->config.config_disabled_functions_ret->disabled_functions = sp_list_new(); |
| 80 | SP_INIT_HT(snuffleupagus_globals->config.config_cookie->cookies); | 81 | SP_INIT_HT(snuffleupagus_globals->config.config_cookie->cookies); |
| @@ -118,6 +119,7 @@ PHP_MSHUTDOWN_FUNCTION(snuffleupagus) { | |||
| 118 | FREE_LST(config.config_disabled_functions->disabled_functions); | 119 | FREE_LST(config.config_disabled_functions->disabled_functions); |
| 119 | FREE_LST(config.config_disabled_functions_ret->disabled_functions); | 120 | FREE_LST(config.config_disabled_functions_ret->disabled_functions); |
| 120 | FREE_LST(config.config_disabled_constructs->construct_include); | 121 | FREE_LST(config.config_disabled_constructs->construct_include); |
| 122 | FREE_LST(config.config_disabled_constructs->construct_eval); | ||
| 121 | 123 | ||
| 122 | #undef FREE_LST | 124 | #undef FREE_LST |
| 123 | 125 | ||
diff --git a/src/sp_config.h b/src/sp_config.h index 12f12e8..6d091ae 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -115,6 +115,7 @@ typedef struct { | |||
| 115 | 115 | ||
| 116 | typedef struct { | 116 | typedef struct { |
| 117 | sp_node_t *construct_include; // list of rules for `(include|require)_(once)?` | 117 | sp_node_t *construct_include; // list of rules for `(include|require)_(once)?` |
| 118 | sp_node_t *construct_eval; | ||
| 118 | sp_node_t *construct_echo; | 119 | sp_node_t *construct_echo; |
| 119 | } sp_config_disabled_constructs; | 120 | } sp_config_disabled_constructs; |
| 120 | 121 | ||
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index 077d78f..0e52846 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -24,6 +24,9 @@ static int get_construct_type(sp_disabled_function const *const df) { | |||
| 24 | .type = ZEND_STRLEN, | 24 | .type = ZEND_STRLEN, |
| 25 | .keys = {"strlen", NULL} | 25 | .keys = {"strlen", NULL} |
| 26 | },{ | 26 | },{ |
| 27 | .type = ZEND_EVAL_CODE, | ||
| 28 | .keys = {"eval", NULL} | ||
| 29 | },{ | ||
| 27 | .type = 0, | 30 | .type = 0, |
| 28 | .keys = {NULL} | 31 | .keys = {NULL} |
| 29 | } | 32 | } |
| @@ -299,6 +302,9 @@ int parse_disabled_functions(char *line) { | |||
| 299 | case ZEND_INCLUDE_OR_EVAL: | 302 | case ZEND_INCLUDE_OR_EVAL: |
| 300 | sp_list_insert(SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include, df); | 303 | sp_list_insert(SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include, df); |
| 301 | return ret; | 304 | return ret; |
| 305 | case ZEND_EVAL_CODE: | ||
| 306 | sp_list_insert(SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval, df); | ||
| 307 | return ret; | ||
| 302 | case ZEND_ECHO: | 308 | case ZEND_ECHO: |
| 303 | default: | 309 | default: |
| 304 | break; | 310 | break; |
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 44a215c..e233259 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -101,16 +101,44 @@ static bool is_local_var_matching(zend_execute_data *execute_data, const sp_disa | |||
| 101 | return false; | 101 | return false; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | bool should_disable(zend_execute_data* execute_data) { | 104 | static sp_node_t *get_config(const char *builtin_name) { |
| 105 | if (!builtin_name) { | ||
| 106 | return SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions; | ||
| 107 | } | ||
| 108 | if (!strcmp(builtin_name, "eval")) { | ||
| 109 | return SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; | ||
| 110 | } | ||
| 111 | if (!strcmp(builtin_name, "include") || | ||
| 112 | !strcmp(builtin_name, "include_once") || | ||
| 113 | !strcmp(builtin_name, "require") || | ||
| 114 | !strcmp(builtin_name, "require_once")) { | ||
| 115 | return SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; | ||
| 116 | } | ||
| 117 | return NULL; | ||
| 118 | } | ||
| 119 | |||
| 120 | bool should_disable(zend_execute_data* execute_data, const char *builtin_name, const char *builtin_param, | ||
| 121 | const char *builtin_param_name) { | ||
| 105 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; | 122 | char current_file_hash[SHA256_SIZE * 2 + 1] = {0}; |
| 106 | const char* current_filename = zend_get_executed_filename(TSRMLS_C); | 123 | const sp_node_t* config = get_config(builtin_name); |
| 107 | const sp_node_t* config = | 124 | char* complete_path_function = get_complete_function_path(execute_data); |
| 108 | SNUFFLEUPAGUS_G(config).config_disabled_functions->disabled_functions; | ||
| 109 | char* complete_path_function = get_complete_function_path(execute_data);; | ||
| 110 | char const* client_ip = sp_getenv("REMOTE_ADDR"); | 125 | char const* client_ip = sp_getenv("REMOTE_ADDR"); |
| 126 | const char* current_filename; | ||
| 111 | 127 | ||
| 128 | if (builtin_name && !strcmp(builtin_name, "eval")) { | ||
| 129 | current_filename = get_eval_filename(zend_get_executed_filename()); | ||
| 130 | } | ||
| 131 | else { | ||
| 132 | current_filename = zend_get_executed_filename(); | ||
| 133 | } | ||
| 134 | |||
| 112 | if (!complete_path_function) { | 135 | if (!complete_path_function) { |
| 113 | return false; | 136 | if (builtin_name) { |
| 137 | complete_path_function = (char *)builtin_name; | ||
| 138 | } | ||
| 139 | else { | ||
| 140 | return false; | ||
| 141 | } | ||
| 114 | } | 142 | } |
| 115 | 143 | ||
| 116 | if (!config || !config->data) { | 144 | if (!config || !config->data) { |
| @@ -133,7 +161,7 @@ bool should_disable(zend_execute_data* execute_data) { | |||
| 133 | } | 161 | } |
| 134 | } else if (config_node->function) { /* Litteral match against the function name. */ | 162 | } else if (config_node->function) { /* Litteral match against the function name. */ |
| 135 | if (0 != strcmp(config_node->function, complete_path_function)) { | 163 | if (0 != strcmp(config_node->function, complete_path_function)) { |
| 136 | goto next; | 164 | goto next; |
| 137 | } | 165 | } |
| 138 | } else if (config_node->r_function) { | 166 | } else if (config_node->r_function) { |
| 139 | if (false == | 167 | if (false == |
| @@ -149,6 +177,7 @@ bool should_disable(zend_execute_data* execute_data) { | |||
| 149 | } | 177 | } |
| 150 | 178 | ||
| 151 | if (config_node->filename) { /* Check the current file name. */ | 179 | if (config_node->filename) { /* Check the current file name. */ |
| 180 | |||
| 152 | if (0 != strcmp(current_filename, config_node->filename)) { | 181 | if (0 != strcmp(current_filename, config_node->filename)) { |
| 153 | goto next; | 182 | goto next; |
| 154 | } | 183 | } |
| @@ -199,58 +228,66 @@ bool should_disable(zend_execute_data* execute_data) { | |||
| 199 | } | 228 | } |
| 200 | } | 229 | } |
| 201 | 230 | ||
| 202 | for (; i < nb_param; i++) { | 231 | if (builtin_name) { |
| 203 | arg_matched = false; | 232 | // we are matching on a builtin param, but for PHP, it's not the same a function param |
| 204 | if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency | 233 | arg_matched = sp_match_value(builtin_param, config_node->value, config_node->value_r); |
| 205 | arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); | 234 | arg_name = builtin_param_name; |
| 206 | } else { | 235 | arg_value_str = builtin_param; |
| 207 | arg_name = execute_data->func->internal_function.arg_info[i].name; | 236 | } |
| 208 | } | 237 | else { |
| 238 | for (; i < nb_param; i++) { | ||
| 239 | arg_matched = false; | ||
| 240 | if (ZEND_USER_CODE(execute_data->func->type)) { // yay consistency | ||
| 241 | arg_name = ZSTR_VAL(execute_data->func->common.arg_info[i].name); | ||
| 242 | } else { | ||
| 243 | arg_name = execute_data->func->internal_function.arg_info[i].name; | ||
| 244 | } | ||
| 209 | 245 | ||
| 210 | const bool arg_matching = | 246 | const bool arg_matching = |
| 211 | config_node->param && (0 == strcmp(arg_name, config_node->param)); | 247 | config_node->param && (0 == strcmp(arg_name, config_node->param)); |
| 212 | const bool pcre_matching = | 248 | const bool pcre_matching = |
| 213 | config_node->r_param && | 249 | config_node->r_param && |
| 214 | (true == is_regexp_matching(config_node->r_param, arg_name)); | 250 | (true == is_regexp_matching(config_node->r_param, arg_name)); |
| 215 | 251 | ||
| 216 | /* This is the parameter name we're looking for. */ | 252 | /* This is the parameter name we're looking for. */ |
| 217 | if (true == arg_matching || true == pcre_matching || (config_node->pos != -1)) { | 253 | if (true == arg_matching || true == pcre_matching || (config_node->pos != -1)) { |
| 218 | zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i); | 254 | zval* arg_value = ZEND_CALL_VAR_NUM(execute_data, i); |
| 219 | 255 | ||
| 220 | if (config_node->param_type) { // Are we matching on the `type`? | 256 | if (config_node->param_type) { // Are we matching on the `type`? |
| 221 | if (config_node->param_type == Z_TYPE_P(arg_value)) { | 257 | if (config_node->param_type == Z_TYPE_P(arg_value)) { |
| 222 | arg_matched = true; | 258 | arg_matched = true; |
| 223 | break; | 259 | break; |
| 224 | } | 260 | } |
| 225 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { | 261 | } else if (Z_TYPE_P(arg_value) == IS_ARRAY) { |
| 226 | arg_value_str = estrdup("Array"); | 262 | arg_value_str = estrdup("Array"); |
| 227 | // match on arr -> match on all key content, if a key is an array, | 263 | // match on arr -> match on all key content, if a key is an array, |
| 228 | // ignore it | 264 | // ignore it |
| 229 | // match on arr[foo] -> match only on key foo, if the key is an | 265 | // match on arr[foo] -> match only on key foo, if the key is an |
| 230 | // array, match on all keys content | 266 | // array, match on all keys content |
| 231 | if (config_node->param_is_array == true) { | 267 | if (config_node->param_is_array == true) { |
| 232 | if (true == sp_match_array_key_recurse( | 268 | if (true == sp_match_array_key_recurse( |
| 233 | arg_value, config_node->param_array_keys, | 269 | arg_value, config_node->param_array_keys, |
| 234 | config_node->value, config_node->value_r)) { | 270 | config_node->value, config_node->value_r)) { |
| 235 | arg_matched = true; | 271 | arg_matched = true; |
| 236 | break; | 272 | break; |
| 237 | } | 273 | } |
| 238 | } else { // match on all keys, but don't go into subarray | 274 | } else { // match on all keys, but don't go into subarray |
| 239 | if (true == sp_match_array_key(arg_value, config_node->value, | 275 | if (true == sp_match_array_key(arg_value, config_node->value, |
| 240 | config_node->value_r)) { | 276 | config_node->value_r)) { |
| 241 | arg_matched = true; | 277 | arg_matched = true; |
| 242 | break; | 278 | break; |
| 243 | } | 279 | } |
| 244 | } | 280 | } |
| 245 | } else { | 281 | } else { |
| 246 | arg_value_str = sp_convert_to_string(arg_value); | 282 | arg_value_str = sp_convert_to_string(arg_value); |
| 247 | if (true == sp_match_value(arg_value_str, config_node->value, | 283 | if (true == sp_match_value(arg_value_str, config_node->value, |
| 248 | config_node->value_r)) { | 284 | config_node->value_r)) { |
| 249 | arg_matched = true; | 285 | arg_matched = true; |
| 250 | break; | 286 | break; |
| 251 | } | 287 | } |
| 252 | } | 288 | } |
| 253 | } | 289 | } |
| 290 | } | ||
| 254 | } | 291 | } |
| 255 | if (false == arg_matched) { | 292 | if (false == arg_matched) { |
| 256 | goto next; | 293 | goto next; |
| @@ -273,14 +310,18 @@ bool should_disable(zend_execute_data* execute_data) { | |||
| 273 | if (true == config_node->simulation) { | 310 | if (true == config_node->simulation) { |
| 274 | goto next; | 311 | goto next; |
| 275 | } else { // We've got a match, the function won't be executed | 312 | } else { // We've got a match, the function won't be executed |
| 276 | efree(complete_path_function); | 313 | if (builtin_name == NULL) { |
| 314 | efree(complete_path_function); | ||
| 315 | } | ||
| 277 | return true; | 316 | return true; |
| 278 | } | 317 | } |
| 279 | next: | 318 | next: |
| 280 | config = config->next; | 319 | config = config->next; |
| 281 | } | 320 | } |
| 282 | allow: | 321 | allow: |
| 283 | efree(complete_path_function); | 322 | if (builtin_name == NULL) { |
| 323 | efree(complete_path_function); | ||
| 324 | } | ||
| 284 | return false; | 325 | return false; |
| 285 | } | 326 | } |
| 286 | 327 | ||
| @@ -370,7 +411,7 @@ ZEND_FUNCTION(check_disabled_function) { | |||
| 370 | void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); | 411 | void (*orig_handler)(INTERNAL_FUNCTION_PARAMETERS); |
| 371 | const char* current_function_name = get_active_function_name(TSRMLS_C); | 412 | const char* current_function_name = get_active_function_name(TSRMLS_C); |
| 372 | 413 | ||
| 373 | if (true == should_disable(execute_data)) { | 414 | if (true == should_disable(execute_data, NULL, NULL, NULL)) { |
| 374 | sp_terminate(); | 415 | sp_terminate(); |
| 375 | } | 416 | } |
| 376 | 417 | ||
diff --git a/src/sp_disabled_functions.h b/src/sp_disabled_functions.h index 260d430..e9180c9 100644 --- a/src/sp_disabled_functions.h +++ b/src/sp_disabled_functions.h | |||
| @@ -2,6 +2,6 @@ | |||
| 2 | #define __SP_DISABLE_FUNCTIONS_H | 2 | #define __SP_DISABLE_FUNCTIONS_H |
| 3 | 3 | ||
| 4 | int hook_disabled_functions(); | 4 | int hook_disabled_functions(); |
| 5 | bool should_disable(zend_execute_data* function_name); | 5 | bool should_disable(zend_execute_data*, const char *, const char *, const char *); |
| 6 | 6 | ||
| 7 | #endif /* __SP_DISABLE_FUNCTIONS_H */ | 7 | #endif /* __SP_DISABLE_FUNCTIONS_H */ |
diff --git a/src/sp_execute.c b/src/sp_execute.c index 45a4ae6..086d769 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -28,49 +28,55 @@ ZEND_COLD static inline void terminate_if_writable(const char *filename) { | |||
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | static void construct_include_handler(const char * const filename) { | 31 | static void is_builtin_matching(const char * const filename, char* function_name, |
| 32 | if (SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include) { | 32 | char *param_name, sp_node_t *config) { |
| 33 | const sp_node_t* config = SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; | 33 | if (!config || !config->data) { |
| 34 | if (!config || !config->data) { | 34 | return; |
| 35 | return; | 35 | } |
| 36 | } | 36 | |
| 37 | if (true == should_disable(EG(current_execute_data), function_name, filename, param_name)) { | ||
| 38 | sp_terminate(); | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | char *get_eval_filename(const char *filename) { | ||
| 43 | size_t i = strlen(filename) - 1; | ||
| 44 | int count = 0; | ||
| 45 | char *clean_filename = estrdup(filename); | ||
| 37 | 46 | ||
| 38 | while (config) { | 47 | //ghetto as fuck |
| 39 | sp_disabled_function *config_node = (sp_disabled_function*)(config->data); | 48 | //get the filename in which eval() is called from "foo.php(1) : eval()'d code" |
| 40 | if (true == sp_match_value(filename, config_node->value, config_node->value_r)) { | 49 | while (i) { |
| 41 | if (true == config_node->allow) { | 50 | if (clean_filename[i] == '(') { |
| 42 | return; | 51 | if (count == 1) { |
| 43 | } | 52 | clean_filename[i] = 0; |
| 44 | sp_log_disable("include", "inclusion path", filename, config_node); | 53 | break; |
| 45 | if (false == config_node->simulation) { | ||
| 46 | sp_terminate(); | ||
| 47 | } | ||
| 48 | } | 54 | } |
| 49 | config = config->next; | 55 | count++; |
| 50 | } | 56 | } |
| 57 | i--; | ||
| 51 | } | 58 | } |
| 59 | return clean_filename; | ||
| 52 | } | 60 | } |
| 53 | 61 | ||
| 54 | static void sp_execute_ex(zend_execute_data *execute_data) { | 62 | static void sp_execute_ex(zend_execute_data *execute_data) { |
| 55 | if (NULL == execute_data->func->common.function_name) { | 63 | if (true == should_disable(execute_data, NULL, NULL, NULL)) { |
| 56 | goto execute; | ||
| 57 | } | ||
| 58 | |||
| 59 | if (true == should_disable(execute_data)) { | ||
| 60 | sp_terminate(); | 64 | sp_terminate(); |
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | if (execute_data->func->op_array.type == ZEND_EVAL_CODE) { | 67 | if (execute_data->func->op_array.type == ZEND_EVAL_CODE) { |
| 64 | sp_log_debug("Currently in an eval\n"); | 68 | sp_node_t* config = SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_eval; |
| 69 | char *filename = get_eval_filename((char *)zend_get_executed_filename()); | ||
| 70 | is_builtin_matching(filename, "eval", NULL, config); | ||
| 71 | efree(filename); | ||
| 65 | } | 72 | } |
| 66 | 73 | ||
| 67 | if (NULL != execute_data->func->op_array.filename) { | 74 | if (NULL != execute_data->func->op_array.filename) { |
| 68 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { | 75 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { |
| 69 | terminate_if_writable(ZSTR_VAL(execute_data->func->op_array.filename)); | 76 | terminate_if_writable(ZSTR_VAL(execute_data->func->op_array.filename)); |
| 70 | } | 77 | } |
| 71 | } | 78 | } |
| 72 | 79 | ||
| 73 | execute: | ||
| 74 | orig_execute_ex(execute_data); | 80 | orig_execute_ex(execute_data); |
| 75 | } | 81 | } |
| 76 | 82 | ||
| @@ -86,7 +92,26 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) { | |||
| 86 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { | 92 | if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->enable) { |
| 87 | terminate_if_writable(filename); | 93 | terminate_if_writable(filename); |
| 88 | } | 94 | } |
| 89 | construct_include_handler(filename); | 95 | sp_node_t* config = SNUFFLEUPAGUS_G(config).config_disabled_constructs->construct_include; |
| 96 | switch (data->opline->extended_value) { | ||
| 97 | case ZEND_INCLUDE: | ||
| 98 | is_builtin_matching(filename, "include", "inclusion path", config); | ||
| 99 | break; | ||
| 100 | case ZEND_REQUIRE: | ||
| 101 | is_builtin_matching(filename, "require", "inclusion path", config); | ||
| 102 | break; | ||
| 103 | case ZEND_REQUIRE_ONCE: | ||
| 104 | is_builtin_matching(filename, "require_once", "inclusion path", config); | ||
| 105 | break; | ||
| 106 | case ZEND_INCLUDE_ONCE: | ||
| 107 | is_builtin_matching(filename, "include_once", "inclusion path", config); | ||
| 108 | break; | ||
| 109 | case ZEND_EVAL: | ||
| 110 | is_builtin_matching(filename, "eval", NULL, config); | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | break; | ||
| 114 | } | ||
| 90 | } | 115 | } |
| 91 | 116 | ||
| 92 | end: | 117 | end: |
diff --git a/src/sp_execute.h b/src/sp_execute.h index 8345736..6ef50ee 100644 --- a/src/sp_execute.h +++ b/src/sp_execute.h | |||
| @@ -2,5 +2,6 @@ | |||
| 2 | #define SP_EXECUTE_H | 2 | #define SP_EXECUTE_H |
| 3 | 3 | ||
| 4 | int hook_execute(void); | 4 | int hook_execute(void); |
| 5 | char *get_eval_filename(const char *filename); | ||
| 5 | 6 | ||
| 6 | #endif /* SP_EXECUTE_H */ | 7 | #endif /* SP_EXECUTE_H */ |
diff --git a/src/sp_utils.c b/src/sp_utils.c index 514fc10..28c8a8b 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -229,6 +229,8 @@ bool sp_match_value(const char* value, const char* to_match, const pcre* rx) { | |||
| 229 | } | 229 | } |
| 230 | } else if (rx) { | 230 | } else if (rx) { |
| 231 | return is_regexp_matching(rx, value); | 231 | return is_regexp_matching(rx, value); |
| 232 | } else { | ||
| 233 | return true; | ||
| 232 | } | 234 | } |
| 233 | return false; | 235 | return false; |
| 234 | } | 236 | } |
diff --git a/src/tests/config/config_disabled_functions_eval_filename.ini b/src/tests/config/config_disabled_functions_eval_filename.ini new file mode 100644 index 0000000..f66cef3 --- /dev/null +++ b/src/tests/config/config_disabled_functions_eval_filename.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.disable_function.function("eval").filename_r("^.*tests/disabled_functions_eval_filename.php$").drop(); | |||
diff --git a/src/tests/config/disabled_functions.ini b/src/tests/config/disabled_functions.ini index 226a107..df7013f 100644 --- a/src/tests/config/disabled_functions.ini +++ b/src/tests/config/disabled_functions.ini | |||
| @@ -5,4 +5,5 @@ sp.disable_function.function("printf").simulation().drop(); | |||
| 5 | sp.disable_function.function("print").disable().drop(); # this is a comment | 5 | sp.disable_function.function("print").disable().drop(); # this is a comment |
| 6 | sp.disable_function.function_r("^var_dump$").drop(); | 6 | sp.disable_function.function_r("^var_dump$").drop(); |
| 7 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); | 7 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); |
| 8 | sp.disable_function.function("sprintf").filename("/wrong file name").drop(); | ||
| 8 | sp.disable_function.function("eval").drop(); | 9 | sp.disable_function.function("eval").drop(); |
diff --git a/src/tests/config/disabled_functions_eval.ini b/src/tests/config/disabled_functions_eval.ini new file mode 100644 index 0000000..f761259 --- /dev/null +++ b/src/tests/config/disabled_functions_eval.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.disable_function.function("eval").drop(); | |||
diff --git a/src/tests/config/disabled_functions_eval_simulation.ini b/src/tests/config/disabled_functions_eval_simulation.ini new file mode 100644 index 0000000..f1dc58c --- /dev/null +++ b/src/tests/config/disabled_functions_eval_simulation.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.disable_function.function("eval").drop().simulation(); | |||
diff --git a/src/tests/deny_writable_execution.phpt b/src/tests/deny_writable_execution.phpt index 2870561..c399d35 100644 --- a/src/tests/deny_writable_execution.phpt +++ b/src/tests/deny_writable_execution.phpt | |||
| @@ -32,8 +32,7 @@ include "$dir/non_writable_file.txt"; | |||
| 32 | include "$dir/writable_file.txt"; | 32 | include "$dir/writable_file.txt"; |
| 33 | ?> | 33 | ?> |
| 34 | --EXPECTF-- | 34 | --EXPECTF-- |
| 35 | Code execution within a non-writable file. | 35 | [snuffleupagus][0.0.0.0][readonly_exec][drop] Attempted execution of a writable file (%a/tests/deny_writable_execution.php). |
| 36 | [snuffleupagus][0.0.0.0][readonly_exec][drop] Attempted execution of a writable file (%a/writable_file.txt). | ||
| 37 | --CLEAN-- | 36 | --CLEAN-- |
| 38 | <?php | 37 | <?php |
| 39 | $dir = __DIR__; | 38 | $dir = __DIR__; |
| @@ -41,4 +40,4 @@ chmod("$dir/non_writable_file.txt", 0777); | |||
| 41 | chmod("$dir/writable_file.txt", 0777); | 40 | chmod("$dir/writable_file.txt", 0777); |
| 42 | unlink("$dir/non_writable_file.txt"); | 41 | unlink("$dir/non_writable_file.txt"); |
| 43 | unlink("$dir/writable_file.txt"); | 42 | unlink("$dir/writable_file.txt"); |
| 44 | ?> \ No newline at end of file | 43 | ?> |
diff --git a/src/tests/disabled_functions_eval.phpt b/src/tests/disabled_functions_eval.phpt index 0beaefe..7bd6b4b 100644 --- a/src/tests/disabled_functions_eval.phpt +++ b/src/tests/disabled_functions_eval.phpt | |||
| @@ -3,13 +3,12 @@ Disable functions - eval | |||
| 3 | --SKIPIF-- | 3 | --SKIPIF-- |
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> |
| 5 | --INI-- | 5 | --INI-- |
| 6 | sp.configuration_file={PWD}/config/disabled_functions.ini | 6 | sp.configuration_file={PWD}/config/disabled_functions_eval.ini |
| 7 | --XFAIL-- | ||
| 8 | --FILE-- | 7 | --FILE-- |
| 9 | <?php | 8 | <?php |
| 10 | $var = 1234; | 9 | $var = 123456789; |
| 11 | eval('$var = 1337;'); | 10 | eval('$var = 1337 + 1337;'); |
| 12 | print("Variable: $var\n"); | 11 | print("Variable: $var\n"); |
| 13 | ?> | 12 | ?> |
| 14 | --EXPECTF-- | 13 | --EXPECTF-- |
| 15 | [snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'eval' in %a/tests/disabled_functions_eval.php:%d has been disabled, because it matched a rule. | 14 | [snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'eval' in %a/tests/disabled_functions_eval.php(%d) : eval()'d code:%d has been disabled. |
diff --git a/src/tests/disabled_functions_eval_filename.phpt b/src/tests/disabled_functions_eval_filename.phpt new file mode 100644 index 0000000..5e64acc --- /dev/null +++ b/src/tests/disabled_functions_eval_filename.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Disable functions - eval | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/config_disabled_functions_eval_filename.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | $var = 123456789; | ||
| 10 | eval('$var = 1337 + 1337;'); | ||
| 11 | print("Variable: $var\n"); | ||
| 12 | ?> | ||
| 13 | --EXPECTF-- | ||
| 14 | [snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'eval' in %a/tests/disabled_functions_eval_filename.php(%d) : eval()'d code:%d has been disabled. | ||
diff --git a/src/tests/disabled_functions_eval_simulation.phpt b/src/tests/disabled_functions_eval_simulation.phpt new file mode 100644 index 0000000..06a006e --- /dev/null +++ b/src/tests/disabled_functions_eval_simulation.phpt | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | --TEST-- | ||
| 2 | Disable functions - eval (simulation) | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/disabled_functions_eval_simulation.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | $var = 123456789; | ||
| 10 | eval('$var = 1337 + 1337;'); | ||
| 11 | print("Variable: $var\n"); | ||
| 12 | ?> | ||
| 13 | --EXPECTF-- | ||
| 14 | [snuffleupagus][0.0.0.0][disabled_function][simulation] The call to the function 'eval' in %a/tests/disabled_functions_eval_simulation.php(%d) : eval()'d code:%d has been disabled. | ||
| 15 | Variable: 2674 | ||
diff --git a/src/tests/disabled_functions_require.phpt b/src/tests/disabled_functions_require.phpt index f848f8b..cc904f1 100644 --- a/src/tests/disabled_functions_require.phpt +++ b/src/tests/disabled_functions_require.phpt | |||
| @@ -14,7 +14,7 @@ require $dir . '/test.meh'; | |||
| 14 | echo "1337"; | 14 | echo "1337"; |
| 15 | ?> | 15 | ?> |
| 16 | --EXPECTF-- | 16 | --EXPECTF-- |
| 17 | BLA[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'include' in %a/disabled_functions_require.php:%d has been disabled, because its argument 'inclusion path' content (%a/test.meh) matched a rule. | 17 | BLA[snuffleupagus][0.0.0.0][disabled_function][drop] The call to the function 'require' in %a/disabled_functions_require.php:%d has been disabled, because its argument 'inclusion path' content (%a/test.meh) matched a rule. |
| 18 | --CLEAN-- | 18 | --CLEAN-- |
| 19 | <?php | 19 | <?php |
| 20 | $dir = __DIR__; | 20 | $dir = __DIR__; |
diff --git a/src/tests/disabled_functions_require_simulation.phpt b/src/tests/disabled_functions_require_simulation.phpt index 2744c37..bd49268 100644 --- a/src/tests/disabled_functions_require_simulation.phpt +++ b/src/tests/disabled_functions_require_simulation.phpt | |||
| @@ -15,7 +15,7 @@ echo "1337\n"; | |||
| 15 | ?> | 15 | ?> |
| 16 | --EXPECTF-- | 16 | --EXPECTF-- |
| 17 | BLA | 17 | BLA |
| 18 | [snuffleupagus][0.0.0.0][disabled_function][simulation] The call to the function 'include' in %a/disabled_functions_require_simulation.php:%d has been disabled, because its argument 'inclusion path' content (%a/test.sim) matched a rule. | 18 | [snuffleupagus][0.0.0.0][disabled_function][simulation] The call to the function 'require' in %a/disabled_functions_require_simulation.php:%d has been disabled, because its argument 'inclusion path' content (%a/test.sim) matched a rule. |
| 19 | MEH | 19 | MEH |
| 20 | 1337 | 20 | 1337 |
| 21 | --CLEAN-- | 21 | --CLEAN-- |
