引言
一直以来,大家都熟悉Oauth2.0相关处理流程,在日常使用中也经常遇见,比如网站使用微信授权认证登录,或者用微博的授权登录等,相信对于对接过微信网页授权的童鞋这个也再熟悉不过。
之前公司的产品登录认证,也是采用了该模式,而目前却发现有人发现了登录系统下的漏洞,利用该漏洞违规登录。
一、登录认证
1.1、OAuth2.0的四种授权模式
日常使用过程中,我们接触到的最多的即是授权码模式。Oauth2.0一共提出了4种授权方式,分别是以下四种:
考虑到安全性,最高的即为授权码模式,避免了向第三方暴露令牌。
而之前公司的产品登录有部分业务直接使用的access_token,实际上采用了第二种方式。所以从根本上来说,已经存在了一定的安全性问题。
同时有部分产品,接入的是授权码模式,流程如下。
1.2、auth code登录认证流程
1.3、直接颁发凭证
相比上述的1.2的流程,少了code换取access_token的流程,在有认证服务端登录后,直接重定向到产品的链接上带上凭证access_token
二、漏洞的产生
2.1、漏洞产生
在1.2和1.3的各自流程中,第8步,用户在认证服务端认证成功之后重定向到业务的链接中,如果此时被用户拦截获取到该链接,然后颁发给其他任何人,对方都可以直接登录该产品。即使是先颁发code,然后换取access_token的流程,依旧可以直接登录。
2.2、漏洞利用
当前发现有用户将自己的账号租用给他人使用,而为了避免直接将自己的账号密码信息提供给他人,于是设计出来一个定制化的登录系统,该系统将在认证服务端账号登录之后重定向的链接进行拦截,然后提供给第三方,这样第三方就可以直接登录进产品。即使第三方可以进到个人中心查看账号,但因为无法更改账号(更新账号信息需要原账号认证),所以不用担心安全问题
2.3、漏洞原因
以上问题暴露的根本问题是,认证服务关于凭证的颁发与校验,其实是不知道申请的客户端到底是谁的。
三、认识state
3.1、疑惑
刚开始碰到上述问题的时候,觉得十分疑惑,我们一直在用的微信网页授权方式,理论上也存在上述漏洞,那怎么可能还一直没有被提出呢?
觉得不太可能,肯定是自身漏掉了某些细节。于是重新翻看相关文档,发现提到了另一个参数:state
3.2、state
以微信网页授权的文档为例,请求获取code的链接示例如下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
基础参数含义:
appid:标明当前应用身份
redirect_uri:授权完成回跳地址
response_type:返回类型
scope:授权模式
state:重定向后会带上 state 参数
即state表示应用方请求过去的是什么,最后授权完成的时候,会原样带回来。
3.3、使用state
起初一直在琢磨认证服务端,如何去识别申请凭证的客户端与校验的客户端是否一致,后面发觉其实思路错了。
这里认证客户端是否前后一致,其实是应用方应该处理的。于是就有了state参数。
state由应用端随机产生,并与当前的客户端会话进行绑定。然后请求认证服务时带上该参数。认证服务在授权后,附带上该state参数重定向到应用端地址,此时应用端再判断state是否与当前客户端的会话有过绑定。如果一致则再去进行下一步流程
关于state解释:http://www.rfcreader.com/#rfc6749_line1098
state这里标注出来的必要级别为:RECOMMENDED
同时提到了关于利用state参数防止CSRF攻击:http://www.rfcreader.com/#rfc6749_line2569
四、尝试修复
4.1、认证服务识别客户端
鉴于上述问题,早期思考了一种快速的解决方案,即认证服务端判断客户端IP。
1. 颁发凭证时,认证服务端记录用户IP,与凭证做关联。
2. 校验凭证时,应用端同时传递过来用户IP
3. 认证服务端判断传递过来的IP与原先颁发凭证时记录的IP是否一致,不一致则不通过
问题:该方案在测试的时候发现,如果用户所在的网络环境有多个出口IP,容易造成校验不通过。因此无法实施
4.2、应用端识别客户端
设想:参考state,应用端在申请登录认证时,同时提交state参数,做客户端认证,保证前后申请与认证方一致
五、思考
针对Oauth2.0,之前从未关注过state参数的作用。各种接入文档对于该参数的描述也是optional,也并未提及到该参数使用的具体目的,也就忽略了其作用。
对于此类标准的解决方案,还是得注重文档,明晰作用,解决方案涉及到的着重点,应该更加仔细琢磨