diff options
| author | Ben Fuhrmannek | 2021-09-16 11:32:41 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-09-16 11:32:41 +0200 |
| commit | 6e07cdb870513270a3c08abc7ecdca64ad2af400 (patch) | |
| tree | f9784435101f85d9ff0776c205421a7916b5854e /src | |
| parent | 31d6a3cddd18cef447698ba2beaa7b5d9ab9dd94 (diff) | |
ported server.strip and server.encode features from suhosin
Diffstat (limited to 'src')
| -rw-r--r-- | src/config.m4 | 2 | ||||
| -rw-r--r-- | src/php_snuffleupagus.h | 1 | ||||
| -rw-r--r-- | src/snuffleupagus.c | 2 | ||||
| -rw-r--r-- | src/sp_config.h | 4 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 2 | ||||
| -rw-r--r-- | src/sp_ifilter.c | 103 | ||||
| -rw-r--r-- | src/sp_ifilter.h | 3 | ||||
| -rw-r--r-- | src/tests/filter/config/filter.ini | 3 | ||||
| -rw-r--r-- | src/tests/filter/server_encode.phpt | 25 | ||||
| -rw-r--r-- | src/tests/filter/server_strip.phpt | 21 |
10 files changed, 165 insertions, 1 deletions
diff --git a/src/config.m4 b/src/config.m4 index a2301fd..ddbd7a1 100644 --- a/src/config.m4 +++ b/src/config.m4 | |||
| @@ -7,7 +7,7 @@ sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" | |||
| 7 | sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" | 7 | sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" |
| 8 | sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" | 8 | sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" |
| 9 | sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c sp_wrapper.c" | 9 | sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c sp_wrapper.c" |
| 10 | sources="$sources sp_ini.c sp_php_compat.c sp_config_scanner.c" | 10 | sources="$sources sp_ini.c sp_php_compat.c sp_config_scanner.c sp_ifilter.c" |
| 11 | 11 | ||
| 12 | PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, | 12 | PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, |
| 13 | [ --enable-snuffleupagus Enable snuffleupagus support]) | 13 | [ --enable-snuffleupagus Enable snuffleupagus support]) |
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index 0c7dc4b..bcb613c 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h | |||
| @@ -88,6 +88,7 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); | |||
| 88 | #include "sp_sloppy.h" | 88 | #include "sp_sloppy.h" |
| 89 | #include "sp_wrapper.h" | 89 | #include "sp_wrapper.h" |
| 90 | #include "sp_ini.h" | 90 | #include "sp_ini.h" |
| 91 | #include "sp_ifilter.h" | ||
| 91 | 92 | ||
| 92 | extern zend_module_entry snuffleupagus_module_entry; | 93 | extern zend_module_entry snuffleupagus_module_entry; |
| 93 | #define phpext_snuffleupagus_ptr &snuffleupagus_module_entry | 94 | #define phpext_snuffleupagus_ptr &snuffleupagus_module_entry |
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index d2f81ff..50711f0 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -383,6 +383,8 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 383 | sp_hook_ini(); | 383 | sp_hook_ini(); |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | sp_hook_register_server_variables(); | ||
| 387 | |||
| 386 | if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { | 388 | if (true == SNUFFLEUPAGUS_G(config).config_global_strict->enable) { |
| 387 | if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { | 389 | if (!zend_get_extension(PHP_SNUFFLEUPAGUS_EXTNAME)) { |
| 388 | zend_extension_entry.startup = NULL; | 390 | zend_extension_entry.startup = NULL; |
diff --git a/src/sp_config.h b/src/sp_config.h index ccf2318..af9b905 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -197,6 +197,8 @@ typedef struct { | |||
| 197 | bool hook_execute; | 197 | bool hook_execute; |
| 198 | char log_media; | 198 | char log_media; |
| 199 | u_long max_execution_depth; | 199 | u_long max_execution_depth; |
| 200 | bool server_encode; | ||
| 201 | bool server_strip; | ||
| 200 | 202 | ||
| 201 | HashTable *config_disabled_functions; | 203 | HashTable *config_disabled_functions; |
| 202 | HashTable *config_disabled_functions_hooked; | 204 | HashTable *config_disabled_functions_hooked; |
| @@ -288,6 +290,8 @@ typedef struct { | |||
| 288 | #define SP_TOKEN_ENV_VAR "cookie_env_var" | 290 | #define SP_TOKEN_ENV_VAR "cookie_env_var" |
| 289 | #define SP_TOKEN_LOG_MEDIA "log_media" | 291 | #define SP_TOKEN_LOG_MEDIA "log_media" |
| 290 | #define SP_TOKEN_MAX_EXECUTION_DEPTH "max_execution_depth" | 292 | #define SP_TOKEN_MAX_EXECUTION_DEPTH "max_execution_depth" |
| 293 | #define SP_TOKEN_SERVER_ENCODE "server_encode" | ||
| 294 | #define SP_TOKEN_SERVER_STRIP "server_strip" | ||
| 291 | 295 | ||
| 292 | // upload_validator | 296 | // upload_validator |
| 293 | #define SP_TOKEN_UPLOAD_SCRIPT "script" | 297 | #define SP_TOKEN_UPLOAD_SCRIPT "script" |
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index 632f9bd..38b8526 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -129,6 +129,8 @@ SP_PARSE_FN(parse_global) { | |||
| 129 | {parse_str, SP_TOKEN_ENV_VAR, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)}, | 129 | {parse_str, SP_TOKEN_ENV_VAR, &(SNUFFLEUPAGUS_G(config).config_snuffleupagus->cookies_env_var)}, |
| 130 | {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SNUFFLEUPAGUS_G(config).log_media)}, | 130 | {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SNUFFLEUPAGUS_G(config).log_media)}, |
| 131 | {parse_ulong, SP_TOKEN_MAX_EXECUTION_DEPTH, &(SNUFFLEUPAGUS_G(config).max_execution_depth)}, | 131 | {parse_ulong, SP_TOKEN_MAX_EXECUTION_DEPTH, &(SNUFFLEUPAGUS_G(config).max_execution_depth)}, |
| 132 | {parse_enable, SP_TOKEN_SERVER_ENCODE, &(SNUFFLEUPAGUS_G(config).server_encode)}, | ||
| 133 | {parse_enable, SP_TOKEN_SERVER_STRIP, &(SNUFFLEUPAGUS_G(config).server_strip)}, | ||
| 132 | {0, 0, 0}}; | 134 | {0, 0, 0}}; |
| 133 | 135 | ||
| 134 | SP_PROCESS_CONFIG_KEYWORDS_ERR(); | 136 | SP_PROCESS_CONFIG_KEYWORDS_ERR(); |
diff --git a/src/sp_ifilter.c b/src/sp_ifilter.c new file mode 100644 index 0000000..171138f --- /dev/null +++ b/src/sp_ifilter.c | |||
| @@ -0,0 +1,103 @@ | |||
| 1 | #include "php_snuffleupagus.h" | ||
| 2 | |||
| 3 | static void (*orig_register_server_variables)(zval *track_vars_array) = NULL; | ||
| 4 | |||
| 5 | static const unsigned char sp_hexchars[] = "0123456789ABCDEF"; | ||
| 6 | |||
| 7 | static const char sp_is_dangerous_char[256] = { | ||
| 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, | ||
| 9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 10 | 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 11 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, | ||
| 12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 14 | 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 20 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 21 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 23 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
| 24 | }; | ||
| 25 | |||
| 26 | static void sp_server_strip(HashTable *svars, char *key, int keylen) { | ||
| 27 | zval *value = zend_hash_str_find(svars, key, keylen); | ||
| 28 | if (!value || Z_TYPE_P(value) != IS_STRING) { return; } | ||
| 29 | |||
| 30 | zend_string *tmp_zstr = Z_STR_P(value); | ||
| 31 | char *tmp = ZSTR_VAL(tmp_zstr); | ||
| 32 | char *tmpend = tmp + ZSTR_LEN(tmp_zstr); | ||
| 33 | |||
| 34 | for (char *p = tmp; p < tmpend; p++) { | ||
| 35 | if (sp_is_dangerous_char[(int)*p]) { | ||
| 36 | *p = '_'; | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | static void sp_server_encode(HashTable *svars, char *key, int keylen) { | ||
| 42 | zval *value = zend_hash_str_find(svars, key, keylen); | ||
| 43 | if (!value || Z_TYPE_P(value) != IS_STRING) { return; } | ||
| 44 | |||
| 45 | zend_string *tmp_zstr = Z_STR_P(value); | ||
| 46 | char *tmp = ZSTR_VAL(tmp_zstr); | ||
| 47 | char *tmpend = tmp + ZSTR_LEN(tmp_zstr); | ||
| 48 | int extra = 0; | ||
| 49 | |||
| 50 | for (char *p = tmp; p < tmpend; p++) { | ||
| 51 | extra += sp_is_dangerous_char[(int)*p] * 2; | ||
| 52 | } | ||
| 53 | if (!extra) { return; } | ||
| 54 | |||
| 55 | zend_string *new_zstr = zend_string_alloc(ZSTR_LEN(tmp_zstr) + extra, 0); | ||
| 56 | char *n = ZSTR_VAL(new_zstr); | ||
| 57 | for (char *p = tmp; p < tmpend; p++, n++) { | ||
| 58 | if (sp_is_dangerous_char[(int)*p]) { | ||
| 59 | *n++ = '%'; | ||
| 60 | *n++ = sp_hexchars[*p >> 4]; | ||
| 61 | *n = sp_hexchars[*p & 15]; | ||
| 62 | } else { | ||
| 63 | *n = *p; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | ZSTR_VAL(new_zstr)[ZSTR_LEN(new_zstr)] = 0; | ||
| 67 | Z_STR_P(value) = new_zstr; | ||
| 68 | |||
| 69 | zend_string_release_ex(tmp_zstr, 0); | ||
| 70 | } | ||
| 71 | |||
| 72 | static void sp_register_server_variables(zval *track_vars_array) { | ||
| 73 | orig_register_server_variables(track_vars_array); | ||
| 74 | |||
| 75 | HashTable *svars; | ||
| 76 | svars = Z_ARRVAL_P(track_vars_array); | ||
| 77 | |||
| 78 | |||
| 79 | if (SNUFFLEUPAGUS_G(config).server_encode) { | ||
| 80 | sp_server_encode(svars, ZEND_STRL("REQUEST_URI")); | ||
| 81 | sp_server_encode(svars, ZEND_STRL("QUERY_STRING")); | ||
| 82 | } | ||
| 83 | |||
| 84 | if (SNUFFLEUPAGUS_G(config).server_strip) { | ||
| 85 | sp_server_strip(svars, ZEND_STRL("PHP_SELF")); | ||
| 86 | sp_server_strip(svars, ZEND_STRL("HTTP_HOST")); | ||
| 87 | sp_server_strip(svars, ZEND_STRL("HTTP_USER_AGENT")); | ||
| 88 | |||
| 89 | // for cgi + fpm | ||
| 90 | sp_server_strip(svars, ZEND_STRL("PATH_INFO")); | ||
| 91 | sp_server_strip(svars, ZEND_STRL("PATH_TRANSLATED")); | ||
| 92 | sp_server_strip(svars, ZEND_STRL("ORIG_PATH_TRANSLATED")); | ||
| 93 | sp_server_strip(svars, ZEND_STRL("ORIG_PATH_INFO")); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | void sp_hook_register_server_variables() | ||
| 98 | { | ||
| 99 | if (sapi_module.register_server_variables) { | ||
| 100 | orig_register_server_variables = sapi_module.register_server_variables; | ||
| 101 | sapi_module.register_server_variables = sp_register_server_variables; | ||
| 102 | } | ||
| 103 | } | ||
diff --git a/src/sp_ifilter.h b/src/sp_ifilter.h new file mode 100644 index 0000000..527c41d --- /dev/null +++ b/src/sp_ifilter.h | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | void sp_hook_register_server_variables(); | ||
diff --git a/src/tests/filter/config/filter.ini b/src/tests/filter/config/filter.ini new file mode 100644 index 0000000..5ebee61 --- /dev/null +++ b/src/tests/filter/config/filter.ini | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | sp.global.server_encode.enable(); | ||
| 2 | sp.global.server_strip.enable(); | ||
| 3 | |||
diff --git a/src/tests/filter/server_encode.phpt b/src/tests/filter/server_encode.phpt new file mode 100644 index 0000000..f7cc233 --- /dev/null +++ b/src/tests/filter/server_encode.phpt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | --TEST-- | ||
| 2 | input filter: server_encode | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/filter.ini | ||
| 7 | display_errors=1 | ||
| 8 | display_startup_errors=1 | ||
| 9 | error_reporting=E_ALL | ||
| 10 | --ENV-- | ||
| 11 | return <<<EOF | ||
| 12 | REQUEST_URI=AAA<>"'`!AAA | ||
| 13 | EOF; | ||
| 14 | --COOKIE-- | ||
| 15 | --GET-- | ||
| 16 | BBB<>"'`!BBB | ||
| 17 | --POST-- | ||
| 18 | --FILE-- | ||
| 19 | <?php | ||
| 20 | var_dump($_SERVER['REQUEST_URI']); | ||
| 21 | var_dump($_SERVER['QUERY_STRING']); | ||
| 22 | --EXPECT-- | ||
| 23 | string(22) "AAA%3C%3E%22%27%60!AAA" | ||
| 24 | string(22) "BBB%3C%3E%22%27%60!BBB" | ||
| 25 | |||
diff --git a/src/tests/filter/server_strip.phpt b/src/tests/filter/server_strip.phpt new file mode 100644 index 0000000..83072b4 --- /dev/null +++ b/src/tests/filter/server_strip.phpt | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | --TEST-- | ||
| 2 | input filter: server_strip | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/filter.ini | ||
| 7 | display_errors=1 | ||
| 8 | display_startup_errors=1 | ||
| 9 | error_reporting=E_ALL | ||
| 10 | --ENV-- | ||
| 11 | return <<<EOF | ||
| 12 | HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 6.0; rv:29.0) <script>alert('123');</script>Gecko/20100101 Firefox/29.0 | ||
| 13 | EOF; | ||
| 14 | --COOKIE-- | ||
| 15 | --GET-- | ||
| 16 | --POST-- | ||
| 17 | --FILE-- | ||
| 18 | <?php | ||
| 19 | var_dump($_SERVER['HTTP_USER_AGENT']); | ||
| 20 | --EXPECT-- | ||
| 21 | string(95) "Mozilla/5.0 (Windows NT 6.0; rv:29.0) _script_alert(_123_);_/script_Gecko/20100101 Firefox/29.0" | ||
