参考文章
CSRF: Cross Site Request Forgery
跨网站请求伪造
防范方法
Referer
通过浏览器在发送 http
请求的时候携带的一个字段 Referer
,这个字段包含了发送这个请求的来源网站,当攻击者伪造请求时,请求发送的来源网站将不会是例如 dongguanbank.cn
,而是该攻击网站的网址,因此,当服务端接受到一个转账请求的时候,可以通过增加一个拦截器,验证这个请求的 Referer
值来判断这个请求是否是来自本行网站
但是这种方法依然存在一个问题,Referer 的值是由浏览器提供的,并且不同浏览器可能在产生 Referer 值的实现上不同,可能存在风险,即浏览器本身的 Referer 实现存在漏洞。并且,对于一些版本较低的浏览器来说,已经有一些方法可以对 Referer 值进行篡改,完全可以通过将 Referer 的值替换成相应的目标网站的网址,来实现 CSRF 攻击。
而即使使用最新的版本的浏览器,依然存在其他问题。虽然黑客无法篡改 Referer 的内容,但是用户本身可能会在浏览器设置中限制 Referer 的使用从而隐藏自己的访问来源。此时用户的正常请求会因为没有包含 Referer 字段而被服务端判断为 CSRF 攻击,无法正常访问网站
Token
通过在和浏览器端建立会话 session
时,服务端生成并保存一个 token
在会话当中,当每次用户发送请求的时候,将 token
从会话中取出,与用户请求中的 token
进行验证。通过自动 token
,从而不需要将信息保存在本地的 cookies
中。
token 的问题在于,每次请求中都需要包含相应的 token,因此我们需要做到在每次请求中都将 token 加入到请求中,显然这样是非常麻烦,并且容易遗漏。因此往往是通过 JavaScript 在页面加载的时候遍历整个 Dom 树,将 token 加入到表单和链接标签中,但是另一方面,这样的方法又无法解决动态加载出来的页面内容的 token 添加问题。
此外,还有一个问题,token 本身也可能存在安全隐患,因为攻击者也可以通过在目标网站上发布链接来获取 token,从而利用这个token 来伪造请求进行 CSRF 攻击,因此服务端需要在添加 token 的时候,判断该链接是否链接到外网的,从而决定是否为该链接添加 token。另外, 攻击者也可以通过 Referer (包含 token 的访问来源)来获取 token,当然此时用户可以通过浏览器设置中禁用 Referer 来避免这种情况发生。
自定义属性
利用 Http
请求中的自定义属性,将 token
添加到自定义属性中,通过 XMLHttpRequest
统一为同一类请求添加 token。这样即可以非常方便的将 token
添加到请求当中,又避免了请求的地址(包含 token
)存放在本地的地址栏中,或者是通过 Referer
导致 token
的泄露问题。