Permalink
Browse files

Input Filter support. See README.input_filter for details.

@- Input Filter support added. See  README.input_filter. (Rasmus)
  • Loading branch information...
1 parent 0458bb5 commit 7429c2dc3f72ed9a6a41ccefc68595e76319cdae @rlerdorf rlerdorf committed Feb 19, 2003
Showing with 212 additions and 3 deletions.
  1. +188 −0 README.input_filter
  2. +3 −2 ext/mbstring/mb_gpc.c
  3. +1 −1 ext/mbstring/mbstring.c
  4. +5 −0 main/SAPI.c
  5. +5 −0 main/SAPI.h
  6. +1 −0 main/php_content_types.c
  7. +8 −0 main/php_variables.c
  8. +1 −0 main/rfc1867.c
View
@@ -0,0 +1,188 @@
+Input Filter Support in PHP5
+----------------------------
+
+XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
+and can be quite difficult to prevent. Whenever you accept user data
+and somehow display this data back to users, you are likely vulnerable
+to XSS hacks.
+
+The Input Filter support in PHP5 is aimed at providing the framework
+through which a company-wide or site-wide security policy can be
+enforced. It is implemented as a SAPI hook and is called from the
+treat_data and post handler functions. To implement your own security
+policy you will need to write a standard PHP extension.
+
+A simple implementation might look like the following. This stores the
+original raw user data and adds a my_get_raw() function while the normal
+$_POST, $_GET and $_COOKIE arrays are only populated with stripped
+data. In this simple example all I am doing is calling strip_tags() on
+the data. If register_globals is turned on, the default globals that
+are created will be stripped ($foo) while a $RAW_foo is created with the
+original user input.
+
+ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
+ zval *post_array;
+ zval *get_array;
+ zval *cookie_array;
+ZEND_END_MODULE_GLOBALS(my_input_filter)
+
+#ifdef ZTS
+#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
+#else
+#define IF_G(v) (my_input_filter_globals.v)
+#endif
+
+ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
+
+function_entry my_input_filter_functions[] = {
+ PHP_FE(my_get_raw, NULL)
+ {NULL, NULL, NULL}
+};
+
+zend_module_entry my_input_filter_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "my_input_filter",
+ my_input_filter_functions,
+ PHP_MINIT(my_input_filter),
+ PHP_MSHUTDOWN(my_input_filter),
+ NULL,
+ PHP_RSHUTDOWN(my_input_filter),
+ PHP_MINFO(my_input_filter),
+ "0.1",
+ STANDARD_MODULE_PROPERTIES
+};
+
+PHP_MINIT_FUNCTION(my_input_filter)
+{
+ ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
+
+ REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
+
+ sapi_register_input_filter(my_sapi_input_filter);
+ return SUCCESS;
+}
+
+PHP_RSHUTDOWN_FUNCTION(my_input_filter)
+{
+ if(IF_G(get_array)) {
+ zval_ptr_dtor(&IF_G(get_array));
+ IF_G(get_array) = NULL;
+ }
+ if(IF_G(post_array)) {
+ zval_ptr_dtor(&IF_G(post_array));
+ IF_G(post_array) = NULL;
+ }
+ if(IF_G(cookie_array)) {
+ zval_ptr_dtor(&IF_G(cookie_array));
+ IF_G(cookie_array) = NULL;
+ }
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(my_input_filter)
+{
+ php_info_print_table_start();
+ php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
+ php_info_print_table_row( 2, "Revision", "$Revision$");
+ php_info_print_table_end();
+}
+
+unsigned int my_sapi_input_filter(int arg, char *var, char *val, unsigned int val_len)
+{
+ zval new_var;
+ zval *array_ptr = NULL;
+ char *raw_var;
+ int var_len;
+
+ assert(val != NULL);
+
+ switch(arg) {
+ case PARSE_GET:
+ if(!IF_G(get_array)) {
+ ALLOC_ZVAL(array_ptr);
+ array_init(array_ptr);
+ INIT_PZVAL(array_ptr);
+ }
+ IF_G(get_array) = array_ptr;
+ break;
+ case PARSE_POST:
+ if(!IF_G(post_array)) {
+ ALLOC_ZVAL(array_ptr);
+ array_init(array_ptr);
+ INIT_PZVAL(array_ptr);
+ }
+ IF_G(post_array) = array_ptr;
+ break;
+ case PARSE_COOKIE:
+ if(!IF_G(cookie_array)) {
+ ALLOC_ZVAL(array_ptr);
+ array_init(array_ptr);
+ INIT_PZVAL(array_ptr);
+ }
+ IF_G(cookie_array) = array_ptr;
+ break;
+ }
+ Z_STRLEN(new_var) = val_len;
+ Z_STRVAL(new_var) = estrndup(val, val_len);
+ Z_TYPE(new_var) = IS_STRING;
+
+ var_len = strlen(var);
+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
+ strcpy(raw_var, "RAW_");
+ strlcat(raw_var,var,var_len+5);
+
+ php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
+
+ php_strip_tags(val, val_len, NULL, NULL, 0);
+
+ return strlen(val);
+}
+
+PHP_FUNCTION(my_get_raw)
+{
+ long arg;
+ char *var;
+ int var_len;
+ zval **tmp;
+ zval *array_ptr = NULL;
+ HashTable *hash_ptr;
+ char *raw_var;
+
+ if(zend_parse_parameters(2 TSRMLS_CC, "ls|l", &arg, &var, &var_len) == FAILURE) {
+ return;
+ }
+
+ switch(arg) {
+ case PARSE_GET:
+ array_ptr = IF_G(get_array);
+ break;
+ case PARSE_POST:
+ array_ptr = IF_G(post_array);
+ break;
+ case PARSE_COOKIE:
+ array_ptr = IF_G(post_array);
+ break;
+ }
+
+ if(!array_ptr) RETURN_FALSE;
+
+ /*
+ * I'm changing the variable name here because when running with register_globals on,
+ * the variable will end up in the global symbol table
+ */
+ raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
+ strcpy(raw_var, "RAW_");
+ strlcat(raw_var,var,var_len+5);
+ hash_ptr = HASH_OF(array_ptr);
+
+ if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
+ *return_value = **tmp;
+ zval_copy_ctor(return_value);
+ } else {
+ RETVAL_FALSE;
+ }
+ efree(raw_var);
+}
+
View
@@ -169,7 +169,7 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
break;
}
- _php_mb_encoding_handler_ex(array_ptr, res, separator, 0, 0 TSRMLS_CC);
+ _php_mb_encoding_handler_ex(arg, array_ptr, res, separator, 0, 0 TSRMLS_CC);
if (MBSTRG(http_input_identify) != mbfl_no_encoding_invalid) {
switch(arg){
@@ -199,7 +199,7 @@ MBSTRING_API SAPI_TREAT_DATA_FUNC(mbstr_treat_data)
/* }}} */
/* {{{ int _php_mb_encoding_handler_ex() */
-int _php_mb_encoding_handler_ex(zval *arg, char *res, char *separator, int force_register_globals, int report_errors TSRMLS_DC)
+int _php_mb_encoding_handler_ex(int data_type, zval *arg, char *res, char *separator, int force_register_globals, int report_errors TSRMLS_DC)
{
char *var, *val, *s1, *s2;
char *strtok_buf = NULL, **val_list = NULL;
@@ -342,6 +342,7 @@ int _php_mb_encoding_handler_ex(zval *arg, char *res, char *separator, int force
val_len = len_list[n];
}
n++;
+ val_len = sapi_module.input_filter(data_type, var, val, val_len TSRMLS_CC);
/* add variable to symbol table */
php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
if (convd != NULL){
View
@@ -1281,7 +1281,7 @@ PHP_FUNCTION(mb_parse_str)
encstr = estrndup(encstr, encstr_len);
- RETVAL_BOOL(_php_mb_encoding_handler_ex(track_vars_array, encstr, separator, (track_vars_array == NULL), 1 TSRMLS_CC));
+ RETVAL_BOOL(_php_mb_encoding_handler_ex(PARSE_STRING, track_vars_array, encstr, separator, (track_vars_array == NULL), 1 TSRMLS_CC));
if (encstr != NULL) efree(encstr);
if (separator != NULL) efree(separator);
View
@@ -823,6 +823,11 @@ SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zva
return SUCCESS;
}
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char *val, unsigned int val_len TSRMLS_DC))
+{
+ sapi_module.input_filter = input_filter;
+ return SUCCESS;
+}
SAPI_API int sapi_flush(TSRMLS_D)
{
View
@@ -178,6 +178,7 @@ SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry);
SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry);
SAPI_API int sapi_register_default_post_reader(void (*default_post_reader)(TSRMLS_D));
SAPI_API int sapi_register_treat_data(void (*treat_data)(int arg, char *str, zval *destArray TSRMLS_DC));
+SAPI_API int sapi_register_input_filter(unsigned int (*input_filter)(int arg, char *var, char *val, unsigned int val_len TSRMLS_DC));
SAPI_API int sapi_flush(TSRMLS_D);
SAPI_API struct stat *sapi_get_stat(TSRMLS_D);
@@ -238,6 +239,8 @@ struct _sapi_module_struct {
int (*get_target_uid)(uid_t * TSRMLS_DC);
int (*get_target_gid)(gid_t * TSRMLS_DC);
+
+ unsigned int (*input_filter)(int arg, char *var, char *val, unsigned int val_len TSRMLS_DC);
};
@@ -266,10 +269,12 @@ struct _sapi_post_entry {
#define SAPI_POST_HANDLER_FUNC(post_handler) void post_handler(char *content_type_dup, void *arg TSRMLS_DC)
#define SAPI_TREAT_DATA_FUNC(treat_data) void treat_data(int arg, char *str, zval* destArray TSRMLS_DC)
+#define SAPI_INPUT_FILTER_FUNC(input_filter) unsigned int input_filter(int arg, char *var, char *val, unsigned int val_len TSRMLS_DC)
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data);
SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader);
SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data);
+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter);
#define STANDARD_SAPI_MODULE_PROPERTIES
View
@@ -77,6 +77,7 @@ int php_startup_sapi_content_types(void)
sapi_register_post_entries(php_post_entries);
sapi_register_default_post_reader(php_default_post_reader);
sapi_register_treat_data(php_default_treat_data);
+ sapi_register_input_filter(php_default_input_filter);
return SUCCESS;
}
/* }}} */
View
@@ -226,12 +226,19 @@ SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
*val++ = '\0';
php_url_decode(var, strlen(var));
val_len = php_url_decode(val, strlen(val));
+ val_len = sapi_module.input_filter(PARSE_POST, var, val, val_len TSRMLS_CC);
php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
}
var = php_strtok_r(NULL, "&", &strtok_buf);
}
}
+SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
+{
+ /* TODO: check .ini setting here and apply user-defined input filter */
+ return val_len;
+}
+
SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
{
char *res = NULL, *var, *val, *separator=NULL;
@@ -314,6 +321,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)
*val++ = '\0';
php_url_decode(var, strlen(var));
val_len = php_url_decode(val, strlen(val));
+ val_len = sapi_module.input_filter(arg, var, val, val_len TSRMLS_CC);
php_register_variable_safe(var, val, val_len, array_ptr TSRMLS_CC);
} else {
php_url_decode(var, strlen(var));
View
@@ -805,6 +805,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler)
value = estrdup("");
}
+ sapi_module.input_filter(PARSE_POST, param, value, strlen(value) TSRMLS_CC);
safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC);
if (!strcmp(param, "MAX_FILE_SIZE")) {
max_file_size = atol(value);

0 comments on commit 7429c2d

Please sign in to comment.