From 5fbb1733f67172e4111fa512961106f4733395db Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Sat, 7 Aug 2021 15:57:30 +0200 Subject: unit tests for ini protection feature --- src/tests/ini/config/sp-policy-drop.ini | 3 +++ src/tests/ini/config/sp-policy-silent-fail.ini | 3 +++ src/tests/ini/config/sp.ini | 11 +++++++++ src/tests/ini/ini_min_policy_drop.phpt | 13 ++++++++++ src/tests/ini/ini_min_policy_silent_fail.phpt | 14 +++++++++++ src/tests/ini/ini_minmax.phpt | 34 ++++++++++++++++++++++++++ src/tests/ini/ini_null.phpt | 26 ++++++++++++++++++++ src/tests/ini/ini_regexp.phpt | 19 ++++++++++++++ src/tests/ini/ini_regexp_drop.phpt | 13 ++++++++++ src/tests/ini/ini_set.phpt | 12 +++++++++ 10 files changed, 148 insertions(+) create mode 100644 src/tests/ini/config/sp-policy-drop.ini create mode 100644 src/tests/ini/config/sp-policy-silent-fail.ini create mode 100644 src/tests/ini/config/sp.ini create mode 100644 src/tests/ini/ini_min_policy_drop.phpt create mode 100644 src/tests/ini/ini_min_policy_silent_fail.phpt create mode 100644 src/tests/ini/ini_minmax.phpt create mode 100644 src/tests/ini/ini_null.phpt create mode 100644 src/tests/ini/ini_regexp.phpt create mode 100644 src/tests/ini/ini_regexp_drop.phpt create mode 100644 src/tests/ini/ini_set.phpt (limited to 'src/tests/ini') diff --git a/src/tests/ini/config/sp-policy-drop.ini b/src/tests/ini/config/sp-policy-drop.ini new file mode 100644 index 0000000..1c28030 --- /dev/null +++ b/src/tests/ini/config/sp-policy-drop.ini @@ -0,0 +1,3 @@ +sp.ini_protection.enable(); +sp.ini_protection.policy_drop(); +sp.ini.key("log_errors_max_len").min("200").max("2000"); diff --git a/src/tests/ini/config/sp-policy-silent-fail.ini b/src/tests/ini/config/sp-policy-silent-fail.ini new file mode 100644 index 0000000..8236077 --- /dev/null +++ b/src/tests/ini/config/sp-policy-silent-fail.ini @@ -0,0 +1,3 @@ +sp.ini_protection.enable(); +sp.ini_protection.policy_silent_fail(); +sp.ini.key("log_errors_max_len").min("200").max("2000"); diff --git a/src/tests/ini/config/sp.ini b/src/tests/ini/config/sp.ini new file mode 100644 index 0000000..3022e37 --- /dev/null +++ b/src/tests/ini/config/sp.ini @@ -0,0 +1,11 @@ +sp.ini_protection.enable(); + +sp.ini.key("log_errors_max_len").min("200").max("2000"); +sp.ini.key("max_execution_time").min("30").max("600"); +sp.ini.key("highlight.comment").regexp("^#[0-9a-fA-F]{6}$"); +sp.ini.key("default_mimetype").set("text/plain").ro(); + +sp.ini.key("sendmail_from").set("test@example.com").regexp(".*@example\\.com$").allow_null(); +sp.ini.key("unserialize_callback_func").set("def").regexp("^abc$"); + +sp.ini.key("user_agent").regexp("^abc$").drop(); diff --git a/src/tests/ini/ini_min_policy_drop.phpt b/src/tests/ini/ini_min_policy_drop.phpt new file mode 100644 index 0000000..9dddcc4 --- /dev/null +++ b/src/tests/ini/ini_min_policy_drop.phpt @@ -0,0 +1,13 @@ +--TEST-- +INI protection .min() + .policy_drop() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp-policy-drop.ini +--FILE-- + +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value out of range in %a/ini_min_policy_drop.php on line 2 diff --git a/src/tests/ini/ini_min_policy_silent_fail.phpt b/src/tests/ini/ini_min_policy_silent_fail.phpt new file mode 100644 index 0000000..8ef780d --- /dev/null +++ b/src/tests/ini/ini_min_policy_silent_fail.phpt @@ -0,0 +1,14 @@ +--TEST-- +INI protection .min() + .policy_silent_fail() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp-policy-silent-fail.ini +--FILE-- + +--EXPECTF-- +bool(true) +string(1) "0" \ No newline at end of file diff --git a/src/tests/ini/ini_minmax.phpt b/src/tests/ini/ini_minmax.phpt new file mode 100644 index 0000000..fc93075 --- /dev/null +++ b/src/tests/ini/ini_minmax.phpt @@ -0,0 +1,34 @@ +--TEST-- +INI protection .min()/.max() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp.ini +--FILE-- + +--EXPECTF-- +bool(false) +string(3) "200" +bool(false) +string(4) "2000" + +Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 8 +bool(true) +string(4) "2000" + +Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 11 +bool(true) +string(4) "2000" \ No newline at end of file diff --git a/src/tests/ini/ini_null.phpt b/src/tests/ini/ini_null.phpt new file mode 100644 index 0000000..32a12c1 --- /dev/null +++ b/src/tests/ini/ini_null.phpt @@ -0,0 +1,26 @@ +--TEST-- +INI protection .allow_null() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp.ini +--FILE-- + +--EXPECTF-- +bool(false) +string(15) "foo@example.com" +bool(false) +string(0) "" + +Warning: [snuffleupagus][0.0.0.0][ini_protection][log] new INI value must not be NULL or empty in %a/ini_null.php on line 8 +bool(true) +string(3) "def" \ No newline at end of file diff --git a/src/tests/ini/ini_regexp.phpt b/src/tests/ini/ini_regexp.phpt new file mode 100644 index 0000000..f6c5198 --- /dev/null +++ b/src/tests/ini/ini_regexp.phpt @@ -0,0 +1,19 @@ +--TEST-- +INI protection .regexp() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp.ini +--FILE-- + +--EXPECTF-- +string(7) "#000aBc" + +Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value does not match regex in %a/ini_regexp.php on line 5 +string(7) "#000aBc" diff --git a/src/tests/ini/ini_regexp_drop.phpt b/src/tests/ini/ini_regexp_drop.phpt new file mode 100644 index 0000000..9225470 --- /dev/null +++ b/src/tests/ini/ini_regexp_drop.phpt @@ -0,0 +1,13 @@ +--TEST-- +INI protection .min() + .drop() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp.ini +--FILE-- + +--EXPECTF-- +Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value does not match regex in %a/ini_regexp_drop.php on line 2 diff --git a/src/tests/ini/ini_set.phpt b/src/tests/ini/ini_set.phpt new file mode 100644 index 0000000..bfafbe8 --- /dev/null +++ b/src/tests/ini/ini_set.phpt @@ -0,0 +1,12 @@ +--TEST-- +INI protection .set() +--SKIPIF-- + +--INI-- +sp.configuration_file={PWD}/config/sp.ini +--FILE-- + +--EXPECTF-- +string(10) "text/plain" \ No newline at end of file -- cgit v1.3 From 6095651e2caa729ff56ae5a53c908b09e5f7dc29 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Tue, 30 Nov 2021 19:38:34 +0100 Subject: PHP 8.1 compatibility with streams/includes + fix for ticks --- src/snuffleupagus.c | 1 - src/sp_disabled_functions.c | 12 +++----- src/sp_execute.c | 40 ++++++++++++++++++++------ src/tests/ini/config/sp-policy-drop.ini | 2 +- src/tests/ini/config/sp-policy-silent-fail.ini | 2 +- src/tests/ini/config/sp.ini | 3 +- src/tests/ini/ini_min_policy_drop.phpt | 4 +-- src/tests/ini/ini_min_policy_silent_fail.phpt | 4 +-- src/tests/ini/ini_minmax.phpt | 24 ++++++++-------- 9 files changed, 55 insertions(+), 37 deletions(-) (limited to 'src/tests/ini') diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index e3ecd72..01a0b01 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c @@ -370,7 +370,6 @@ static PHP_INI_MH(OnUpdateConfiguration) { if (SPCFG(show_old_php_warning)) { time_t ts = time(NULL); - sp_log_debug("foo"); if (PHP_VERSION_ID < 70300 || PHP_VERSION_ID < 70400 && ts >= (time_t)1638745200L || PHP_VERSION_ID < 80000 && ts >= (time_t)1669590000L || diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 4ef72bf..a3b3e99 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c @@ -498,11 +498,9 @@ static int hook_functions_regexp(const sp_list_node* config) { assert(function_name || function_name_regexp); if (function_name) { - HOOK_FUNCTION(ZSTR_VAL(function_name), disabled_functions_hook, - PHP_FN(check_disabled_function)); + HOOK_FUNCTION(ZSTR_VAL(function_name), disabled_functions_hook, PHP_FN(check_disabled_function)); } else { - HOOK_FUNCTION_BY_REGEXP(function_name_regexp, disabled_functions_hook, - PHP_FN(check_disabled_function)); + HOOK_FUNCTION_BY_REGEXP(function_name_regexp, disabled_functions_hook, PHP_FN(check_disabled_function)); } config = config->next; @@ -515,10 +513,8 @@ static void hook_functions(HashTable* to_hook_ht, HashTable* hooked_ht) { zval* value; ZEND_HASH_FOREACH_STR_KEY_VAL(to_hook_ht, key, value) { - bool hooked = HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, - PHP_FN(check_disabled_function)); - bool is_builtin = - check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data); + bool hooked = HOOK_FUNCTION(ZSTR_VAL(key), disabled_functions_hook, PHP_FN(check_disabled_function)); + bool is_builtin = check_is_builtin_name(((sp_list_node*)Z_PTR_P(value))->data); if (hooked || is_builtin) { zend_symtable_add_new(hooked_ht, key, value); zend_hash_del(to_hook_ht, key); diff --git a/src/sp_execute.c b/src/sp_execute.c index ccb7508..f540119 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -3,8 +3,11 @@ static void (*orig_execute_ex)(zend_execute_data *execute_data) = NULL; static void (*orig_zend_execute_internal)(zend_execute_data *execute_data, zval *return_value) = NULL; -static int (*orig_zend_stream_open)(const char *filename, - zend_file_handle *handle) = NULL; +#if PHP_VERSION_ID < 80100 +static int (*orig_zend_stream_open)(const char *filename, zend_file_handle *handle) = NULL; +#else +static zend_result (*orig_zend_stream_open)(zend_file_handle *handle) = NULL; +#endif // FIXME handle symlink ZEND_COLD static inline void terminate_if_writable(const char *filename) { @@ -168,6 +171,7 @@ static void sp_execute_ex(zend_execute_data *execute_data) { case ZEND_DO_FCALL_BY_NAME: case ZEND_DO_ICALL: case ZEND_DO_UCALL: + case ZEND_TICKS: should_disable_ht(execute_data, function_name, NULL, NULL, config_disabled_functions_reg, config_disabled_functions); @@ -209,21 +213,21 @@ static void sp_zend_execute_internal(INTERNAL_FUNCTION_PARAMETERS) { } } -static int sp_stream_open(const char *filename, zend_file_handle *handle) { +static inline void sp_stream_open_checks(zend_string *zend_filename, zend_file_handle *handle) { zend_execute_data const *const data = EG(current_execute_data); if ((NULL == data) || (NULL == data->opline) || (data->func->type != ZEND_USER_FUNCTION)) { - goto end; + return; } - zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); + // zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); const HashTable *disabled_functions_hooked = SPCFG(disabled_functions_hooked); switch (data->opline->opcode) { case ZEND_INCLUDE_OR_EVAL: if (SPCFG(readonly_exec).enable) { - terminate_if_writable(filename); + terminate_if_writable(ZSTR_VAL(zend_filename)); } switch (data->opline->extended_value) { case ZEND_INCLUDE: @@ -253,12 +257,32 @@ static int sp_stream_open(const char *filename, zend_file_handle *handle) { EMPTY_SWITCH_DEFAULT_CASE(); // LCOV_EXCL_LINE } } - efree(zend_filename); + // efree(zend_filename); + +// end: + // return orig_zend_stream_open(filename, handle); +} + +#if PHP_VERSION_ID < 80100 + +static int sp_stream_open(const char *filename, zend_file_handle *handle) { + zend_string *zend_filename = zend_string_init(filename, strlen(filename), 0); -end: + sp_stream_open_checks(zend_filename, handle); + + zend_string_release_ex(zend_filename, 0); return orig_zend_stream_open(filename, handle); } +#else // PHP >= 8.1 + +static zend_result sp_stream_open(zend_file_handle *handle) { + sp_stream_open_checks(handle->filename, handle); + return orig_zend_stream_open(handle); +} + +#endif + int hook_execute(void) { TSRMLS_FETCH(); diff --git a/src/tests/ini/config/sp-policy-drop.ini b/src/tests/ini/config/sp-policy-drop.ini index 1c28030..4b1e374 100644 --- a/src/tests/ini/config/sp-policy-drop.ini +++ b/src/tests/ini/config/sp-policy-drop.ini @@ -1,3 +1,3 @@ sp.ini_protection.enable(); sp.ini_protection.policy_drop(); -sp.ini.key("log_errors_max_len").min("200").max("2000"); +sp.ini.key("max_execution_time").min("30").max("300"); diff --git a/src/tests/ini/config/sp-policy-silent-fail.ini b/src/tests/ini/config/sp-policy-silent-fail.ini index 8236077..2123837 100644 --- a/src/tests/ini/config/sp-policy-silent-fail.ini +++ b/src/tests/ini/config/sp-policy-silent-fail.ini @@ -1,3 +1,3 @@ sp.ini_protection.enable(); sp.ini_protection.policy_silent_fail(); -sp.ini.key("log_errors_max_len").min("200").max("2000"); +sp.ini.key("max_execution_time").min("30").max("300"); diff --git a/src/tests/ini/config/sp.ini b/src/tests/ini/config/sp.ini index 3022e37..86a63a7 100644 --- a/src/tests/ini/config/sp.ini +++ b/src/tests/ini/config/sp.ini @@ -1,7 +1,6 @@ sp.ini_protection.enable(); -sp.ini.key("log_errors_max_len").min("200").max("2000"); -sp.ini.key("max_execution_time").min("30").max("600"); +sp.ini.key("max_execution_time").min("30").max("300"); sp.ini.key("highlight.comment").regexp("^#[0-9a-fA-F]{6}$"); sp.ini.key("default_mimetype").set("text/plain").ro(); diff --git a/src/tests/ini/ini_min_policy_drop.phpt b/src/tests/ini/ini_min_policy_drop.phpt index 9dddcc4..ef40ebc 100644 --- a/src/tests/ini/ini_min_policy_drop.phpt +++ b/src/tests/ini/ini_min_policy_drop.phpt @@ -6,8 +6,8 @@ INI protection .min() + .policy_drop() sp.configuration_file={PWD}/config/sp-policy-drop.ini --FILE-- --EXPECTF-- Fatal error: [snuffleupagus][0.0.0.0][ini_protection][drop] INI value out of range in %a/ini_min_policy_drop.php on line 2 diff --git a/src/tests/ini/ini_min_policy_silent_fail.phpt b/src/tests/ini/ini_min_policy_silent_fail.phpt index 8ef780d..d0117a7 100644 --- a/src/tests/ini/ini_min_policy_silent_fail.phpt +++ b/src/tests/ini/ini_min_policy_silent_fail.phpt @@ -6,8 +6,8 @@ INI protection .min() + .policy_silent_fail() sp.configuration_file={PWD}/config/sp-policy-silent-fail.ini --FILE-- --EXPECTF-- bool(true) diff --git a/src/tests/ini/ini_minmax.phpt b/src/tests/ini/ini_minmax.phpt index fc93075..4cd6bc4 100644 --- a/src/tests/ini/ini_minmax.phpt +++ b/src/tests/ini/ini_minmax.phpt @@ -6,29 +6,29 @@ INI protection .min()/.max() sp.configuration_file={PWD}/config/sp.ini --FILE-- --EXPECTF-- bool(false) -string(3) "200" +string(2) "30" bool(false) -string(4) "2000" +string(3) "300" Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 8 bool(true) -string(4) "2000" +string(3) "300" Warning: [snuffleupagus][0.0.0.0][ini_protection][log] INI value out of range in %a/ini_minmax.php on line 11 bool(true) -string(4) "2000" \ No newline at end of file +string(3) "300" \ No newline at end of file -- cgit v1.3