为什么codeigner2没有';t以更安全的方式存储csrf_hash,例如session


Why codeigniter2 doesn't store the csrf_hash in a more secure way, such as session?

为什么生成的CSRF保护令牌没有像这里建议的那样通过SESSION保存和使用?目前在CI2中,CSRF保护机制(安全级别)如下:

1.在_CSRF_set_hash()函数中为CSRF令牌生成唯一值:

$this->csrf_hash = md5(uniqid(rand(), TRUE));

2.将该令牌插入表单隐藏字段(使用form_open助手)

3.用户提交表单,服务器通过POST获取令牌。CI在Input类中的"_sanitize_globals()"函数中执行令牌验证

$this->security->csrf_verify();

4.Security类刚才检查的函数"csrf_verify"是否设置了POST['token'],并且POST['token']是否等于COOKIE['token'];

public function csrf_verify(){
// If no POST data exists we will set the CSRF cookie
if (count($_POST) == 0)
{
    return $this->csrf_set_cookie();
}
// Do the tokens exist in both the _POST and _COOKIE arrays?
if ( ! isset($_POST[$this->_csrf_token_name]) OR
         ! isset($_COOKIE[$this->_csrf_cookie_name]))
{
    $this->csrf_show_error();
}
// Do the tokens match?
if ($_POST[$this->_csrf_token_name] != $_COOKIE[$this->_csrf_cookie_name])
{
    $this->csrf_show_error();
}
// We kill this since we're done and we don't want to
// polute the _POST array
unset($_POST[$this->_csrf_token_name]);
// Nothing should last forever
unset($_COOKIE[$this->_csrf_cookie_name]);
$this->_csrf_set_hash();
$this->csrf_set_cookie();
log_message('debug', "CSRF token verified ");
return $this;
}

为什么不在会话中存储令牌?IMHO只是检查POST["token"]是否为非空并且等于COOKIE["token'"]是不够的,因为两者都可能是由邪恶网站发送的。

有几个原因。

首先,将令牌存储在cookie中并非不安全。反CSRF并不是为了防止内容的自动发布,而是为了防止作为经过身份验证的用户(通过iframe或简单链接)伪造请求。只要代币本身是不可猜测的,那就足够了。

第二种情况是,如果它存储在会话中,那么你需要启用会话,这也会导致可用性问题,因为如果你的会话超时,并且你打开了一个带有表单的页面,你就无法再提交该表单(即使表单本身不需要登录状态)。

在CodeIgniter中,它们在代码中的任何位置都不使用本机PHP会话。

您提供的示例是使用本机PHP会话显示的。

当使用CodeIgniterSession类时,可以通过cookie存储数据,也可以将数据存储在数据库中。[参考:http://codeigniter.com/user_guide/libraries/sessions.html]

在检查csrf数据时,每次都检查数据库是没有意义的,将它们存储在cookie中是合理的。

我认为它通常是安全的,但这种方法存在一些漏洞。也许用服务器端密钥加密它可能有助于提高安全性。。。

编辑:

https://code.djangoproject.com/wiki/CsrfProtection#Sessionindependentnonce

根据这篇文章,它说具有会话无关nonce的CSRF保护(由CodeIgniter使用)存在CSRF+MITM攻击(中间人)的漏洞:

攻击者可以使用set cookie设置CSRF cookie,然后提供POST表单数据中的匹配令牌。由于站点不绑定会话cookie到CSRF cookie,它无法确定CSRF令牌+cookie是真实的(对其中一个进行哈希等它们将不起作用,因为攻击者只能从站点,并在攻击中使用该对)。

函数csrf_verify()几乎只检查cookie和输入POST是否equal,两者都可以通过简单的javascript创建。如果你对安全性很认真,你应该三思而后行。

来源:"中间人"的攻击是如何运作的?

因为CSRF代表"跨站点请求伪造"。这种攻击的一个例子是,如果你知道有人在http://somedomain.com/wordpress安装了wordpress。你可以让他们点击一个新的链接,这会在他们的wordpress控制面板上造成不好的结果。CSRF旨在防止这种情况的发生,验证所采取的行动是由采取行动的用户准备的。

即使有人知道如何伪造cookie和隐藏的表单字段来匹配,也没有办法跨网站进行,也没有伪造的方法可以防止。