1 Input Filter Support in PHP 5
2 -----------------------------
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
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
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
24 ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
28 ZEND_END_MODULE_GLOBALS(my_input_filter)
31 #define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
33 #define IF_G(v) (my_input_filter_globals.v)
36 ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
38 zend_function_entry my_input_filter_functions[] = {
39 PHP_FE(my_get_raw, NULL)
43 zend_module_entry my_input_filter_module_entry = {
44 STANDARD_MODULE_HEADER,
46 my_input_filter_functions,
47 PHP_MINIT(my_input_filter),
48 PHP_MSHUTDOWN(my_input_filter),
50 PHP_RSHUTDOWN(my_input_filter),
51 PHP_MINFO(my_input_filter),
53 STANDARD_MODULE_PROPERTIES
56 PHP_MINIT_FUNCTION(my_input_filter)
58 ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
60 REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
61 REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
62 REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
64 sapi_register_input_filter(my_sapi_input_filter);
68 PHP_RSHUTDOWN_FUNCTION(my_input_filter)
71 zval_ptr_dtor(&IF_G(get_array));
72 IF_G(get_array) = NULL;
74 if(IF_G(post_array)) {
75 zval_ptr_dtor(&IF_G(post_array));
76 IF_G(post_array) = NULL;
78 if(IF_G(cookie_array)) {
79 zval_ptr_dtor(&IF_G(cookie_array));
80 IF_G(cookie_array) = NULL;
85 PHP_MINFO_FUNCTION(my_input_filter)
87 php_info_print_table_start();
88 php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
89 php_info_print_table_row( 2, "Revision", "$Id$");
90 php_info_print_table_end();
93 /* The filter handler. If you return 1 from it, then PHP also registers the
94 * (modified) variable. Returning 0 prevents PHP from registering the variable;
95 * you can use this if your filter already registers the variable under a
96 * different name, or if you just don't want the variable registered at all. */
97 SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
100 zval *array_ptr = NULL;
104 assert(*val != NULL);
108 if(!IF_G(get_array)) {
109 ALLOC_ZVAL(array_ptr);
110 array_init(array_ptr);
111 INIT_PZVAL(array_ptr);
113 IF_G(get_array) = array_ptr;
116 if(!IF_G(post_array)) {
117 ALLOC_ZVAL(array_ptr);
118 array_init(array_ptr);
119 INIT_PZVAL(array_ptr);
121 IF_G(post_array) = array_ptr;
124 if(!IF_G(cookie_array)) {
125 ALLOC_ZVAL(array_ptr);
126 array_init(array_ptr);
127 INIT_PZVAL(array_ptr);
129 IF_G(cookie_array) = array_ptr;
132 Z_STRLEN(new_var) = val_len;
133 Z_STRVAL(new_var) = estrndup(*val, val_len);
134 Z_TYPE(new_var) = IS_STRING;
136 var_len = strlen(var);
137 raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
138 strcpy(raw_var, "RAW_");
139 strlcat(raw_var,var,var_len+5);
141 php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
143 php_strip_tags(*val, val_len, NULL, NULL, 0);
145 *new_val_len = strlen(*val);
149 PHP_FUNCTION(my_get_raw)
155 zval *array_ptr = NULL;
157 if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
163 array_ptr = IF_G(get_array);
166 array_ptr = IF_G(post_array);
169 array_ptr = IF_G(post_array);
177 if(zend_hash_find(HASH_OF(array_ptr), var, var_len+5, (void **)&tmp) == SUCCESS) {
178 *return_value = **tmp;
179 zval_copy_ctor(return_value);