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>