大家如果对Oauth还不是很了解可以先看下这篇文章https://www.cnblogs.com/maoxiaolv/p/5838680.html

我这篇博客主要是总结一下安全测试过程中遇到Oauth2.0有哪些可能存在的漏洞,以及如何去测试。

Oauth2.0协议流程:

(A)用户打开客户端以后,客户端要求用户给予授权。(比如说你登陆淘宝,但是不想注册淘宝账户,于是淘宝说你可以用QQ登陆哟,于是说好,这个时候淘宝将你引导至QQ的认证服务器)

(B)用户同意给予客户端授权。(这个时候你在手机上弹出是否授权,你点击是,这个时候会返回一个授权码给淘宝,为什么是返回给淘宝呢?因为第一步中发送的认证服务器中会带有一个重定向url,是淘宝自己的)

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。(淘宝拿着这个授权码再去找认证服务器)

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。(淘宝取人授权码无误后,发放accesstoken令牌)

(E)客户端使用令牌,向资源服务器申请获取资源。(淘宝拿着令牌就可以访问QQ资源服务器)

(F)资源服务器确认令牌无误,同意向客户端开放资源。(QQ资源服务器对比令牌无误后开放资源)

上面有些细节没讲(例如url一般是怎样的),但不影响我们的测试。

这里还要科普两个知识点:

1.并不是什么网站都可以想QQ要授权的,比如说淘宝想和QQ搞这Oauth,必须先在QQ(服务提供商)那里进行注册,淘宝需要提供以下三个东西

  1)应用程序名称

  2)应用程序网站

  3)回调URL

  注册完成后,QQ会给淘宝两个东西

  1)Client ID (用于在构建上面B步骤中的请求url,这样QQ才知道是什么网站在找我要授权吧)

  2)Client Secret(也是淘宝要给QQ的东西,Client ID谁都知道可以伪造,这东西只有QQ和淘宝知道,至于是怎么给的还不知道)

2.上面的C、D两个步骤属于授权过程,Oauth2.0提供了四种授权模式

  • 授权码授权模式(Authorization Code Grant)
  • 隐式授权模式(Implicit Grant)
  • 密码授权模式(Resource Owner Password Credentials Grant)
  • 客户端凭证授权模式(Client Credentials Grant)

  

 Oauth2.0协议本身没有什么问题,只是开发人员在实现授权过程中没有严格安装协议规定来,可能会导致一些常见的问题

 其中主要是前三种可能存在问题,先以授权码授权模式为例将下流程吧:

授权码模式:

(A)用户访问客户端,客户端将用户引导向认证服务器。

(B)用户选择是否给予客户端授权。

(C)如用户给予授权,认证服务器将用户引导向客户端指定的redirection uri,同时加上授权码code。

(D)客户端收到code后,通过后台的服务器向认证服务器发送code和redirection uri。

(E)认证服务器验证code和redirection uri,确认无误后,响应客户端访问令牌(access token)和刷新令牌(refresh token)。

请求示例

(A)步骤:客户端申请认证的URI(淘宝请求QQ)  

https://www.example.com/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx

参数说明:

  response_type:授权类型,必选项,此处的值固定为"code"
  client_id:客户端的ID,必选项
  redirect_uri:重定向URI,必选项
  scope:申请的权限范围,可选项
  state:任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。

(C)步骤:服务器回应客户端的URI(用户点击授权后,QQ引导用户访问A步骤中指定的重定向url,并带着授权码和state)

https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xxx

参数说明:

  code:授权码,必选项。授权码有效期通常设为10分钟,一次性使用。该码与客户端ID、重定向URI以及用户,是一一对应关系。
  state:原样返回客户端传的该参数的值。

(D)步骤:客户端向认证服务器申请令牌(淘宝带着接收到C步骤中的请求后,用授权码发送下面的请求去找QQ认证服务器要token)

https://www.example.com/v1/oauth/token?client_id=CLIENT_ID&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=CALLBACK_URL

参数说明:

  client_id:表示客户端ID,必选项。
  grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
  code:表示上一步获得的授权码,必选项。
  redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。

注意:协议里没有提及client_secret参数,建议可以使用此参数进行客户端的二次验证。

(E)步骤:响应(D)步骤的数据

    {
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}

参数说明:

  access_token:访问令牌,必选项。
  token_type:令牌类型,该值大小写不敏感,必选项。
  expires_in:过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  refresh_token:更新令牌,用来获取下一次的访问令牌,可选项。
  scope:权限范围,如果与客户端申请的范围一致,此项可省略。

使用场景

    • 授权码模式是最常见的一种授权模式,在oauth2.0内是最安全和最完善的。
    • 适用于所有有Server端的应用,如Web站点、有Server端的手机客户端。
    • 可以得到较长期限授权。

授权码授权模式常出现的安全问题是A步骤中,由于开发者没有严格按照协议来,请求中没有带上state,可能造成账户劫持的问题。正常情况下,淘宝先生成一个state并放在session中,然后再A步骤中的请求中带上state,QQ返回url带有授权码和state的链接给淘宝,淘宝这个时候需要在后台对比这个state是否和session中的一样,用来防止csrf攻击(这里将的有点啰嗦,实际上就是csrf嘛)。如果开发者在开发中没有使用state,我们也应该怎样测试呢?

1.确认A步骤中是否带有state,如果没有该参数则存在漏洞

2.准备AB两个账号,A是攻击者,B是受害者,两个都登陆的情况下,当然是不同的浏览器下喽(这里有个场景限制,就是绑定账户的地方才有,比如说我有各淘宝账户,但是要记住账号密码登陆很麻烦,我将他绑定到QQ,以后就可以直接用QQ登陆啦)

3.A点击绑定QQ,然后用打开burp抓包,点击授权,一步一步forward,知道遇到请求中带有授权码的请求,复制该请求后drop掉,因为code一般都是一次性的

4.拿去B账户的浏览器中打开(实际攻击中就是csrf嘛),会发现B账户绑定了A账户的QQ,以后A就可以用自己的QQ登陆B的淘宝了。

隐身授权模式:

A)客户端将用户引导向认证服务器。

(B)用户决定是否给于客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端指定的”重定向URI",并在URI的Hash部分包含了访问令牌。

(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

(F)浏览器执行上一步获得的脚本,提取出令牌。

(G)浏览器将令牌发给客户端。

请求示例

(A)步骤:客户端发出请求

https://www.QQ.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx

参数说明

  response_type:授权类型,此处的值固定为"token",必选项。
  client_id:客户端的ID,必选项。
  redirect_uri:重定向的URI,必选项。
  scope:权限范围,可选项。
  state: 任意值,认证服务器会原样返回,用于抵制CSRF(跨站请求伪造)攻击。

(C)步骤:认证服务器响应客户端的请求url

https://www.example.com/callback#access_token =ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600&state=xxx

参数说明

  access_token:访问令牌,必选项。
  token_type:令牌类型,该值大小写不敏感,必选项。
  expires_in:过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
  scope:权限范围,如果与客户端申请的范围一致,此项可省略。
  state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

使用场景

    • 适用于所有无Server端配合的应用
    • 如手机/桌面客户端程序、浏览器插件。
    • 基于JavaScript等脚本客户端脚本语言实现的应用。

这里主要讲下隐式授权和授权码授权的区别:

两者主要是应用场景不同,授权码授权模式中淘宝是有自己的server端的,也就是说淘宝有自己的账户,只是想和QQ绑定而已。而隐式授权模式适用于比如说QQ自己的其他服务,比如英雄杀这种网页游戏,假设它自己有没有单独的server端,那么就可以使用隐式授权模式找QQ的其他服务要授权(这里有点说不清楚哈,大家意会,其实也不一定是QQ自己的其他服务,比如说我自己开了各三国杀的网站游戏,我不想要自己的服务器端,因为用户可能不想麻烦再注册账户,那么我用隐式授权模式实现QQ的开发的Oauth服务,这样用户就可以直接用QQ的账户登陆啦)

说完大家就可以发现一个问题就是,隐式授权模式可能就不存在账户劫持的问题了,因为我(三国杀)都没有账户你怎么劫持呢?但是这里有个其他的问题:

这是上面A步骤和C步骤发送的两个请求

A   https://www.QQ.com/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read&state=xxx
C   https://www.example.com/callback#access_token =ACCESS_TOKEN&state=xyz&token_type=example&expires_in=3600&state=xxx

C步骤中的请求链接实际上来源A请求中的redirect_uri参数(用于指定重定向的链接),最为关键的地方是C请求中带有access_token,那么实际场景就是当state参数不存在的时候又可以进行csrf攻击了,伪造redirect_uri就好了,但正常情况下
QQ至少会对redirect_uri的域名做校验吧,所以不能随便重定向,需要找到受信任的网站下的xss漏洞,然后重定向获取劫持access_token即可
可以发现隐式授权如果存在问题一般是指服务提供商没有做好redirect_uri的校验,同时呢开发人员也没有加上state参数。
密码模式授权:这个没什么好说的,就是需要用户输入QQ的账号密码。判断是否存在漏洞就是看下有没有爆破漏洞 最后我还想说下sso(单点登陆的问题),sso和Oauth还是有区别的,sso主要是指比如我说登陆企业的OA后,我在OA里面再登陆企业邮箱啊、jira啊、wiki啊等等都不用再输入账号密码了,这就是单点登陆。
sso存在的问题主要是盗取access_token后登陆他人账户,原因主要没有对redirect_uri做校验:
场景一:和上面Oauth隐身授权模式的攻击手法一样,厂商只对域名做了校验,我们找到白名单中的域名下的xss漏洞进行利用就好了
场景二:厂商没有做任何校验,这里和Oauth有些区别,sso不同的公司实现其他可能都有些不同,根据开发者的安全意识而异,所以可能对redirect_uri没有任何校验,这样利用起来就方便很多了,可以直接跳转到www.evil.com,同时这里还可以尝试javascript:alert(1)进行xss 不能在写了,早上来就写这个,工作还没干呢

Oauth2.0安全问题浅谈的更多相关文章

  1. Zabbix4.0安装浅谈

    一.此篇文章存在意义 针对超级小白,大神绕过 在zabbix官网https://www.zabbix.com/download里,需要数据库,但是并没有指导小白的我们如何安装数据库,此文章包含了Mys ...

  2. 0基础浅谈反射型xss(2)

    0x1:回顾前文疑惑“先闭合,在构造” 上一篇,我们说到了xss的一个触发精髓,“先闭合,在构造”,对于前面的先闭合,我们来简单的解释一下:   首先说,为什么要闭合? 因为HTML标签都是成对出现的 ...

  3. 0基础浅谈反射型xss (1)

    0X1:在学习xss之前,先快速学习相关的HTML代码 1.  <input>标签 文本域用法: <input  type="text" /> Type的作 ...

  4. [C#]6.0新特性浅谈

    原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...

  5. 浅谈Android Studio3.0更新之路(遇坑必入)

    >可以参考官网设置-> 1 2 >> Fantasy_Lin_网友评论原文地址是:简书24K纯帅豆写的我也更新一下出处[删除]Fa 转自脚本之家 浅谈Android Studi ...

  6. 浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释

    浅谈linux中shell变量$#,$@,$0,$1,$2,$?的含义解释 下面小编就为大家带来一篇浅谈linux中shell变量$#,$@,$0,$1,$2的含义解释.小编觉得挺不错的,现在就分享给 ...

  7. 浅谈[0,1]区间内的n个随机实数变量中增加偏序关系类题目的解法

    浅谈[0,1]区间内的n个随机实数变量中增加偏序关系类题目的解法 众所周知,把[0,1]区间内的n个随机.相互独立的实数变量\(x_i\)之间的大小关系写成一个排列\(\{p_i\}\),使得\(\f ...

  8. Spring5.0源码学习系列之浅谈BeanFactory创建

    Spring5.0源码学习系列之浅谈BeanFactory创建过程 系列文章目录 提示:Spring源码学习专栏链接 @ 目录 系列文章目录 博客前言介绍 一.获取BeanFactory主流程 二.r ...

  9. Spring5.0源码学习系列之浅谈循环依赖问题

    前言介绍 附录:Spring源码学习专栏 在上一章的学习中,我们对Bean的创建有了一个粗略的了解,接着本文浅谈Spring循环依赖问题,这是一个面试比较常见的问题 1.什么是循环依赖? 所谓的循环依 ...

随机推荐

  1. python之基于libsvm识别数字验证码

    1. 参考 字符型图片验证码识别完整过程及Python实现 2.图片预处理和手动分类 (1)分析图片 from PIL import Image img = Image.open('nums/ttt. ...

  2. 手机号流量统计---Mapreduce项目分析

    文档显示: 每行依次是 ~手机号~上行流量~下行流量 需求分析: 需要统计各自的手机号,及上行.下行.总流量 具体做法: 1.定义map输入输出类型 通常情况下map的输入的key-value就是lo ...

  3. 动态sql与静态sql的区别

    首先,所谓SQL的动态和静态,是指SQL语句在何时被编译和执行,二者都是用在SQL嵌入式编程中的,这里所说的嵌入式是指将SQL语句嵌入在高级语言中,而不是针对于单片机的那种嵌入式编程. 静态SQL,在 ...

  4. PostgreSQL自学笔记:7 插入、更新与删除数据

    7 插入.更新与删除数据 7.1 插入数据 先创建表person: create table person( id int not null, name char(40) not null defau ...

  5. MongDB 数据结构

    Object  ID :Documents 自生成的 _id String: 字符串,必须是utf-8 Boolean:布尔值,true 或者false (这里有坑哦~在我们大Python中 True ...

  6. 如何使用RestTemplate访问restful服务

    一. 什么是RestTemplate 传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient.不过此种方法使用起来太过繁琐.spring提供了一种简单便捷的模板类 ...

  7. redis日志格式

    在redis.conf中,在大概65行左右有个loglevel # 指定日志记录级别# Redis总共支持四个级别:debug.verbose.notice.warning,默认为verbose# d ...

  8. 顺序表的原理与python中的list类型

    数据是如何在内存中存储的? 在32位的计算机上,1个字节有8位,内存寻址的最小单位就是字节.假设我们有一个int类型的值,它从0x10开始,一个int占据4个字节,则其结束于0x13. 那么数据类型有 ...

  9. HTML5_canvas_填充文本,描边文本

    canvas 文本相关 填充文本 pen.fillText("HelloWorld", 100, 100);        文本的(100, 100) 在文本基线处 文本样式 pe ...

  10. vue引入外部.css文件,webpack将其与.vue中的样式混合打包了,怎么办?

    我使用vue-cli搭自己的博客,希望引入公共样式: // main.js import './assets/styles/common.css' 我本来是希望webpack打包后,能将这个样式独立打 ...