Annotation of embedaddon/php/README.input_filter, revision 1.1.1.1
1.1 misho 1: Input Filter Support in PHP 5
2: -----------------------------
3:
4: XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
5: and can be quite difficult to prevent. Whenever you accept user data
6: and somehow display this data back to users, you are likely vulnerable
7: to XSS hacks.
8:
9: The Input Filter support in PHP 5 is aimed at providing the framework
10: through which a company-wide or site-wide security policy can be
11: enforced. It is implemented as a SAPI hook and is called from the
12: treat_data and post handler functions. To implement your own security
13: policy you will need to write a standard PHP extension. There is also
14: a powerful standard implementation in ext/filter that should suit most
15: peoples' needs. However, if you want to implement your own security
16: policy, read on.
17:
18: A simple implementation might look like the following. This stores the
19: original raw user data and adds a my_get_raw() function while the normal
20: $_POST, $_GET and $_COOKIE arrays are only populated with stripped
21: data. In this simple example all I am doing is calling strip_tags() on
22: the data. If register_globals is turned on, the default globals that
23: are created will be stripped ($foo) while a $RAW_foo is created with the
24: original user input.
25:
26: ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
27: zval *post_array;
28: zval *get_array;
29: zval *cookie_array;
30: ZEND_END_MODULE_GLOBALS(my_input_filter)
31:
32: #ifdef ZTS
33: #define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
34: #else
35: #define IF_G(v) (my_input_filter_globals.v)
36: #endif
37:
38: ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
39:
40: zend_function_entry my_input_filter_functions[] = {
41: PHP_FE(my_get_raw, NULL)
42: {NULL, NULL, NULL}
43: };
44:
45: zend_module_entry my_input_filter_module_entry = {
46: STANDARD_MODULE_HEADER,
47: "my_input_filter",
48: my_input_filter_functions,
49: PHP_MINIT(my_input_filter),
50: PHP_MSHUTDOWN(my_input_filter),
51: NULL,
52: PHP_RSHUTDOWN(my_input_filter),
53: PHP_MINFO(my_input_filter),
54: "0.1",
55: STANDARD_MODULE_PROPERTIES
56: };
57:
58: PHP_MINIT_FUNCTION(my_input_filter)
59: {
60: ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
61:
62: REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
63: REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
64: REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
65:
66: sapi_register_input_filter(my_sapi_input_filter);
67: return SUCCESS;
68: }
69:
70: PHP_RSHUTDOWN_FUNCTION(my_input_filter)
71: {
72: if(IF_G(get_array)) {
73: zval_ptr_dtor(&IF_G(get_array));
74: IF_G(get_array) = NULL;
75: }
76: if(IF_G(post_array)) {
77: zval_ptr_dtor(&IF_G(post_array));
78: IF_G(post_array) = NULL;
79: }
80: if(IF_G(cookie_array)) {
81: zval_ptr_dtor(&IF_G(cookie_array));
82: IF_G(cookie_array) = NULL;
83: }
84: return SUCCESS;
85: }
86:
87: PHP_MINFO_FUNCTION(my_input_filter)
88: {
89: php_info_print_table_start();
90: php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
91: php_info_print_table_row( 2, "Revision", "$Revision: 222526 $");
92: php_info_print_table_end();
93: }
94:
95: /* The filter handler. If you return 1 from it, then PHP also registers the
96: * (modified) variable. Returning 0 prevents PHP from registering the variable;
97: * you can use this if your filter already registers the variable under a
98: * different name, or if you just don't want the variable registered at all. */
99: SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
100: {
101: zval new_var;
102: zval *array_ptr = NULL;
103: char *raw_var;
104: int var_len;
105:
106: assert(*val != NULL);
107:
108: switch(arg) {
109: case PARSE_GET:
110: if(!IF_G(get_array)) {
111: ALLOC_ZVAL(array_ptr);
112: array_init(array_ptr);
113: INIT_PZVAL(array_ptr);
114: }
115: IF_G(get_array) = array_ptr;
116: break;
117: case PARSE_POST:
118: if(!IF_G(post_array)) {
119: ALLOC_ZVAL(array_ptr);
120: array_init(array_ptr);
121: INIT_PZVAL(array_ptr);
122: }
123: IF_G(post_array) = array_ptr;
124: break;
125: case PARSE_COOKIE:
126: if(!IF_G(cookie_array)) {
127: ALLOC_ZVAL(array_ptr);
128: array_init(array_ptr);
129: INIT_PZVAL(array_ptr);
130: }
131: IF_G(cookie_array) = array_ptr;
132: break;
133: }
134: Z_STRLEN(new_var) = val_len;
135: Z_STRVAL(new_var) = estrndup(*val, val_len);
136: Z_TYPE(new_var) = IS_STRING;
137:
138: var_len = strlen(var);
139: raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
140: strcpy(raw_var, "RAW_");
141: strlcat(raw_var,var,var_len+5);
142:
143: php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
144:
145: php_strip_tags(*val, val_len, NULL, NULL, 0);
146:
147: *new_val_len = strlen(*val);
148: return 1;
149: }
150:
151: PHP_FUNCTION(my_get_raw)
152: {
153: long arg;
154: char *var;
155: int var_len;
156: zval **tmp;
157: zval *array_ptr = NULL;
158: HashTable *hash_ptr;
159: char *raw_var;
160:
161: if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
162: return;
163: }
164:
165: switch(arg) {
166: case PARSE_GET:
167: array_ptr = IF_G(get_array);
168: break;
169: case PARSE_POST:
170: array_ptr = IF_G(post_array);
171: break;
172: case PARSE_COOKIE:
173: array_ptr = IF_G(post_array);
174: break;
175: }
176:
177: if(!array_ptr) RETURN_FALSE;
178:
179: /*
180: * I'm changing the variable name here because when running with register_globals on,
181: * the variable will end up in the global symbol table
182: */
183: raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
184: strcpy(raw_var, "RAW_");
185: strlcat(raw_var,var,var_len+5);
186: hash_ptr = HASH_OF(array_ptr);
187:
188: if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
189: *return_value = **tmp;
190: zval_copy_ctor(return_value);
191: } else {
192: RETVAL_FALSE;
193: }
194: efree(raw_var);
195: }
196:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>