summaryrefslogtreecommitdiff
path: root/src/sp_disabled_functions.c
diff options
context:
space:
mode:
authorjvoisin2017-11-29 11:36:57 +0100
committerGitHub2017-11-29 11:36:57 +0100
commit10437787b0e8ede80976de4a1c22775fc1282f36 (patch)
tree1ab911ab000989b98449475eda655a797e278049 /src/sp_disabled_functions.c
parent8df77884f38e7a7334b56aafe2f441567f175af8 (diff)
Implement eval hooking
It's not possible to hook the `eval` builtin like other functions.
Diffstat (limited to 'src/sp_disabled_functions.c')
-rw-r--r--src/sp_disabled_functions.c153
1 files changed, 97 insertions, 56 deletions
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
104bool should_disable(zend_execute_data* execute_data) { 104static 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
120bool 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 }
279next: 318next:
280config = config->next; 319config = config->next;
281 } 320 }
282allow: 321allow:
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