From 6e07cdb870513270a3c08abc7ecdca64ad2af400 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Thu, 16 Sep 2021 11:32:41 +0200 Subject: ported server.strip and server.encode features from suhosin --- src/sp_ifilter.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/sp_ifilter.c (limited to 'src/sp_ifilter.c') 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 @@ +#include "php_snuffleupagus.h" + +static void (*orig_register_server_variables)(zval *track_vars_array) = NULL; + +static const unsigned char sp_hexchars[] = "0123456789ABCDEF"; + +static const char sp_is_dangerous_char[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static void sp_server_strip(HashTable *svars, char *key, int keylen) { + zval *value = zend_hash_str_find(svars, key, keylen); + if (!value || Z_TYPE_P(value) != IS_STRING) { return; } + + zend_string *tmp_zstr = Z_STR_P(value); + char *tmp = ZSTR_VAL(tmp_zstr); + char *tmpend = tmp + ZSTR_LEN(tmp_zstr); + + for (char *p = tmp; p < tmpend; p++) { + if (sp_is_dangerous_char[(int)*p]) { + *p = '_'; + } + } +} + +static void sp_server_encode(HashTable *svars, char *key, int keylen) { + zval *value = zend_hash_str_find(svars, key, keylen); + if (!value || Z_TYPE_P(value) != IS_STRING) { return; } + + zend_string *tmp_zstr = Z_STR_P(value); + char *tmp = ZSTR_VAL(tmp_zstr); + char *tmpend = tmp + ZSTR_LEN(tmp_zstr); + int extra = 0; + + for (char *p = tmp; p < tmpend; p++) { + extra += sp_is_dangerous_char[(int)*p] * 2; + } + if (!extra) { return; } + + zend_string *new_zstr = zend_string_alloc(ZSTR_LEN(tmp_zstr) + extra, 0); + char *n = ZSTR_VAL(new_zstr); + for (char *p = tmp; p < tmpend; p++, n++) { + if (sp_is_dangerous_char[(int)*p]) { + *n++ = '%'; + *n++ = sp_hexchars[*p >> 4]; + *n = sp_hexchars[*p & 15]; + } else { + *n = *p; + } + } + ZSTR_VAL(new_zstr)[ZSTR_LEN(new_zstr)] = 0; + Z_STR_P(value) = new_zstr; + + zend_string_release_ex(tmp_zstr, 0); +} + +static void sp_register_server_variables(zval *track_vars_array) { + orig_register_server_variables(track_vars_array); + + HashTable *svars; + svars = Z_ARRVAL_P(track_vars_array); + + + if (SNUFFLEUPAGUS_G(config).server_encode) { + sp_server_encode(svars, ZEND_STRL("REQUEST_URI")); + sp_server_encode(svars, ZEND_STRL("QUERY_STRING")); + } + + if (SNUFFLEUPAGUS_G(config).server_strip) { + sp_server_strip(svars, ZEND_STRL("PHP_SELF")); + sp_server_strip(svars, ZEND_STRL("HTTP_HOST")); + sp_server_strip(svars, ZEND_STRL("HTTP_USER_AGENT")); + + // for cgi + fpm + sp_server_strip(svars, ZEND_STRL("PATH_INFO")); + sp_server_strip(svars, ZEND_STRL("PATH_TRANSLATED")); + sp_server_strip(svars, ZEND_STRL("ORIG_PATH_TRANSLATED")); + sp_server_strip(svars, ZEND_STRL("ORIG_PATH_INFO")); + } +} + +void sp_hook_register_server_variables() +{ + if (sapi_module.register_server_variables) { + orig_register_server_variables = sapi_module.register_server_variables; + sapi_module.register_server_variables = sp_register_server_variables; + } +} -- cgit v1.3