diff options
| -rw-r--r-- | Changelog | 1 | ||||
| -rw-r--r-- | execute.c | 130 | ||||
| -rw-r--r-- | tests/filter/filter_logging_statistics.phpt | 40 |
3 files changed, 108 insertions, 63 deletions
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | - Added better handling of non existing/non executable shell scripts | 3 | - Added better handling of non existing/non executable shell scripts |
| 4 | - Added protection against XSS/SQL/Other Injections through User-Agent HTTP header | 4 | - Added protection against XSS/SQL/Other Injections through User-Agent HTTP header |
| 5 | - Fix variable logging statistics outputting on every include - ticket: #37 | ||
| 5 | - Added LICENSE file to make distributions happy | 6 | - Added LICENSE file to make distributions happy |
| 6 | 7 | ||
| 7 | 2014-02-24 - 0.9.35 | 8 | 2014-02-24 - 0.9.35 |
| @@ -397,96 +397,100 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML | |||
| 397 | unsigned long *suhosin_flags = NULL; | 397 | unsigned long *suhosin_flags = NULL; |
| 398 | 398 | ||
| 399 | /* log variable dropping statistics */ | 399 | /* log variable dropping statistics */ |
| 400 | if (SUHOSIN_G(abort_request) && (SUHOSIN_G(att_request_variables)-SUHOSIN_G(cur_request_variables) > 0)) { | 400 | if (SUHOSIN_G(abort_request)) { |
| 401 | suhosin_log(S_VARS, "dropped %u request variables - (%u in GET, %u in POST, %u in COOKIE)", | ||
| 402 | SUHOSIN_G(att_request_variables)-SUHOSIN_G(cur_request_variables), | ||
| 403 | SUHOSIN_G(att_get_vars)-SUHOSIN_G(cur_get_vars), | ||
| 404 | SUHOSIN_G(att_post_vars)-SUHOSIN_G(cur_post_vars), | ||
| 405 | SUHOSIN_G(att_cookie_vars)-SUHOSIN_G(cur_cookie_vars)); | ||
| 406 | } | ||
| 407 | |||
| 408 | if (SUHOSIN_G(abort_request) && !SUHOSIN_G(simulation) && SUHOSIN_G(filter_action)) { | ||
| 409 | |||
| 410 | char *action = SUHOSIN_G(filter_action); | ||
| 411 | long code = -1; | ||
| 412 | 401 | ||
| 413 | SUHOSIN_G(abort_request) = 0; /* we do not want to endlessloop */ | 402 | SUHOSIN_G(abort_request) = 0; /* we only want this to happen the first time */ |
| 414 | 403 | ||
| 415 | while (*action == ' ' || *action == '\t') action++; | 404 | if (SUHOSIN_G(att_request_variables)-SUHOSIN_G(cur_request_variables) > 0) { |
| 405 | suhosin_log(S_VARS, "dropped %u request variables - (%u in GET, %u in POST, %u in COOKIE)", | ||
| 406 | SUHOSIN_G(att_request_variables)-SUHOSIN_G(cur_request_variables), | ||
| 407 | SUHOSIN_G(att_get_vars)-SUHOSIN_G(cur_get_vars), | ||
| 408 | SUHOSIN_G(att_post_vars)-SUHOSIN_G(cur_post_vars), | ||
| 409 | SUHOSIN_G(att_cookie_vars)-SUHOSIN_G(cur_cookie_vars)); | ||
| 416 | 410 | ||
| 417 | if (*action >= '0' && *action <= '9') { | ||
| 418 | char *end = action; | ||
| 419 | while (*end && *end != ',' && *end != ';') end++; | ||
| 420 | code = zend_atoi(action, end-action); | ||
| 421 | action = end; | ||
| 422 | } | 411 | } |
| 412 | |||
| 413 | if (!SUHOSIN_G(simulation) && SUHOSIN_G(filter_action)) { | ||
| 414 | |||
| 415 | char *action = SUHOSIN_G(filter_action); | ||
| 416 | long code = -1; | ||
| 417 | |||
| 418 | while (*action == ' ' || *action == '\t') action++; | ||
| 419 | |||
| 420 | if (*action >= '0' && *action <= '9') { | ||
| 421 | char *end = action; | ||
| 422 | while (*end && *end != ',' && *end != ';') end++; | ||
| 423 | code = zend_atoi(action, end-action); | ||
| 424 | action = end; | ||
| 425 | } | ||
| 423 | 426 | ||
| 424 | while (*action == ' ' || *action == '\t' || *action == ',' || *action == ';') action++; | 427 | while (*action == ' ' || *action == '\t' || *action == ',' || *action == ';') action++; |
| 425 | 428 | ||
| 426 | if (*action) { | 429 | if (*action) { |
| 427 | 430 | ||
| 428 | if (strncmp("http://", action, sizeof("http://")-1)==0) { | 431 | if (strncmp("http://", action, sizeof("http://")-1)==0) { |
| 429 | sapi_header_line ctr = {0}; | 432 | sapi_header_line ctr = {0}; |
| 430 | 433 | ||
| 431 | if (code == -1) { | 434 | if (code == -1) { |
| 432 | code = 302; | 435 | code = 302; |
| 433 | } | 436 | } |
| 434 | 437 | ||
| 435 | ctr.line_len = spprintf(&ctr.line, 0, "Location: %s", action); | 438 | ctr.line_len = spprintf(&ctr.line, 0, "Location: %s", action); |
| 436 | ctr.response_code = code; | 439 | ctr.response_code = code; |
| 437 | sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); | 440 | sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); |
| 438 | efree(ctr.line); | 441 | efree(ctr.line); |
| 439 | } else { | 442 | } else { |
| 440 | zend_file_handle file_handle; | 443 | zend_file_handle file_handle; |
| 441 | zend_op_array *new_op_array; | 444 | zend_op_array *new_op_array; |
| 442 | zval *result = NULL; | 445 | zval *result = NULL; |
| 443 | 446 | ||
| 444 | if (code == -1) { | 447 | if (code == -1) { |
| 445 | code = 200; | 448 | code = 200; |
| 446 | } | 449 | } |
| 447 | 450 | ||
| 448 | #ifdef ZEND_ENGINE_2 | 451 | #ifdef ZEND_ENGINE_2 |
| 449 | if (zend_stream_open(action, &file_handle TSRMLS_CC) == SUCCESS) { | 452 | if (zend_stream_open(action, &file_handle TSRMLS_CC) == SUCCESS) { |
| 450 | #else | 453 | #else |
| 451 | if (zend_open(action, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { | 454 | if (zend_open(action, &file_handle) == SUCCESS && ZEND_IS_VALID_FILE_HANDLE(&file_handle)) { |
| 452 | file_handle.filename = action; | 455 | file_handle.filename = action; |
| 453 | file_handle.free_filename = 0; | 456 | file_handle.free_filename = 0; |
| 454 | #endif | 457 | #endif |
| 455 | if (!file_handle.opened_path) { | 458 | if (!file_handle.opened_path) { |
| 456 | file_handle.opened_path = estrndup(action, strlen(action)); | 459 | file_handle.opened_path = estrndup(action, strlen(action)); |
| 457 | } | 460 | } |
| 458 | new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); | 461 | new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC); |
| 459 | zend_destroy_file_handle(&file_handle TSRMLS_CC); | 462 | zend_destroy_file_handle(&file_handle TSRMLS_CC); |
| 460 | if (new_op_array) { | 463 | if (new_op_array) { |
| 461 | EG(return_value_ptr_ptr) = &result; | 464 | EG(return_value_ptr_ptr) = &result; |
| 462 | EG(active_op_array) = new_op_array; | 465 | EG(active_op_array) = new_op_array; |
| 463 | zend_execute(new_op_array TSRMLS_CC); | 466 | zend_execute(new_op_array TSRMLS_CC); |
| 464 | #ifdef ZEND_ENGINE_2 | 467 | #ifdef ZEND_ENGINE_2 |
| 465 | destroy_op_array(new_op_array TSRMLS_CC); | 468 | destroy_op_array(new_op_array TSRMLS_CC); |
| 466 | #else | 469 | #else |
| 467 | destroy_op_array(new_op_array); | 470 | destroy_op_array(new_op_array); |
| 468 | #endif | 471 | #endif |
| 469 | efree(new_op_array); | 472 | efree(new_op_array); |
| 470 | #ifdef ZEND_ENGINE_2 | 473 | #ifdef ZEND_ENGINE_2 |
| 471 | if (!EG(exception)) | 474 | if (!EG(exception)) |
| 472 | #endif | 475 | #endif |
| 473 | { | 476 | { |
| 474 | if (EG(return_value_ptr_ptr)) { | 477 | if (EG(return_value_ptr_ptr)) { |
| 475 | zval_ptr_dtor(EG(return_value_ptr_ptr)); | 478 | zval_ptr_dtor(EG(return_value_ptr_ptr)); |
| 476 | EG(return_value_ptr_ptr) = NULL; | 479 | EG(return_value_ptr_ptr) = NULL; |
| 480 | } | ||
| 477 | } | 481 | } |
| 482 | } else { | ||
| 483 | code = 500; | ||
| 478 | } | 484 | } |
| 479 | } else { | 485 | } else { |
| 480 | code = 500; | 486 | code = 500; |
| 481 | } | 487 | } |
| 482 | } else { | ||
| 483 | code = 500; | ||
| 484 | } | 488 | } |
| 485 | } | 489 | } |
| 486 | } | ||
| 487 | 490 | ||
| 488 | sapi_header_op(SAPI_HEADER_SET_STATUS, (void *)code TSRMLS_CC); | 491 | sapi_header_op(SAPI_HEADER_SET_STATUS, (void *)code TSRMLS_CC); |
| 489 | zend_bailout(); | 492 | zend_bailout(); |
| 493 | } | ||
| 490 | } | 494 | } |
| 491 | 495 | ||
| 492 | SDEBUG("%s %s", op_array->filename, op_array->function_name); | 496 | SDEBUG("%s %s", op_array->filename, op_array->function_name); |
diff --git a/tests/filter/filter_logging_statistics.phpt b/tests/filter/filter_logging_statistics.phpt new file mode 100644 index 0000000..a448d78 --- /dev/null +++ b/tests/filter/filter_logging_statistics.phpt | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | --TEST-- | ||
| 2 | suhosin variable filter logging statistics | ||
| 3 | --INI-- | ||
| 4 | suhosin.log.syslog=0 | ||
| 5 | suhosin.log.sapi=0 | ||
| 6 | suhosin.log.stdout=255 | ||
| 7 | suhosin.log.script=0 | ||
| 8 | suhosin.get.max_vars=5 | ||
| 9 | error_reporting=E_ALL | ||
| 10 | --SKIPIF-- | ||
| 11 | <?php include('skipif.inc'); ?> | ||
| 12 | --COOKIE-- | ||
| 13 | --GET-- | ||
| 14 | A=A&B=B&C=C&D=D&E=E&F=F&G=G& | ||
| 15 | --POST-- | ||
| 16 | --FILE-- | ||
| 17 | <?php | ||
| 18 | $counter++; | ||
| 19 | if ($counter < 5) { | ||
| 20 | include __FILE__; | ||
| 21 | } else { | ||
| 22 | var_dump($_GET); | ||
| 23 | } | ||
| 24 | ?> | ||
| 25 | --EXPECTF-- | ||
| 26 | Notice: Undefined variable: counter in %s on line 2 | ||
| 27 | array(5) { | ||
| 28 | ["A"]=> | ||
| 29 | string(1) "A" | ||
| 30 | ["B"]=> | ||
| 31 | string(1) "B" | ||
| 32 | ["C"]=> | ||
| 33 | string(1) "C" | ||
| 34 | ["D"]=> | ||
| 35 | string(1) "D" | ||
| 36 | ["E"]=> | ||
| 37 | string(1) "E" | ||
| 38 | } | ||
| 39 | ALERT - configured GET variable limit exceeded - dropped variable 'F' - all further GET variables are dropped (attacker 'REMOTE_ADDR not set', file '%s') | ||
| 40 | ALERT - dropped 2 request variables - (2 in GET, 0 in POST, 0 in COOKIE) (attacker 'REMOTE_ADDR not set', file '%s') | ||
