Php 为什么codeigniter2没有';t以更安全的方式存储csrf_散列,例如会话?

Php 为什么codeigniter2没有';t以更安全的方式存储csrf_散列,例如会话?,php,security,codeigniter,csrf,codeigniter-2,Php,Security,Codeigniter,Csrf,Codeigniter 2,为什么生成的CSRF保护令牌没有像建议的那样通过会话保存和使用?目前在CI2中,CSRF保护机制(安全级)如下: 1.在_CSRF_set_hash()函数中为CSRF令牌生成唯一值: $this->csrf_hash = md5(uniqid(rand(), TRUE)); 2.将该令牌插入表单隐藏字段(使用form_open helper) 3.用户提交表单,服务器通过POST获取令牌。CI在输入类中的“\u sanitize\u globals()”函数中执行令牌验证: $this

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

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

$this->csrf_hash = md5(uniqid(rand(), TRUE));
2.将该令牌插入表单隐藏字段(使用form_open helper)

3.用户提交表单,服务器通过POST获取令牌。CI在输入类中的“\u sanitize\u globals()”函数中执行令牌验证:

$this->security->csrf_verify();
4.安全类的函数“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;
}

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

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

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

在使用CodeIgniter会话类时,有两种方法:通过cookie存储数据,或者将数据存储在数据库中。[参考:]

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

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

编辑:

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

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

基本上,函数csrf\u verify()只检查cookie和输入POST是否正确 相等,这两者都可以通过简单的javascript创建。如果你对安全性很认真的话,你应该三思而后行


来源:

有几个原因

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

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

因为CSRF代表“跨站点请求伪造”这种攻击的一个例子是,如果您知道有人在
http://somedomain.com/wordpress
。你可以让他们点击一个新的链接,这真的会在他们的wordpress控制面板上做些坏事。CSRF旨在防止这种情况的发生,验证所采取的行动是否是用户的意图


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

我认为一个邪恶的站点不能为“好”站点设置cookie值:既不能读取也不能写入其他域的cookie。或者我遗漏了什么?也许你是对的,也许这只是会话使用的另一种方法。只是好奇它是否同样安全。我对我的问题做了修改,请检查一下。谢谢我不太同意,它是在检查cookies和input post,这是非常多余的,因为两者都可以以某种方式进行更改。基本上,只需设置cookie并输入相同的内容,这可以通过少量javascript轻松完成。我相信这是CodeIgniter的安全漏洞。来源:马修:请看我下面的评论。我很想知道,使用这种方法是否足够。这可能超出了我的理解范围,但如果cookie设置为仅安全,那么它不应该受到这种特定类型的攻击。事实上,我和你的想法一样:)问题是,一个邪恶的网站(www.badsite.com)可以吗为好站点(www.goodsite.com)设置cookie,以便cookie中的令牌与邪恶站点发送的POST中的令牌相匹配,并且好站点将接收邪恶站点设置的POST和cookie?不知怎的,从答案来看,我认为你可以将cookie设置到其他域(从evilsite),并期望它会通过浏览器自动发送到好的站点。即使是这样,如果一个邪恶的站点有一些受害者从一个邪恶的站点下载的javascript代码,那么javascript代码IMHO可能会改变相关的cookie:正确,没有第三方网站可以手动更改cookie,但cookie可以通过恶意javascript进行更改。请查看下面的@tpae答案和评论。您希望我看到什么?CSRF并不是身份验证的替代品,但它——再加上良好的身份验证——可以防止已经通过身份验证的用户进行意外操作。。。