PHP/Yii 项目中的 CSRF

CSRF in a PHP/Yii project

我有一个 yii (php) 项目,现在我想测试它是否可以抵御 csrf 攻击。

代码如下所示:

if (!Yii::app()->request->isAjaxRequest)){
   die("error");
} else { 
   // Do stuff
}

现在,如果我在 Firebug 中调用 URL,它会起作用("Do stuff" 被执行)。

$.get("example.com/foo", function(data){
    // Works - no error
});

但是,如果我在浏览器中调用完全相同的 URL,我会得到 "error",因为 Yii::app()->request->isAjaxRequest将是错误的。

这是否意味着,我的应用程序可以安全抵御 CSRF 攻击,或者有什么方法可以让 "Yii::app()->request->isAjaxRequest" 认为它是一个真正的 Ajax-Request?

非常感谢!

简答:您误解了 CSRF 的含义。

长答案:CSRF 是关于保护 POST 请求,包括 AJAX 提出的请求。这是通过创建一个随机生成的令牌来完成的,该令牌将作为隐藏的表单字段呈现在页面上,将其添加到请求中,以便在处理表单的其余部分之前对其进行验证。如果您正在进行 AJAX POST 调用,您需要手动将 CSRF 令牌添加到请求中。当 POST 请求中缺少 CSRF 令牌时,框架会抛出异常。

isAjaxRequest 属性 只是检查特定的 http header。你不应该依赖它,也就是说它不应该被用来保护访问。

isAjaxRequest的代码如下:

public function getIsAjaxRequest()
{
    return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
}

它似乎在检查 X-Requested-With HTTP header is set. This is actually a valid defence for CSRF because it is a header that cannot be sent cross-domain, without the consent of CORS. Yes, an attacker with cURL 是否可以通过设置此 header 来欺骗 AJAX 请求,但这对它们在 CSRF 攻击中没有好处,因为它们不会让用户的 cookie 一起发送。

此方法的唯一缺点是您只能使用它来保护来自 CSRF 的 AJAX 请求,而不是普通的 Web 表单 POSTs,因为您无法设置 headers使用此机制。

如果您需要保护 Web 表单 POST,那么您需要实施 Synchronizer Token Pattern 之类的解决方案。这是您生成加密安全令牌服务器端并将其与用户的 session 相关联的地方。然后在每个表单 POST 上检查此密钥,因为您将其包含在隐藏的表单字段中。这可以防止 CSRF,因为攻击者无法从页面读取令牌。