diff --git a/Security/Security.class.php b/Security/Security.class.php new file mode 100644 index 00000000..9e7e6141 --- /dev/null +++ b/Security/Security.class.php @@ -0,0 +1,264 @@ + | +// +----------------------------------------------------------------------+ + +// Source Code Highlight +/* Security Fix; Only dev +if(isset($_GET['show_source'])) +{ + highlight_file(__FILE__); + exit; +} +*/ + +/** + * Provides static functions to help protect against cross site scripting + * attacks and helps clean up the php environment upon initializing. + * + * Based upon Security library by http://kohanaphp.com/ + * + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + */ +define('PCRE_UNICODE_PROPERTIES', (bool) preg_match('/^\pL$/u', '?')); + +class Security +{ + // Instance of the security class. + protected static $instance; + protected $magic_quotes_gpc = FALSE; + + /** + * Gets the instance of the Security class. + * + * @return object Instance of Security + */ + public static function instance() + { + if(self::$instance === NULL) + { + //return new Security; + } + + //return self::$instance; + } + + + /** + * Constructor. Sanitizes global data GET, POST and COOKIE data. + * Also makes sure those pesty magic quotes and register globals + * don't bother us. This is protected because it really only needs + * to be run once. + * + * @return void + */ + protected function __construct() + { + if(self::$instance === NULL) + { + // Check for magic quotes + if(get_magic_quotes_runtime()) + { + // Dear lord!! This is bad and deprected. Sort it out ;) + set_magic_quotes_runtime(0); + } + + if(get_magic_quotes_gpc()) + { + // This is also bad and deprected. See http://php.net/magic_quotes for more information. + $this->magic_quotes_gpc = TRUE; + } + + // Check for register globals and prevent security issues from arising. + if(ini_get('register_globals')) + { + if(isset($_REQUEST['GLOBALS'])) + { + // No no no.. just kill the script here and now + exit('Illegal attack on global variable.'); + } + + // Get rid of REQUEST + $_REQUEST = array(); + + // The following globals are standard and shouldn't really be removed + $preserve = array('GLOBALS', '_REQUEST', '_GET', '_POST', '_FILES', '_COOKIE', '_SERVER', '_ENV', '_SESSION'); + + // Same effect as disabling register_globals + foreach($GLOBALS as $key => $value) + { + if( ! in_array($key, $preserve)) + { + global $$key; + $$key = NULL; + + unset($GLOBALS[$key], $$key); + } + } + } + + // Sanitize global data + + if(is_array($_POST)) + { + foreach($_POST as $key => $value) + { + $_POST[$this->clean_input_keys($key)] = $this->clean_input_data($value); + } + } + else + { + $_POST = array(); + } + + if(is_array($_GET)) + { + foreach($_GET as $key => $value) + { + $_GET[$this->clean_input_keys($key)] = $this->clean_input_data($value); + } + } + else + { + $_GET = array(); + } + + if(is_array($_COOKIE)) + { + foreach($_COOKIE as $key => $value) + { + $_COOKIE[$this->clean_input_keys($key)] = $this->clean_input_data($value); + } + } + else + { + $_COOKIE = array(); + } + + // Just make REQUEST a merge of POST and GET. Who really wants cookies in it anyway? + $_REQUEST = array_merge($_GET, $_POST); + + + self::$instance = $this; + } + } + + /** + * Cross site filtering (XSS). Recursive. + * + * @param string Data to be cleaned + * @return mixed + */ + public function xss_clean($data) + { + // If its empty there is no point cleaning it :\ + if(empty($data)) + return $data; + + // Recursive loop for arrays + if(is_array($data)) + { + foreach($data as $key => $value) + { + $data[$key] = $this->xss_clean($data); + } + + return $data; + } + + // Fix &entity\n; + $data = str_replace(array('&','<','>'), array('&','<','>'), $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'); + + // Remove any attribute starting with "on" or xmlns + $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data); + + // Remove javascript: and vbscript: protocols + $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); + + // Only works in IE: + $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); + + // Remove namespaced elements (we do not need them) + $data = preg_replace('#]*+>#i', '', $data); + + do + { + // Remove really unwanted tags + $old_data = $data; + $data = preg_replace('#]*+>#i', '', $data); + } + while ($old_data !== $data); + + return $data; + } + + /** + * Enforces W3C specifications to prevent malicious exploitation. + * + * @param string Key to clean + * @return string + */ + protected function clean_input_keys($data) + { + $chars = PCRE_UNICODE_PROPERTIES ? '\pL' : 'a-zA-Z'; + + if ( ! preg_match('#^[' . $chars . '0-9:_.-]++$#uD', $data)) + { + exit('Illegal key characters in global data'); + } + + return $data; + } + + /** + * Escapes data. + * + * @param mixed Data to clean + * @return mixed + */ + protected function clean_input_data($data) + { + if(is_array($data)) + { + $new_array = array(); + foreach($data as $key => $value) + { + $new_array[$this->clean_input_keys($key)] = $this->clean_input_data($value); + } + + return $new_array; + } + + if($this->magic_quotes_gpc === TRUE) + { + // Get rid of those pesky magic quotes! + $data = stripslashes($data); + } + + $data = $this->xss_clean($data); + + return $data; + } +} +?> \ No newline at end of file diff --git a/Security/index.php b/Security/index.php new file mode 100644 index 00000000..b5bb52b8 --- /dev/null +++ b/Security/index.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/index.php b/index.php index be78e57a..b6f15862 100644 --- a/index.php +++ b/index.php @@ -22,6 +22,24 @@ header("Location: install/"); } include ("GameEngine/config.php"); + //Change it to your own domain +if($_SERVER['HTTP_HOST'] != 'www.travianix.co.cc') +{ + header('location: http://www.travianix.co.cc'); + exit; +} + +error_reporting(E_ALL || E_NOTICE); + +if(file_exists('Security/Security.class.php')) +{ + require 'Security/Security.class.php'; + Security::instance(); +} +else +{ + die('Security: Please activate security class!'); +} include ("GameEngine/Database.php"); include ("GameEngine/Lang/".LANG.".php"); ?>