浏览器之CSRF攻击

什么时CSRF攻击

CSRF 全称 Cross Site Request Forgery 又称为 “跨站请求伪造”,指黑客引用用户打开黑客的网站,再黑客的网站,利用用户的登录状态发起跨站请求,简单的讲,CSRF就是黑客利用了用户登陆状态,并通过第三方的站点来做一些坏事。

一些例子

1.自动发起GET请求

<!DOCTYPE html>
<html>
 <body>
 <h1>⿊客的站点:CSRF攻击演示</h1>
 <img src="https://time.geekbang.org/sendcoin?user=hacker&number=100">
 </body>
</html>

转账接口隐藏在图片里,页面被加载的时候就会对img请求,结果就发起转账了。

2.自动发起POST请求

<!DOCTYPE html>
<html>
<body>
 <h1>⿊客的站点:CSRF攻击演示</h1>
 <form id='hacker-form' action="https://time.geekbang.org/sendcoin" method=POST>
 <input type="hidden" name="user" value="hacker" />
 <input type="hidden" name="number" value="100" />
 </form>
 <script> document.getElementById('hacker-form').submit(); </script>
</body>
</html>

黑客构建了一个隐藏表单,用户打开站点后,表单被自动提交。

3.引诱用户点击链接

 <img width=150 src=http://images.xuejuzi.cn/1612/1_161230185104_1.jpg> </img> </div> <div>
 <a href="https://time.geekbang.org/sendcoin?user=hacker&number=100" taget="_blank">
 点击下载美⼥照⽚
 </a>
</div>

用户一旦点击,发起转账。

和XSS不同的是,CSRF攻击不需要将恶意代 码注⼊⽤户的⻚⾯,仅仅是利⽤服务器的漏洞和⽤户的登录状态来实施攻击。

如何防止CSRF攻击

起CSRF攻击的三个必要条件:

  • 第⼀个,⽬标站点⼀定要有CSRF漏洞;
  • 第⼆个,⽤户要登录过⽬标站点,并且在浏览器上保持有该站点的登录状态;
  • 第三个,需要⽤户打开⼀个第三⽅站点,可以是⿊客的站点,也可以是⼀些论坛

免受CSRF攻击有一下几个途径

1.充分利用好Cookie的SameSite属性

这个属性可以实现从第三方站点发起请求的时候禁止Cookie的发送。

SameSite通常有 Strict,Lax,None三个值。

Strict最严格: 浏览器完全禁止第三方Cookie,简单说如果如果你从A的页面访问了B的资源,而B的Cookie设置了SameSite=Strict 那么这些Cookie时不会被送到B的服务器上的。只有你在B的站点请求B的资源,才会带上这些Cookie

Lax相对宽松一点,跨站点的情况下,从第三方站点的链接打开和从第三方的站点提交Get方式和表单,这两种方式会携带Cookie。 但是如果在第三方站点中使用POST方法或者通过 Img,Iframe等标签加载url,这些场景不会携带Cookie

如果是None,任何情况下都会发送Cookie。

2.验证请求来源站点

在服务端验证请求来源的站点。

需要使用HTTP头中 Referer和Origin属性。 虽然可以通过Referer来告诉服务器但是有一些场景不适用,所以也可以不上传Referere值,具体参考 Referer Policy.

服务端请求中 Referer并不是很可靠,因此标准委员会有制定了 Origin属性,一些场合,比如XMLHTTPRequest、Fetch发起跨站请求或者通过POST方法发送请求时,都会带上Origin。

由于安全考虑Origin只携带域名不携带路径。

服务器的策略优先判断Origin 如果没有 再根据情况判断是否用Referer

3. CSRF Token

大致分为两步:

第一步: 浏览器向服务器发起请求,服务器生成一个 CSRF TOKEN, 其实就是一个字符串,然后将字符串植入返回页面中,例如如下例子:

<!DOCTYPE html>
<html>
<body>
 <form action="https://time.geekbang.org/sendcoin" method="POST">
 <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9ajDlcn">
 <input type="text" name="user">
 <input type="text" name="number">
 <input type="submit">
 </form>
</body>
</html>

第二部:浏览器发起转账请求,那么就会携带上CSRF Token然后服务器会验证是否合法。

第三方网站因为无法获得TOken的值,即使发出了请求也会因为Token错误而被拒绝。

Mark24

Everything can Mix.