1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#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 1 2 3 4 5 6 7 8 9 a b c d e f */
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xf0 */ 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 (SPCFG(server_encode)) {
sp_server_encode(svars, ZEND_STRL("REQUEST_URI"));
sp_server_encode(svars, ZEND_STRL("QUERY_STRING"));
}
if (SPCFG(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 && sapi_module.register_server_variables != sp_register_server_variables) {
orig_register_server_variables = sapi_module.register_server_variables;
sapi_module.register_server_variables = sp_register_server_variables;
}
}
|