对任何可以由浏览器处理的请求使用CSRF保护。如果您只创建一个由非浏览器客户端使用的服务,那么可以禁用CSRF保护。
CSRD防护和JSON
一个常见的问题是“我需要保护由javascript发出的JSON请求吗?”简单的回答是,看情况而定。但是,必须非常小心,因为存在可能影响JSON请求的CSRF漏洞。例如,恶意用户可以使用以下形式创建一个带有JSON的CSRF:
<form action="https://bank.example.com/transfer" method="post" enctype="text/plain">
<input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'>
<input type="submit" value="Win Money!"/>
</form>
这会产生如下的Json结构
{
"amount": 100,
"routingNumber": "evilsRoutingNumber",
"account": "evilsAccountNumber",
"ignore_me": "=test"
}
如果应用程序不验证Content-Type,那么它将暴露给这个漏洞。验证Content-Type的Spring MVC应用程序仍然可以通过更新URL后缀以.json结尾,如下所示:
<form action="https://bank.example.com/transfer.json" method="post" enctype="text/plain">
<input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'>
<input type="submit"
value="Win Money!"/>
</form>
CSRF和无状态浏览器应用程序
如果我的应用程序是无状态的怎么办?那并不一定意味着你受到了保护。事实上,如果用户对于给定的请求不需要在web浏览器中执行任何操作,那么他们很可能仍然容易受到CSRF攻击。
例如,考虑一个应用程序使用包含所有状态的自定义cookie进行身份验证,而不是使用JSESSIONID。当发起CSRF攻击时,自定义cookie将与请求一起发送,发送方式与前面示例中的JSESSIONID cookie相同。此应用程序很容易受到CSRF攻击。
使用基本身份验证的应用程序也容易受到CSRF攻击。该应用程序很容易受到攻击,因为浏览器将自动在任何请求中包含用户名和密码,其方式与前面示例中发送JSESSIONID cookie的方式相同。
需要CSRF防护的场景
logging in
HTTP请求的登录应该被防止CSRF攻击。这样恶意用户就无法读取被攻击者的敏感信息。攻击执行方式为
-
恶意用户使用恶意用户的凭据执行CSRF登录,受害者现在被验证为恶意用户。
-
然后,恶意用户就会欺骗受害者,让他们访问被破坏的网站,并输入敏感信息
-
这些信息与恶意用户的帐户相关联,因此恶意用户可以使用自己的凭证登录并查看受害者的敏感信息
logging out
登出CSRF攻击也会获取到用户敏感信息,参考资料.
csrf和会话超时
通常,期望的CSRF令牌存储在会话中。这意味着一旦会话过期,服务器将找不到预期的CSRF令牌并拒绝HTTP请求。解决超时有多种选择,每种都需要进行权衡。
- 减轻超时的最好方法是在表单提交时使用JavaScript请求CSRF令牌。然后使用CSRF令牌更新表单并提交。
- 另一种选择是使用一些JavaScript让用户知道他们的会话即将过期。用户可以单击一个按钮继续并刷新会话。
- 最后,期望的CSRF令牌可以存储在一个cookie中。这允许期望的CSRF令牌在会话之后继续存在
文件上传
保护多部分请求(文件上传)免受CSRF攻击会导致先有鸡还是先有蛋的问题。为了防止发生CSRF攻击,必须读取HTTP请求的主体以获得实际的CSRF令牌。然而,读取主体意味着文件将被上传,这意味着外部站点可以上传文件。
两种解决方案:
- 将csrf的令牌放在body中
- 将csrf的令牌放在url中
第一种选择是在请求体中包含实际的CSRF令牌。通过在主体中放置CSRF令牌,将在执行授权之前读取主体。这意味着任何人都可以在您的服务器上放置临时文件。但是,只有授权用户才能提交由您的应用程序处理的File。通常,这是推荐的方法,因为临时文件上传对大多数服务器的影响应该可以忽略不计。
如果不允许未经授权的用户上传临时文件,那么另一种方法是将期望的CSRF令牌作为查询参数包含在表单的action属性中。这种方法的缺点是查询参数可能泄露。一般来说,最好的做法是将敏感数据放置在阀体或标头内,以确保不会泄漏
隐藏Http方法
在某些应用程序中,表单参数可用于覆盖HTTP方法。例如,下面的表单可用于将HTTP方法视为delete
而不是post
。
<form action="/process" method="post">
<!-- ... -->
<input type="hidden" name="_method" value="delete"/>
</form>
覆盖HTTP方法发生在Filter中。这个Filter必须放在Spring Security的支持之前