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!