小编典典

X-Requested-With标头服务器是否足以防止Ajax驱动的应用程序受到CSRF的攻击?

ajax

我正在开发一个完全由ajax驱动的应用程序,其中所有请求都通过一个基本上等于一个主控制器的主控制器,该主控制器看起来像这样:

if(strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    fetch($page);
}

这通常足以防止跨站点请求伪造吗?

当没有随每个请求刷新整个页面时,具有旋转令牌是很不方便的。

我想我可以在每次请求时都将唯一令牌作为全局javascript变量传递和更新-但是以某种方式感到笨拙并且似乎本质上不安全。

编辑-也许像用户的UUID这样的静态令牌总比没有好?

编辑#2-正如 The Rook
指出的那样,这可能是一个令人毛骨悚然的问题。我已经阅读了两种方式的猜测,并听到了关于低版本Flash可用于这种恶作剧的遥远的耳语。由于我对此一无所知,因此我向所有可以解释这是CSRF风险的人悬赏。否则,我会将其交给
Artefacto 。谢谢。


阅读 308

收藏
2020-07-26

共1个答案

小编典典

我会说就足够了。如果允许跨域请求,那么您将注定要失败,因为攻击者可能会使用Javascript来获取CSRF令牌并将其用于伪造的请求中。

静态令牌不是一个好主意。每个会话至少应生成一次令牌。

EDIT2 Mike毕竟不对,抱歉。我没有正确阅读链接到的页面。它说:

一个简单的跨站点请求是这样的:[…]不使用HTTP请求设置自定义标头(例如X-Modified等)。

因此,如果您设置了X-Requested- With,则该请求必须是预先执行的,除非您响应OPTIONS授权跨站点请求的飞行前请求,否则该请求将无法通过。

编辑 Mike是正确的,从Firefox
3.5开始,允许跨站点XMLHttpRequests
。因此,您还必须检查Origin标题(如果存在)是否与您的站点匹配。

if (array_key_exists('HTTP_ORIGIN', $_SERVER)) {
    if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN'])
        doStuff();
}
elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) &&
        (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'))
    doStuff();
2020-07-26