More Related Content
Similar to OAuth: How And Why?
Similar to OAuth: How And Why? (20)
More from LI Daobing (12)
OAuth: How And Why?
- 1. OAuth: How and Why?
LI Daobing (盛大创新院)
lidaobing@gmail.com
@lidaobing
July 2010
- 4. Facebook 做法
1. 我确实是从 Facebook 点击过来的
2. 确实是 Google 的网站
3. 申请的权限仅限我的联系人
- 5. 查看权限, 回收权限
在整个过程中:
1. 密码没有泄漏给 facebook
2. 同时可以随时回收权限
- 7. 需求再整理
前提
我有一些数据储存在服务方A
第三方客户端B想访问/修改我的数据
需求
我想授权B访问我的数据,同时不暴露我的用户名和密码
这种授权可以随时回收
即使信息被窃听, 攻击者也无法伪造请求
即使有恶意中间人, 攻击者也无法伪造请求
- 11. OAuth 词汇表
三方
客户端: client, 原称 consumer
服务端: server, 原称 service provider
资源所有者: resource owner, 原称 user (本文仍使用"
用户")
三凭证 (凭证即两个随机字符串, 分别为 key 和 secret)
客户端凭证: client credentials, 原称 consumer key and
secret, 客户端在服务端注册后获得
临时凭证: temporary credentials, 原称 request token
and secret
令牌凭证: token credentials, 原称 access token and
scret
- 13. 详细数据流 (1/5)
缩写
CK: 客户端凭证key
CS: 客户端凭证secret
TK, TS: 临时凭证 key 和 secret
AK, AS: 令牌凭证 key 和 secret (A 代表 access token)
- 14. 详细数据流 (2/5)
0. 初始状态, 客户端持有 CK 和 CS
1. 用户发起授权操作: 用户点击位于客户端上的一个按钮, 发起授权
2. 客户端申请临时凭证:
客户端向服务端发送 CK 和申请的授权(rights), 并用 CS 签名
3. 服务端返回临时凭证,
服务端首先校验签名, 服务端生成一对 TK 和 TS, 把 {TK: [TS, CK,
rights]} 放入 cache, 把 TK 和 TS 发送到客户端
4. 跳转至登录页面
客户端把 {TK: [TS, client_user]} 放入 cache, 使用 TK 和回调URL
(oauth_callback) 构造出登录 URL, 发送一个 301 响应让用户跳转至登录 URL
- 15. 详细数据流 (3/5)
5. 用户访问登录URL, URL中包含 TK 和 oauth_callback (回调URL)
6. 完成授权
如果用户没有登录, 服务端首先引导用户登录, 获得 server_user. 服务端根据
URL 中的 TK 提取出 CK 和 rights, 展示客户端的详细信息以及申请的授权。
用户点击同意后, 服务端产生 AK, AS 以及一个 verify_code (一个随机字符
串), 更新 cache 为 {TK: [TS, CK, rights, AK, AS, verify_code,
server_user]}, 根据URL中的 oauth_callback 和 verify_code 构造出新的回
调 URL。
- 16. 详细数据流 (4/5)
7. 用户访问回调URL, 该URL 中包含 TK 和 verify_code
8. 客户端申请令牌凭证
客户端通过 TK 拿到 TS 和 user_id, 首先判定此时的用户与申请TK时用户一
致, 然后向服务器发送 CK+TK+verify_code, 并用 CS+TS 签名
9. 服务端返回令牌凭证
服务端通过 TK 从 cache 取出 [TS, CK, rights, AK, AS, verify_code],
校验 CK 一致, verify_code 一致, 签名正确, 销毁 cache, 持久化 {AK: [AS,
CK, user_id, rights]}, 返回 AK 和 AS
- 17. 详细数据流 (5/5)
10. 客户端发起 API 请求
根据 API 文档准备数据, 加上 CK, AK, 使用 CS+AS 签名
11. 服务端返回 API 结果
根据 AK 从数据库中调出 [AS, CK, user_id, rights], 校验 CK 及签名, 检验
访问的 API 是否在授权范围内, 使用 user_id 对应的数据支持 API, 返回结果
到客户端
- 19. 签名范例
GET /photos?file=vacation.jpg&size=original HTTP/1.1 #请求 Path
Host: photos.example.net #请求 Host
Authorization: OAuth realm="Photos",
oauth_consumer_key="dpf43f3p2l4k3l03", #CK
oauth_token="nnch734d00sl2jdk", #TK/AK
oauth_signature_method="HMAC-SHA1", #签名方法
oauth_timestamp="137131202", #时间戳
oauth_nonce="chapoH", #nonce
oauth_signature="MdpQcU8iPSUjWoN%2FUDMsK2sui9I%3D" #签名
1. 从客户端发送到服务端的每个请求都需要签名
2. 除了前面讲到的数据外, 需要额外加上 oauth_timestamp(时间戳)
以及 oauth_nonce, 用于防止重放攻 击 (后面有详解)
3. oauth_signature_method 用于指定签名方法, oauth_signature 为签名
签名细节参见 RFC 5849 3.4 节 , 简单来说就是把请求的内容拼接为字符串
(包括 GET/POST), 然后使用 对应的密钥签名
- 20. 需求回顾
我想授权B访问我的数据,同时不暴露我的用户名和密码
用户名和密码都是在 A 服务器上输入的, 从未暴露
这种授权可以随时回收
在 A 服务器上随时可以回收
如果信息被窃听,数据不会有危险
API 请求需要用 CK+AK 来签名, 数据窃听只能听到 AK, 所
以无法伪造请求 (PS, 尽管新的标准要求在返回 TS 和 AS
必须使用 HTTPS, 但仍有大量服务器使用 HTTP)
如果有恶意中间人,数据不会有危险
理由基本同上, 不过恶意中间人能够给客户端返回假数据,误
导客户端,但仍无法伪造出对服务端的合法请求
- 21. 更多的安全细节
1. 客户端需要保存好 TS
2. TS 在服务端是明码保存的, 所以如果服务端被入侵, TS 可
能会泄漏
3. 服务端用户登录页面必须是 HTTPS
4. 服务端展示客户端凭证密码的页面必须是 HTTPS 页面(很多
现有服务不满足)
5. 服务端返回临时凭证和令牌凭证时必须是 HTTPS 协议(原始
OAuth 协议为应该, RFC 改为必须)
6. 凭证的密钥应当足够长(大部分服务使用 128bit 密钥,
douban 的是 64bit)
7. OAuth 不保证 API中涉及到的保密数据的安全。
- 24. 为什么不用 HTTPS
Q: 前面提到的很多手段都是为了应对窃听和恶意中间人, 全部
用 HTTPS 不就行了么?
一般情况下, 一个 IP+端口只能部署一套 HTTPS 密钥,也就
是说没法玩虚拟主机了(因为在 Host 发送前TLS连接就必须建立好 )。
SNI 扩展支持 HTTPS 虚拟主机,但客户端方面 IE6 不支持,
WinXP 下 IE所有版本, Chrome, Safari 不支持.
Dreamhost 之类的 Host 供应商不支持 HTTPS 虚拟主机。
HTTPS 对服务器端压力也更大
HTTPS 密钥很昂贵, 比较便宜的godaddy 每年 30 美金左
右, 贵的可达数千美金一年
- 25. 为什么使用 HMAC-SHA1
Q: HMAC-SHA1 需要计算两次 SHA1, 有必要么?
A: 签名是为了防止窃听者和恶意中间人伪造请求, 而其他更简单的签名
方法都存在安全风险
1. 比如使用 sign = SHA1(key+data), 中间人截获了 data 和 sign, 由
于 SHA1 算法的特性,对于构造出 data' = data + padding, 可以
计算出对应的 sign' = SHA1(key+data'), 伪造成功。
2. 比如使用 sign = SHA1(data+key), 中间人截获了 data 和 sign, 如
果我们能找到 data' 满足 SHA1(data)==SHA1(data'), 那么伪造请
求 data', sign 也能通过服务端的验证
3. 对于 HMAC: sign = SHA1(f1(key)+SHA1(f2(key)+data)), 没有前
面所说的两种风险。
4. 第二步 SHA1 的参数很短(320bit), 所以对比单次 SHA1, 时间不是两
倍,而只是增加了一个很小的常数时间
- 26. 为什么需要 nonce 和 timestamp
A: 防止重放攻击 (Replay attack)
一种重放攻击是把截获到的请求重发一次或多次, 对于 POST
这种非幂等的方法会造成服务器端的数据错误。加入 nonce
后, 首次之后的请求会被拒绝。这种攻击手法只需要窃听能
力。
另一种重放攻击是把请求拦截下来, 不发给服务器。然后等
待到合适的时间后再把请求发给服务器。也可以收集多个请
求,重新组合成合适的顺序后再发送。这种攻击手法需要中间
人能力。
由于 nonce 与 timestamp 是一起使用的,所以 timestamp 过期
后 nonce 也可以抛弃, nonce 储存容量不会无限制增长。
- 28. 1.0a 修复了什么Bug?
A: 1.0 下存在如下的一种攻击手法
1. 存在两个用户: 攻击者和受害人, 存在一个客户端,这个客
户端会把用户在服务端的权限通过 OAuth 绑定到本地帐号。
2. 攻击者登录客户端, 在客户端触发 OAuth 请求, 跳转到服务
端后,不进行授权操作,保存此时的 URL。
3. 攻击者把保存好的 URL 发给受害人, 并诱导受害人完成授权
操作(注意: 此时绑定操作通常会失败, 因为因为临时凭证的
密钥部分应该只存在攻击者的 session 数据中)。
4. 攻击者访问 callback URL, 就可以绑定受害人的权限到攻击
者的帐号。
- 29. 1.0a 如何修复Bug?
服务器应该提醒用户, 登录链接是否来自指定的网站。
客户端应当确认,发起请求的用户和完成登录的是同一个用
户 (避免在受害者访问 callback 时就完成绑定了)
服务端会下发确认码, 攻击者无法构造出完整的 callback
url, 攻击失败
申请临时凭证的协议也略有更改,用于识别 1.0a 客户端和
服务端
- 30. OAuth 不做什么?
只保护服务端,不保护客户端
OAuth 只保证用户在服务端的数据不被非法访问或修改,
但不保证客户端接收到正确的数据,恶意中间人可以修改
返回的数据,当然这个也可以用签名来解决。
不保护恶意浏览器/恶意操作系统攻击
用户必须自行确认自己的浏览器/操作系统是否安全。
OAuth 的安全建立在 HTTPS 之上, 攻击 HTTPS 的手段也会
影响到 OAuth
比如 DNS 污染加上伪造证书
比如 SSL 2.0 漏洞
不保护笨蛋, 用户需要教育
OAuth 授权时需要验证确实在真实的服务器上, 避免被恶意
客户端钓鱼
- 31. 国内现有 OAuth 服务器的问题
Douban
仍在使用 OAuth 1.0
客户端令牌展示页面没有加密
密钥只有 64bit
Sohu 微博
每次认证时都要求用户输入密码, 容易造成用户麻痹, 更
容易被钓鱼网站袭击
...
PS. 仅代表当时(2010-07)的情况, 不代表现状