use_xss_clean = (bool) Kohana::config('core.global_xss_filtering'); if (Input::$instance === NULL) { if (get_magic_quotes_runtime()) { set_magic_quotes_runtime(0); Kohana::log('debug', 'Disable magic_quotes_runtime! It is evil and deprecated: http://php.net/magic_quotes'); } if (get_magic_quotes_gpc()) { $this->magic_quotes_gpc = TRUE; Kohana::log('debug', 'Disable magic_quotes_gpc! It is evil and deprecated: http://php.net/magic_quotes'); } if (ini_get('register_globals')) { if (isset($_REQUEST['GLOBALS'])) { exit('Global variable overload attack.'); } $_REQUEST = array(); $preserve = array('GLOBALS', '_REQUEST', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER', '_ENV', '_SESSION'); foreach (array_diff(array_keys($GLOBALS), $preserve) as $key) { global $$key; $$key = NULL; unset($GLOBALS[$key], $$key); } Kohana::log('debug', 'Disable register_globals! It is evil and deprecated: http://php.net/register_globals'); } if (is_array($_GET)) { foreach ($_GET as $key => $val) { $_GET[$this->clean_input_keys($key)] = $this->clean_input_data($val); } } else { $_GET = array(); } if (is_array($_POST)) { foreach ($_POST as $key => $val) { $_POST[$this->clean_input_keys($key)] = $this->clean_input_data($val); } } else { $_POST = array(); } if (is_array($_COOKIE)) { foreach ($_COOKIE as $key => $val) { if ($key == '$Version' OR $key == '$Path' OR $key == '$Domain') continue; $_COOKIE[$this->clean_input_keys($key)] = $this->clean_input_data($val); } } else { $_COOKIE = array(); } Input::$instance = $this; Kohana::log('debug', 'Global GET, POST and COOKIE data sanitized'); } } public function get($key = array(), $default = NULL, $xss_clean = FALSE) { return $this->search_array($_GET, $key, $default, $xss_clean); } public function post($key = array(), $default = NULL, $xss_clean = FALSE) { return $this->search_array($_POST, $key, $default, $xss_clean); } public function cookie($key = array(), $default = NULL, $xss_clean = FALSE) { return $this->search_array($_COOKIE, $key, $default, $xss_clean); } public function server($key = array(), $default = NULL, $xss_clean = FALSE) { return $this->search_array($_SERVER, $key, $default, $xss_clean); } protected function search_array($array, $key, $default = NULL, $xss_clean = FALSE) { if ($key === array()) return $array; if ( ! isset($array[$key])) return $default; $value = $array[$key]; if ($this->use_xss_clean === FALSE AND $xss_clean === TRUE) { $value = $this->xss_clean($value); } return $value; } public function ip_address() { if ($this->ip_address !== NULL) return $this->ip_address; $keys = array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'); foreach ($keys as $key) { if ($ip = $this->server($key)) { $this->ip_address = $ip; break; } } if ($comma = strrpos($this->ip_address, ',') !== FALSE) { $this->ip_address = substr($this->ip_address, $comma + 1); } if ( ! valid::ip($this->ip_address)) { $this->ip_address = '0.0.0.0'; } return $this->ip_address; } public function xss_clean($data, $tool = NULL) { if ($tool === NULL) { $tool = Kohana::config('core.global_xss_filtering'); } if (is_array($data)) { foreach ($data as $key => $val) { $data[$key] = $this->xss_clean($val, $tool); } return $data; } if (trim($data) === '') return $data; if ($tool === TRUE) { $tool = 'default'; } switch ($tool) { case 'htmlpurifier': if ( ! class_exists('HTMLPurifier_Config', FALSE)) { require Kohana::find_file('vendor', 'htmlpurifier/HTMLPurifier.auto', TRUE); require 'HTMLPurifier.func.php'; } $config = HTMLPurifier_Config::createDefault(); $config->set('HTML', 'TidyLevel', 'none'); $data = HTMLPurifier($data, $config); break; default: $data = str_replace(array('&','<','>'), array('&amp;','&lt;','&gt;'), $data); $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data); $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data); $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8'); $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data); $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data); $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data); $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data); $data = preg_replace('#]*+>#i', '', $data); do { $old_data = $data; $data = preg_replace('#]*+>#i', '', $data); } while ($old_data !== $data); break; } return $data; } public function clean_input_keys($str) { $chars = PCRE_UNICODE_PROPERTIES ? '\pL' : 'a-zA-Z'; if ( ! preg_match('#^['.$chars.'0-9:_.-]++$#uD', $str)) { exit('Disallowed key characters in global data.'.$str); } return $str; } public function clean_input_data($str) { if (is_array($str)) { $new_array = array(); foreach ($str as $key => $val) { $new_array[$this->clean_input_keys($key)] = $this->clean_input_data($val); } return $new_array; } if ($this->magic_quotes_gpc === TRUE) { $str = stripslashes($str); } if ($this->use_xss_clean === TRUE) { $str = $this->xss_clean($str); } if (strpos($str, "\r") !== FALSE) { $str = str_replace(array("\r\n", "\r"), "\n", $str); } return $str; } }