vlambda博客
学习文章列表

CSRF漏洞前世今生

大家有没有发现随着时间的推移,提及CSRF漏洞的次数越来越少,而且OWASP十大网站安全风险排名也早已经没有CSRF的踪影了,是开发人员的风险意识越来越高了吗?还是该漏洞已经被历史淘汰了?下面开始随着我来具体探寻一下CSRF漏洞的前世今生吧

一、CSRF介绍

跨站请求伪造 (CSRF),也称为 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。跟跨网站脚本(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任

1、攻击细节

跨站请求攻击,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证只能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

2、具体示例

 <img src="https://bank.example.com/withdraw?account=Alice&amount=1000&for=Badman" />

如果有账户名为张三的用户访问了恶意站点,而他之前刚访问过银行不久,登录信息尚未过期,那么他就会损失1000资金。

透过例子能够看出,攻击者并不能通过CSRF攻击来直接获取用户的账户控制权,也不能直接窃取用户的任何信息。他们能做到的,是欺骗用户的浏览器,让其以用户的名义运行操作。

二、常见防御手段

1、令牌同步模式

令牌同步模式(英语:Synchronizer token pattern,简称STP)。原理是:当用户发送请求时,服务器端应用将令牌(英语:token,一个保密且唯一的值)嵌入HTML表格,并发送给客户端。客户端提交HTML表格时候,会将令牌发送到服务端,令牌的验证是由服务端实行的。令牌可以通过任何方式生成,只要确保随机性和唯一性(如:使用随机种子【英语:random seed】的哈希链 )。这样确保攻击者发送请求时候,由于没有该令牌而无法通过验证。Django框架默认带有STP功能:

<form method="post">
    {% csrf_token %}
</form>

渲染后的效果如下:

<form method="post">
    <input type="hidden" name="csrfmiddlewaretoken" value="KbyUmhTLMpYj7CD2di7JKP1P3qmLlkPt" />
</form>

STP能在HTML下运作顺利,但会导致服务端的复杂度升高,复杂度源于令牌的生成和验证。因为令牌是唯一且随机,如果每个表格都使用一个唯一的令牌,那么当页面过多时,服务器由于生产令牌而导致的负担也会增加。而使用会话(英语:session)等级的令牌代替的话,服务器的负担将没有那么重。

2、检查Referer字段

3、添加校验token

4、引入Same-Site Cookie 属性

谷歌浏览器于 3 月 29 日开始支持开始支持新的 cookie 属性,其他流行的浏览器也紧随其后,现在有一个解决方案。它称为Same-Site cookie 属性。开发人员现在可以指示浏览器控制 cookie 是否与第三方网站发起的请求一起发送 - 通过使用 SameSite cookie 属性,这是比拒绝发送 cookie 更实用的解决方案。

为 cookie 设置 Same-Site 属性非常简单。它只包括向 cookie 添加一条指令。只需添加 'SameSite=Lax' 或 'SameSite=Strict' 就足够了!

Set-Cookie: CookieName=CookieValue; SameSite=Lax;
Set-Cookie: CookieName=CookieValue; SameSite=Strict;

三、为什么CSRF变少了?

Chrome 80 默认将没有设置SameSite设置为SameSite=Lax,默认Post方式将不发送Cookie,仅Get请求会携带Cookie,这导致CSRF可利用的场景越来越少,所以CSRF漏洞也越来越少的人去提及了。

SameSite一共有三种值:

①、Strict Scrict最为严格,完全禁止第三方Cookie,跨站点时,任何情况下都不会发送Cookie

②、Lax Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。

③、None 网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效

关闭SameSite属性操作方法

  • 谷歌浏览器地址栏输入:chrome://flags/
  • 找到:SameSite by default cookies、Cookies without SameSite must be secure
  • 设置上面这两项设置成 Disable