为什么codeigniter2不以更安全的方式(例如会话)存储csrf_hash?

发布于 2024-12-25 17:24:55 字数 1549 浏览 2 评论 0原文

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

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;
}

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

Why generated CSRF protection token is not saved and used via SESSION like suggested here? Currently in CI2, the CSRF protection mechanism (in Security class) is such:

1.generate a unique value for CSRF token in _csrf_set_hash() function:

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

2.Insert that token into form hidden field (using form_open helper)

3.A user submits the form and a server gets the token via POST. The CI performs token verification in "_sanitize_globals()" function in Input class:

$this->security->csrf_verify();

4.The function "csrf_verify" of Security class just checks is POST['token'] set and is POST['token'] equal to 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;
}

Why not to store token in session? IMHO just checking is POST['token'] non-empty and is equal to COOKIE['token'] is not sufficient because both might be sent by an evil site.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

背叛残局 2025-01-01 17:24:55

有几个原因。

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

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

There are a few reasons.

First being that storing the token in the cookie is not insecure. Anti-CSRF is not designed to prevent automated posting of content, it is to prevent forging a request as an authenticated user (via an iframe, or a simple link). So long as the token itself is not guessable, that is enough.

The second being if it's stored in the session, then you need sessions enabled, this also causes usability issues because if your session times out and you have a page open with a form, you can no longer submit that form (even if the form itself doesn't require a logged in state).

望她远 2025-01-01 17:24:55

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

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

在使用 CodeIgniter Session 类时,有两种选择:通过 cookie 存储数据,或者将它们存储在数据库中。 [参考:http://codeigniter.com/user_guide/libraries/sessions.html ]

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

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

编辑:

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

根据该文章,它说具有会话独立随机数的 CSRF 保护(由CodeIgniter)存在 CSRF + MITM 攻击漏洞(中间人攻击):

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

几乎,函数 csrf_verify() 仅检查 cookie 和输入 POST 是否为
equal,两者都可以通过简单的 javascript 创建。如果您认真对待安全性,那么在使用此功能时应该三思而后行。

来源:这种中间人攻击是如何工作的?

In CodeIgniter, they don't use native PHP sessions anywhere in the code.

The example you provided is shown using native PHP sessions.

While using CodeIgniter Session class, there's either: store data via cookies, or store them in database. [ reference: http://codeigniter.com/user_guide/libraries/sessions.html ]

While checking for csrf data, it wouldn't make sense to check the database every time, it would be plausible to store them in the cookies.

I think it's generally safe, but there are some windows of vulnerability with this method. Perhaps encrypting it with server side key might help increase the security...

EDIT:

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

According to the article, it says that CSRF Protection with Session independent nonce (used by CodeIgniter) has a vulnerability to CSRF + MITM Attack (Man-in-the-Middle):

The attacker can set the CSRF cookie using Set-Cookie, and then supply
a matching token in the POST form data. Since the site does not tie
the session cookies to the CSRF cookies, it has no way of determining
that the CSRF token + cookie are genuine (doing hashing etc. of one of
them will not work, as the attacker can just get a valid pair from the
site directly, and use that pair in the attack).

Pretty much, the function csrf_verify() only checks whether the cookie and input POST is
equal, which both can be created through simple javascript. You should think twice about using this if you are serious about security.

Source: How does this Man-In-The-Middle attack work?

命硬 2025-01-01 17:24:55

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

即使有人知道如何伪造 cookie 和隐藏表单字段以进行匹配,也无法跨站点执行此操作,并且无论如何也无法防止伪造。

Because CSRF stands for "Cross-site Request Forgery." An example of this attack would be if you knew someone had a wordpress install at http://somedomain.com/wordpress. You could get them to click on a new link, which would really go do something bad over on their wordpress control panel. CSRF was designed to prevent this, verifying that the action taken was intended by the user taking the action.

Even if someone knew how to forge both the cookie and the hidden form field to match, there's no way to do that cross-site, and there's no forgery to prevent anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文