Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application?
我正在开发一个完全由Ajax驱动的应用程序,其中所有的请求都通过一个基本上相当于主控制器的程序,它的基本结构如下:
1 2 3 |
这一般足以防止跨站点请求伪造吗?
当整个页面没有根据每个请求刷新时,使用一个旋转令牌是相当不方便的。
我想我可以在每个请求中传递和更新唯一的令牌作为一个全局javascript变量——但不知何故,这会让人觉得很笨拙,而且似乎天生就不安全。
编辑——也许静态令牌(比如用户的UUID)比什么都没有要好?
编辑2-正如Rook指出的,这可能是一个令人毛骨悚然的问题。我读过各种各样的猜测,也听到过一些遥远的耳语,说旧版本的flash可以用来对付这种恶作剧。因为我对此一无所知,所以我要对任何能解释这是一种CSRF风险的人发放奖金。否则,我就把它交给人造的。谢谢。
我说够了。如果跨域请求被允许,那么无论如何,你都会被判有罪,因为攻击者可以使用javascript来获取CSRF令牌,并在伪造的请求中使用它。
静态令牌不是一个好主意。每个会话至少应生成一次令牌。
伊迪丝2麦克毕竟不对劲,对不起。我没有正确阅读我链接到的页面。上面写着:
A simple cross-site request is one that: [...]
Does not set custom headers with the HTTP Request (such as X-Modified, etc.)
号
因此,如果您设置了
编辑Mike是对的,从火狐3.5开始,允许跨站点的xmlhttprequest。因此,您还必须检查存在的
1 2 3 4 5 6 7 | 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(); |
对。这是公认的CSRF保护方法。
https://www.owasp.org/index.php/cross-site_-request_-forgery_u(csrf)_-prevention_-craty_-sheet protecting_-rest_服务:_-use_-of-custom_-request_-headers
我不相信这是安全的。相同的源策略旨在防止来自不同域的文档访问从不同域返回的内容。这就是为什么XSRF问题首先存在的原因。一般来说,XSRF不关心响应。它用于执行特定类型的请求,如删除操作。在最简单的形式中,这可以通过一个格式正确的img标记来完成。您建议的解决方案将阻止这种最简单的形式,但不保护某人使用xmlhttp对象发出请求。您需要使用XSRF的标准预防技术。我喜欢在javascript中生成一个随机数,并将其添加到cookie和表单变量中。这确保代码也可以为该域编写cookie。如果您需要更多信息,请查看此条目。
另外,要预先清空有关xmlhttp不在脚本中工作的注释。我在firefox 3.5中使用以下代码从本地主机域中运行的HTML向Google发出请求。内容不会被返回,但是使用Firebug,您可以看到请求已经发出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var xmlhttp = false; if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { try { xmlhttp = new XMLHttpRequest(); } catch (e) { xmlhttp = false; } } if (!xmlhttp && window.createRequest) { try { xmlhttp = window.createRequest(); } catch (e) { xmlhttp = false; } } xmlhttp.open("GET","http://www.google.com", true); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4) { alert("Got Response"); alert(xmlhttp.responseText) } } xmlhttp.send(null) alert("test Complete"); |
号
您所做的是安全的,因为XMLHttpRequest通常不易受到跨站点请求伪造的攻击。
由于这是客户端的问题,最安全的方法是检查每个浏览器的安全架构:—)
(这是一个总结;我要添加这个答案,因为这个问题非常混乱,让我们看看投票结果如何)
简短回答:没有。任何攻击者都会使用Ajax攻击您的网站。您应该生成一个随机令牌,它的生存期很短,但不会太长,您将在每个Ajax请求期间对其进行更新。
您必须在JavaScript中使用一个令牌数组,因为您可能同时运行多个Ajax请求。
我不认为这能提供任何保护。攻击站点仍然可以使用