CI的CSRF是有缺陷的。
创新互联公司-专业网站定制、快速模板网站建设、高性价比进贤网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式进贤网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖进贤地区。费用合理售后完善,十年实体公司更值得信赖。
只要同时开俩个不同的涉及csrf的页面,
http://host/csrf1
http://host/csrf2
就会发现页面直接互相影响(问题1)。
即使同一页面也涉及这样的问题。
http://host/csrf1
http://host/csrf1
也会发现这样的问题(问题2)。
先解决简单问题2
只需要将配置 csrf_regenerate 设置为 false; 即是cookie过期或者被清掉。
$config['csrf_regenerate'] = FALSE;
解决复杂问题1:
一. 将system/core/Input 中的 验证代码过滤。
// CSRF Protection check if ($this->_enable_csrf === TRUE && ! is_cli()) { //$this->security->csrf_verify(); }
二. 改造Security类
class CI_Security { /** * Class constructor * * @return void */ public function __construct() { $this->charset = strtoupper(config_item('charset')); log_message('info', 'Security Class Initialized'); } public function start_csrf($class, $function) { // Is CSRF protection enabled? if (config_item('csrf_protection')) { if(!$class || !$function){ return ; } $this->_csrf_cookie_name = md5($class.'_'.$function); // CSRF config foreach (array( 'csrf_expire', 'csrf_token_name', //'csrf_cookie_name', ) as $key) { if (NULL !== ($val = config_item($key))) { $this->{'_'.$key} = $val; } } // Append application specific cookie prefix if ($cookie_prefix = config_item('cookie_prefix')) { //$this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name; } // Set the CSRF hash $this->_csrf_set_hash(); $this->csrf_set_cookie(); } } // -------------------------------------------------------------------- /** * CSRF Verify * * @return CI_Security */ public function csrf_verify($class, $function) { if (!config_item('csrf_protection')){ return ; } if(!$class || !$function){ return ; } $this->_csrf_cookie_name = md5($class.'_'.$function); // CSRF config foreach (array( 'csrf_expire', 'csrf_token_name', //'csrf_cookie_name', ) as $key) { if (NULL !== ($val = config_item($key))) { $this->{'_'.$key} = $val; } } // If it's not a POST request we will set the CSRF cookie if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') { //return $this->csrf_set_cookie(); $this->csrf_show_error(); } // Check if URI has been whitelisted from CSRF checks if ($exclude_uris = config_item('csrf_exclude_uris')) { $uri = load_class('URI', 'core'); foreach ($exclude_uris as $excluded) { if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string())) { return $this; } } } // Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate $valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]) && hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]); // We kill this since we're done and we don't want to pollute the _POST array unset($_POST[$this->_csrf_token_name]); // Regenerate on every submission? if (config_item('csrf_regenerate')) { // Nothing should last forever unset($_COOKIE[$this->_csrf_cookie_name]); $this->_csrf_hash = NULL; } $this->_csrf_set_hash(); $this->csrf_set_cookie(); if ($valid !== TRUE) { $this->csrf_show_error(); } log_message('info', 'CSRF token verified'); return $this; } // -------------------------------------------------------------------- /** * CSRF Set Cookie * * @codeCoverageIgnore * @return CI_Security */ public function csrf_set_cookie() { if (!config_item('csrf_protection')){ return ; } $expire = time() + $this->_csrf_expire; $secure_cookie = (bool) config_item('cookie_secure'); if ($secure_cookie && ! is_https()) { return FALSE; } setcookie( $this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie, config_item('cookie_httponly') ); log_message('info', 'CSRF cookie sent'); return $this; } // -------------------------------------------------------------------- /** * Set CSRF Hash and Cookie * * @return string */ protected function _csrf_set_hash() { if (!config_item('csrf_protection')){ return ; } if ($this->_csrf_hash === NULL) { // If the cookie exists we will use its value. // We don't necessarily want to regenerate it with // each page load since a page could contain embedded // sub-pages causing this feature to fail if (isset($_COOKIE[$this->_csrf_cookie_name]) && is_string($_COOKIE[$this->_csrf_cookie_name]) && preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1) { return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; } $rand = $this->get_random_bytes(16); $this->_csrf_hash = ($rand === FALSE) ? md5(uniqid(mt_rand(), TRUE)) : bin2hex($rand); } return $this->_csrf_hash; } }
三.使用实例
controller
security->csrf_verify(__CLASS__, __FUNCTION__); var_dump($_POST); exit; } $this->security->start_csrf(__CLASS__, __FUNCTION__); $csrf = array( 'name' => $this->security->get_csrf_token_name(), 'hash' => $this->security->get_csrf_hash() ); $data['csrf'] = $csrf; $this->load->view('csrf1', $data); } }
view
Welcome to CodeIgniter Welcome to CodeIgniter!