如何防御CSRF攻击

http://tommwq.tech/blog/2020/12/28/294

1 会话和cookie

会话(session)这一术语通常有两重含义。首先,会话表示客户端和服务器端之间的一系列交互。一次交互可以理解为一次请求-应答过程。在这一系列交互过程中,往往需要保存一些和交互有关的信息(比如登录信息),这些信息有时叫做通讯上下文(context)。会话也可以用来指代通讯上下文。出于安全性和性能的考虑,通讯上下文通常保存在服务器端。为了让服务器可以同时服务多个客户端,区分不同客户端的上下文,服务器为每个客户端分配一个编号,根据编号访问对应的上下文。如果采用单一TCP连接通讯模式,套接字文件描述符(socket fd)往往成为天然的会话编号。套接字和客户端的绑定关系由操作系统维护,因此客户端不需要保存自己的会话编号。但是对于短连接和多连接通讯模式,套接字文件描述符的方案行不通了,客户端必须保存会话编号,并在每次请求时携带这一编号。

HTTP采用的就是短连接和多连接通讯模式。HTTP协议没有规定如何传递会话编号,具体打实现方式由客户端(浏览器/HTML/JavaScript)和服务器来决定。HTTP请求包括请求头和请求体,二者都可以传递会话编号。如果保存在请求头中,可以通过URL(或URL参数)传递、可以通过cookie传递,也可以通过自定义HTTP头传递。如果保存在请求体中,可以按照自定义消息格式传递。按照目前行业通行的做法,会话编号通过cookie传递。

2 会话编号泄漏和盗用

服务器根据会话编号来寻找请求的上下文,并根据上下文中包含的认证和授权信息,执行客户端请求的操作。如果第三方获得了会话编号,或者构造一个包含会话编号的请求,就可以盗用实际客户的身份,欺骗并要求服务器执行一些特权操作。HTTPS可以在大多数情况下(除了HTTPS中间人攻击)保护会话编号不被第三方窃取。但如果会话编号保存在cookie中,HTTPS无法阻止攻击者构造一个包含会话编号的请求。这种攻击方式就是CSRF(Cross Site Request Forgery,也叫做Session Riding)跨站请求伪造。

3 CSRF如何盗用会话

为了理解CSRF,我们将HTTP请求分为3部分:header(除了cookie)、cookie、body。在发送HTTP请求的时候,header和body是由HTML/JavaScript控制的,cookie是浏览器自动发送的。假设我们登录网站www.good.com,浏览器生成cookie。这时候点击连接www.good.com/somepath,浏览器会自动将good.com关联的cookie加入到HTTP请求头中。假如我们访问了网站www.bad.com,页面中包含 <img src="www.good.com/transfer_money"/> ,浏览器将自动发送请求到good.com,同样携带good.com的cookie。good.com收到请求后,从cookie中得到会话编号,发现用户已经认证和授权,执行请求。这样,bad.com就盗用了客户的身份。

4 如何防御CSRF

从上一节的分析可以看到,要避免会话被盗用,就需要将会话编号从cookie中移除,或者增加额外的校验方式。从cookie中移除会话编号的方案,对于一些Web应用改动较大。这里介绍增加额外校验的方式。方法就是使用令牌。服务器生成一个随机令牌,通过HTML发送给浏览器,比如在<form>中增加一个隐藏标签 <input type="hidden" value="some_random_number" name="csrf_token" /> ,或者通过JavaScript写入请求头。这种方案叫做Synchronizer Token Pattern,适用于Web服务器数量较少的情况。采用Synchronizer Token Pattern时,令牌不得通过cookie传递。

如果服务器数量较多,在多个服务器之间分发令牌比较困难,可以采用Encrypted Token Pattern。这种方法将会话编号和时间戳生通过服务器端密钥加密,生成令牌。验证时对令牌进行解密,如果解密成功并且会话编号和时间戳匹配,验证通过。Encrypted Token Pattern的好处是不用在服务器端保存状态。

如同账户密码登录校验,确认令牌匹配,并不一定要得到令牌内容。HMAC Based Token Pattern计算会话编号和时间键戳的信息摘要,得到令牌。令牌和时间戳一同发给浏览器。在验证时用同样的方法再次生成令牌。如果两个令牌一致,验证通过。采用这种方法时,最好采用SHA-256或安全性更强的HMAC函数。

在生成令牌时使用时间戳的目的是防止重放攻击(replay attack)。

5 HTTPS中间人攻击

HTTPS中间人攻击可以通过CA证书的数字签名进行防范,这里就不介绍了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值