summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/config.m42
-rw-r--r--src/php_snuffleupagus.h1
-rw-r--r--src/snuffleupagus.c2
-rw-r--r--src/sp_config.h4
-rw-r--r--src/sp_config_keywords.c2
-rw-r--r--src/sp_ifilter.c103
-rw-r--r--src/sp_ifilter.h3
-rw-r--r--src/tests/filter/config/filter.ini3
-rw-r--r--src/tests/filter/server_encode.phpt25
-rw-r--r--src/tests/filter/server_strip.phpt21
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"
7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" 7sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c"
8sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" 8sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c"
9sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c sp_wrapper.c" 9sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c sp_wrapper.c"
10sources="$sources sp_ini.c sp_php_compat.c sp_config_scanner.c" 10sources="$sources sp_ini.c sp_php_compat.c sp_config_scanner.c sp_ifilter.c"
11 11
12PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, 12PHP_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
92extern zend_module_entry snuffleupagus_module_entry; 93extern 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
3static void (*orig_register_server_variables)(zval *track_vars_array) = NULL;
4
5static const unsigned char sp_hexchars[] = "0123456789ABCDEF";
6
7static 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
26static 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
41static 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
72static 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
97void 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
3void 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 @@
1sp.global.server_encode.enable();
2sp.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--
2input filter: server_encode
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/filter.ini
7display_errors=1
8display_startup_errors=1
9error_reporting=E_ALL
10--ENV--
11return <<<EOF
12REQUEST_URI=AAA<>"'`!AAA
13EOF;
14--COOKIE--
15--GET--
16BBB<>"'`!BBB
17--POST--
18--FILE--
19<?php
20var_dump($_SERVER['REQUEST_URI']);
21var_dump($_SERVER['QUERY_STRING']);
22--EXPECT--
23string(22) "AAA%3C%3E%22%27%60!AAA"
24string(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--
2input filter: server_strip
3--SKIPIF--
4<?php if (!extension_loaded("snuffleupagus")) print "skip"; ?>
5--INI--
6sp.configuration_file={PWD}/config/filter.ini
7display_errors=1
8display_startup_errors=1
9error_reporting=E_ALL
10--ENV--
11return <<<EOF
12HTTP_USER_AGENT=Mozilla/5.0 (Windows NT 6.0; rv:29.0) <script>alert('123');</script>Gecko/20100101 Firefox/29.0
13EOF;
14--COOKIE--
15--GET--
16--POST--
17--FILE--
18<?php
19var_dump($_SERVER['HTTP_USER_AGENT']);
20--EXPECT--
21string(95) "Mozilla/5.0 (Windows NT 6.0; rv:29.0) _script_alert(_123_);_/script_Gecko/20100101 Firefox/29.0"