CI的CSRF的改造
admin
2023-01-19 16:41:55
0

CI的CSRF是有缺陷的。

只要同时开俩个不同的涉及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

    

        ::selection { background-color: #E13300; color: white; }
        ::-moz-selection { background-color: #E13300; color: white; }

        body {
            background-color: #fff;
            margin: 40px;
            font: 13px/20px normal Helvetica, Arial, sans-serif;
            color: #4F5155;
        }

        a {
            color: #003399;
            background-color: transparent;
            font-weight: normal;
        }

        h2 {
            color: #444;
            background-color: transparent;
            border-bottom: 1px solid #D0D0D0;
            font-size: 19px;
            font-weight: normal;
            margin: 0 0 14px 0;
            padding: 14px 15px 10px 15px;
        }

        code {
            font-family: Consolas, Monaco, Courier New, Courier, monospace;
            font-size: 12px;
            background-color: #f9f9f9;
            border: 1px solid #D0D0D0;
            color: #002166;
            display: block;
            margin: 14px 0 14px 0;
            padding: 12px 10px 12px 10px;
        }

        #body {
            margin: 0 15px 0 15px;
        }

        p.footer {
            text-align: right;
            font-size: 11px;
            border-top: 1px solid #D0D0D0;
            line-height: 32px;
            padding: 0 10px 0 10px;
            margin: 20px 0 0 0;
        }

        #container {
            margin: 10px;
            border: 1px solid #D0D0D0;
            box-shadow: 0 0 8px #D0D0D0;
        }
    




    

Welcome to CodeIgniter!

                                                                                                                                                                                                                                                                                         " value="" />                                               
用户名:
密  码:
             


相关内容

热门资讯

德国总理:美国正在被伊朗羞辱 德国之声4月27日报道,德国总理默茨在访问一所学校时表示,在当前的持续冲突中,伊朗领导层正试图羞辱美...
理响中国|“长”歌以行,风云激... 光阴如梭,东方潮阔。这里是中国的长三角,世界的长三角。无论过去、现在还是未来,这片土地都因时代而生,...
白宫:特朗普及其国安团队开会讨... 新华社华盛顿4月27日电 美国白宫新闻秘书莱维特27日在记者会上证实,总统特朗普及其国家安全团队当天...
人民日报刊文:日本放开杀伤性武... 日本放开杀伤性武器出口推高地缘冲突风险(国际论坛)常思纯《人民日报》(2026年04月28日 第 0...
医疗保障法草案二审:明确生育保... 满足多样化健康保障需求本报记者 彭 波4月27日,医疗保障法草案二审稿提请十四届全国人大常委会第二十...
天津一景区发生自转旋翼机事故1... 澎湃新闻记者 吕新文中国民用航空华北地区管理局4月22日公布《豪客通航“10•1”天津长芦汉盐旅游区...
卡塔尔埃米尔与美国总统特朗普通... 当地时间24日,卡塔尔埃米尔塔米姆与美国总统特朗普通电话,重点就中东地区局势以及伊朗与美国谈判问题交...
男子30年前被扣押2859克黄... 澎湃新闻记者 王鑫家住辽宁省大连市的潘永嘉近日向澎湃新闻反映称,三十年前,他在大连周水子机场被盖州市...
商务部:取消反制欧盟两家金融机... 中华人民共和国商务部令二〇二六年 第1号鉴于欧盟已取消对中国两家金融机构的制裁措施,现公布《关于取消...
过去24小时共有5艘船只通过霍... 总台记者当地时间24日获悉,过去24小时内,共有5艘船只通过霍尔木兹海峡,其中包括一艘伊朗油轮。(总...