我正在寻找一种(希望是直截了当的)方法来为Spring WebFlow 2上的应用程序构建添加CSRF保护。
首选可以很好地迁移到Spring WebFlow 3(发布时)的方法。
答案 0 :(得分:4)
阻止CSRF检查引用request.getHeader("referer");
以确保请求来自同一域的最简单方法。 CSRF Prevention Cheat Sheet已涵盖此方法。
在内存需求有限的嵌入式网络硬件上看到这种CSRF保护系统很常见,摩托罗拉在大多数硬件上使用这种方法。这不是最安全的CSRF保护,基于令牌的保护更好,但两个系统仍然可以用xss绕过。基于令牌的CSRF保护的最大问题是需要很多时间来返回并修复每个请求,您可能会错过一些请求。
实现此目的的一种安全方法是检查所有传入POST请求的引用者,并对敏感函数使用POST,例如更改密码,添加用户帐户,执行代码,进行配置更改。 GET应仅用于导航或搜索,基本上GET对于任何不会导致状态更改的内容都是安全的。
确保使用xss scanner测试您的网站。
答案 1 :(得分:2)
OWASP有一个很好的预防CSRF攻击的指南here:
检查Referer标头当然是最简单的,并且最好至少记录Referer是第三方或空的实例。然而,有一些缺点使得单独使用引用者是不可靠的:
幸运的是,WebFlow可以轻松实现自定义的唯一令牌每流调用CSRF过滤器(您可能不必修改任何视图/表单)!
首先,每当流程启动时使用FlowExectionListener创建一个新的随机令牌并将其存储在flowScope中。然后,每当发出事件信号时,验证提交的令牌(作为请求中的参数提交)是否等于存储在flowScope中的值。
然后,配置一个自定义FlowUrlHandler,它附加" _token"生成URL的参数,因此如果您一直使用$ {flowExecutionUrl}来引用您的流,则只要您自动POST / GET回流到您的流,就会附加该令牌。要从FlowUrlHandler内部从flowScope获取令牌,我不得不求助于使用RequestContextHolder
private String retrieveToken() {
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (requestContext == null) {
return null;
}
return (String) requestContext.getFlowScope().get(CsrfTokenFlowListener.TOKEN_NAME);
}
...
每当您为GET和POST输出$ {flowExecutionUrl}时,此方法都将包含CSRF令牌,如果您使用post-redirect-get,则可以确保CSRF令牌不会出现在网址栏。
我会警告不要只检查POST的CSRF令牌:
WebFlow和许多其他Web框架没有区分GET和POST - 默认情况下,除非您自己验证请求方法,否则您通常可以使用GET来执行POST操作(这将是一个很好的方法)无论如何)。因此,想要绕过CSRF过滤器的攻击者只需执行GET而不是POST。
编辑:在$ {flowExecutionUrl}中包含CSRF令牌时要注意的一个缺点是,CSRF令牌可能始终作为请求URL的一部分发送(因为它将是HTML表单的动作'属性),从不在POST正文中。在请求URL中包含敏感信息并不是很好,因为它更有可能记录在服务器/ ISP日志中。另一种方法是在包含CSRF令牌的每个表单中添加一个隐藏的输入,并仅强制执行POST请求。