Annotation of embedaddon/php/README.input_filter, revision 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>