OAuth是一套关于授权的网络标准
现在一般使用的是OAuth 2.0
OAuth
OAuth的核心是向第三方应用授予权限,也就是我们常见的第三方登陆
它的优势在于可以方便的控制权限等,不赘述
OAuth一共有四种授权方式
授权码(authorization-code)
授权码也就是我们常用的流程
它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
这里以一次实际登陆A网站的流程为例
首先我们通常的登陆是这样
然后我们选择微信登陆
然后可以看到是请求了这样的一个数据包,然后同时会生成一个二维码,即让你用微信进行授权
先看一下OAuth相关各个字段的含义
- response_type=code 表示使用的是授权码方式
- redirect_uri=http%3A%2F%2Fi.nosec.org% 是微信授权以后的回调地址
- scope=snsapi_login 代表授权的范围,可能会存在修改scope越权的问题
- appid是身份校验,标志你来自哪个应用
- state字段用于防范一种特殊的CSRF,具体后面解释
扫码授权以后会发生跳转,也就是下面这个包
code参数极为OAuth中的授权码
我们讲一下这个state参数
state在这里用于防范CSRF,如果没有这个state或者未对state做校验会发生什么呢
看一下利用方式,假设A是被攻击网站,我是攻击者1
2
3
4我用自己的微信扫码授权,然后跳转到redirect_uri
我拦截这个url,https://A.com/xxx?code=081vdwbI1SU6i008y0&state=xxxxxxx
删除state参数后用于钓鱼
受害者点击后会在A网站登陆我的账号
但如果对state参数进行校验的话,受害者就会登陆失败
利用的成果是受害者登陆攻击者指定的账号
这种称为登陆型CSRF吧,一种脑洞大开的攻击方式
A网站拿到授权码以后在后端请求获取令牌进行后续操作即可
后端的交互请求如下1
2
3
4
5
6https://b.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
client_secret是获取令牌的一个校验,其实就是一个秘钥,是你在申请接入OAuth时分配给的,能够避免攻击者取得code后自己去请求获得令牌
隐藏式(implicit)
也就是隐藏了获取授权码的过程,直接获取令牌
通常请求格式如下1
2
3
4
5https://b.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
同意授权后B会返回1
https://a.com/callback#token=ACCESS_TOKEN
注意,令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在”中间人攻击”的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险
(上面这段是引用
解释起来锚点就是一个能快速返回的点,是一个前端的概念,并不会作为参数发送给服务器
但是可以被js取得,然后a通过js取得锚点的令牌就行通信即可
所以该种方式令牌完全在后台进行了传输,避免了中间人攻击
而OAuth设计的目标之一就是要让不支持https的网站使用
所以才会出现授权码这种东西
这里就再谈一下code的设计
为什么code没有防范使用http协议的网站被中间人攻击呢?
因为code拿到以后是要生成令牌的,但是OAuth中code只能使用一次
一个code被使用两次会导致令牌失效,所以即便被中间人窃取
因为受害者肯定会立刻生成令牌,所以并不能产生危害,顶多是授权失败
密码式(password)
密码式就是更进一步的隐藏式,直接通过账号密码进行授权
通常请求格式如下1
2
3
4
5https://oauth.b.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
密码式不需要跳转,直接返回令牌
该方式风险较大,提一下,不常见
客户端凭证(client credentials)
最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌
简单说这东西是提供给系统本身不是提供给用户使用的
常见请求格式为1
2
3
4https://oauth.b.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
也是直接返回令牌
参考链接
http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
https://www.chrisyue.com/security-issue-about-oauth-2-0-you-should-know.html