CSRF 的传统修复方式
几天前,在阅读一篇极为专业的渗透测试报告时,发现了安全人员汇报了一个严重又常见的问题:CSRF 跨站请求伪造,诚然由于开发者的疏忽,产生 CSRF 的问题的确比较严重,好在发现的早我们可以尽早修复。安全人员是这样建议的:
The application should implement anti-CSRF tokens into all requests that perform actions which change the application state or which add/modify/delete content. An anti-CSRF token should be a long randomly generated value unique to each user so that attackers cannot easily brute-force it. It is important that anti-CSRF tokens are validated when user requests are handled by the application. The application should both verify that the token exists in the request, and also check that it matches the user’s current token. If either of these checks fails, the application should reject the request.
使用 anti-CSRF token 是防御 CSRF 的有效手段之一,安全人员的建议也很照本宣科的,很多 web 框架与编程语言都类似的实现方式,例如:
<form method="POST" action="/profile">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
...
</form>
或者使用 cookie / meta 与 ajax 全局设置,例如:
// 在 HTML 里面塞入这个 meta
<meta name="csrf-token" content="{
{ csrf_token() }}">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
**核心思路是,使用一个由服务器派发的 token,在前端进行状态修改时,也同时提交这个 token(往往会放在 html form 的 input 中,或者 ajax header 中),这时候服务端验证该 token 是否是之前所生成的,以此来判断这个请求是否被允许。**所以,当用户点击 hacker 所提供的三方网站时,这些恶意网站无论如何也无法获取到之前服务端生成 token,这样的话,即使请求可以发送至服务端,也不会通过验证。关于 CSRF 与 anti-CSRF Token 的具体机制本篇不再赘述,请参考这篇文章,此外,防范 CSRF 是一个稍微复杂的实践,还可以使用 referer、origin 等其他手段进行深度防御,而且一定是根据具体现状的考虑。</