OAuth2基础与安全解析

-- 基础 --

概念

  • 简介: OAuth是一种授权框架, 允许 网站/应用 申请 另一个网站/应用上用户 的有限访问权限
    例子: 微信/QQ扫描第三方登录
  • 认证流程(通用)
    客户端请求授权: 客户端应用(如"百度") 向资源所有者(用户) 申请访问其在第三方平台(如"微信") 的特定资源(如用户头像、邮箱), 申请中需明确客户端身份、访问范围等信息
    用户批准授权: 用户通过授权服务器(第三方平台的认证系统)的界面, 明确同意或拒绝客户端的访问请求, 若同意, 授权服务器会生成"授权证据"(如授权码/证书等) 并返回给客户端
    客户端获取访问令牌: 客户端将用户的"授权证据"提交给授权服务器, 同时验证自身身份(如通过client_secret, 但若为公开客户端, 则无需提供client_secret), 授权服务器验证通过后, 发放访问令牌(Access Token)
    客户端访问资源: 客户端携带访问令牌访问资源服务器(存储用户数据的服务器), 资源服务器验证令牌有效性/权限后, 返回相应数据
  • 认证模式:
    OAuth定义了多种授权类型, 其中 授权码模式 和 隐式授权类型(已过时, 设计初衷是用于纯前端页面) 最常用
  • 机密客户端/公开客户端
    授权码模式中可处理 机密客户端和公开客户端
    公开客户端对比机密客户端的区别在于 其通常不可存储client_secret, 或存储可能会存在很大的泄露风险
    公开客户端常见于 纯前端页面(无法存储client_secret) APP(因为安装包可被反编译, client_secret容易泄露)

授权码模式(机密客户端)

  • 客户端请求授权: 客户端向授权服务器的/authorization端点发送GET请求,
    /authorization?client_id=<客户端在授权服务器注册的唯一标识>&redirect_uri=<授权成功后跳转URL>&scope=<申请访问信息的范围>&state=<客户端生成的随机值(防CSRF)>&response_type=code(代表使用授权码模式)
  • 用户登录与授权: 授权服务器将用户重定向到登录页面, 用户输入第三方平台(如微信)的账号密码登录, 并在授权界面确认是否允许客户端访问请求的资源(如 “百度请求获取你的头像和昵称”)
  • 授权服务器返回授权码: 用户同意授权后, 授权服务器将用户浏览器重定向到redirect_uri指定的回调地址, 并在 URL中携带 授权码(code) 和 state参数, 通过用户携带访问的方式, 将授权码和state传给客户端 (此时客户端应该检测state是否与之前的相同从而防止CSRF)
  • 客户端用授权码换访问令牌: 客户端 向授权服务器的/token端点发送 POST请求, 提交授权码、客户端身份凭证(client_idclient_secret,后者为客户端注册时生成的密钥), 请求换取访问令牌, 换取后授权码会立即失效
    如POST请求/token client_id=xxx&client_secret=xxx&redirect_uri=<跳转的url>&code=<授权码>&grant_type=authorization_code(代表使用授权码换访问令牌)
  • 授权服务器返回访问令牌: 响应返回access_token给客户端, 后端通过将access_token 放在Authorization头中可以向资源服务器申请资源 (整个过程用户无法得知access_token)
    响应格式如{ "access_token": "xxx", "token_type": "Bearer", "expires_in": 3600, "scope": "openid profile" }

授权码模式(公开客户端)

  • 客户端请求授权: 相同, 需多加两个参数code_challenge=<PKCE挑战码,是对code_verifier哈希后的值>&code_challenge_method=S256(哈希算法)
  • 用户登录与授权: 相同
  • 授权服务器返回授权码: 相同
  • 客户端用授权码换访问令牌: 相同, 但无需提供client_secret参数, 需提供code_verifier参数, 授权服务器会校验 该参数值用code_challenge_method中的算法哈希后 与之前提交code_challenge是否相同
  • 授权服务器返回访问令牌: 相同

隐式授权类型

  • 客户端请求授权: 与授权码模式相同, response_type需改为token
  • 用户登录与授权: 与授权码模式相同
  • 授权服务器直接返回访问令牌: 用户同意授权后, 授权服务器直接返回令牌, 存储在用户的前端页面(一般存储在localStorage/sessionStorage)
  • 前端提取令牌并访问资源: 通过前端脚本 从URL片段中提取访问令牌, 随后用户携带令牌(通过将access_token放在Authorization头)向资源服务器请求数据, 用户将数据发送给客户端

-- 安全 --

授权码劫持

  • 简介: 授权服务器漏洞, 当redirect_uri未校验时, 可通过修改伪造 客户端的网站来钓鱼获取授权码(redirect_uri就指向钓鱼网站), 或者直接发送带有恶意redirect_uri的链接让别人点击并授权 来获取授权码
  • 修复: 授权服务器 redirect_uri使用白名单进行匹配过滤
  • 注: 这只能获取授权码, 授权码的进一步利用则 需要获取客户端的client_id/client_secret(机密客户端), 知道code_verifier(公开客户端)

CSRF绑定劫持

  • 简介: 客户端漏洞, 对于类似绑定qq/微信的功能点, 当客户端不使用/校验state参数时, 此时攻击者可发送 带有自己的qq/微信授权码的 换取访问令牌的请求链接, 点击后受害者账号就会绑定攻击者QQ与微信
  • 修复: 客户端 校验state参数是否与用户会话存储的state相同, 再进行绑定
  • 注: 对于OAuth2, state参数是可选的, 但某些授权服务器会强制使用state参数, 否则会拒绝请求

隐式授权

  • 简介: 客户端漏洞, 隐式授权已过时, 而且其设计初衷是用于 纯前端页面, 若用于带有后端的页面, 则客户端 要不让用户提交token到客户端, 要不让用户自行向授权服务器申请数据然后将数据提交给客户端(没法校验数据是否正确), token直接传输, 也易被浏览器历史、插件、XSS 脚本窃取
  • 修复: 不使用隐式授权的方式, 改为授权码(公开客户端)的形式

其它

  • 授权码重复使用: 授权服务器漏洞, 授权码应一次性有效且短期有效, 否则可能会因授权码泄露而导致用户信息泄露
  • client_secret泄露: 客户端漏洞, 可伪造合法客户端, 用授权码向授权服务器请求access_token/refresh_token
  • access_token泄露: 可访问授权服务器资源
  • refresh_token泄露: 可重新申请access_token
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇