CSRF攻击:陌生链接不要随便点

回顾: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的防御?
  • 充分利用好CookieSameSite属性

由于黑客会利用用户的登录状态来发起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 不正确而拒绝请求