邱永哲
(中国科学技术馆 网络科普部,北京 100012)
随着互联网的高速发展,各种社交、购物网站层出不穷,中国已经全面迈入了互联网时代。对用户来说,这些繁杂的网站、应用程序在方便生活的同时,也引入了个人信息安全的问题。为避免个人信息遭到泄露,不同的网站设置不同的账户密码这一方法也逐渐深入人心,成了每个网民在互联网中保护个人安全的最有效方法。然而,大量的账号和密码也给用户带来了记忆负担,大大降低了使用体验。因此,跨应用数据共享这一需求逐渐呈现出越来越高的态势,Google,Facebook,腾讯等各大互联网厂商也相继推出了自己的跨应用数据共享接口,使得用户在不同网站之间能使用相同的用户数据,在提高用户数据安全性的同时也极大地方便了用户的使用。
本文通过介绍跨应用授权协议OAuth及其运行机制,详细阐述了不同应用之间数据的共享方式和其安全性保护措施,并列举了OAuth 2.0协议在实施过程中容易出现的安全问题,最后对开发者提出了相应的安全性建议。
开放授权(Open Authorization,OAuth)是一个开放的授权协议,其允许用户让第三方应用访问自己在某一网站上存储的私密资源(例如照片、视频、联系人等信息),而无需将用户名和密码提供给第三方应用。OAuth规定用户必须使用一个访问令牌来获取存放在OAuth服务提供方的数据,每一个访问令牌只对唯一一个第三方应用有效。如图1所示为国内开发者社区SegmentFault提供的Google,Github等平台OAuth服务快速登录接口。
OAuth的出现极大地方便了用户在不同应用之间数据的共享需求。2010年4月,OAuth 1.0正式以RFC 5849的形式出现,后被全世界广泛运用[1]。目前经过多年的发展,OAuth授权协议已经升级至2.0版本,其官方文档也已更迭为RFC 6749。
从RFC 6749当中可以看到OAuth 2.0的运行流程,如图2所示。
图中左侧的Client(客户端)为想要获取用户数据的第三方应用,右侧的Resource owner、Authorization Server、Resource Server均为提供OAuth接口服务的Server(服务商)。因此整个OAuth 2.0的授权运行过程如下。
图1 开发者社区SegmentFault快速登录接口
图2 OAuth 2.0运行流程
(1)用户打开客户端后客户端要求给予授权。
(2)用户同意给予客户端授权。
(3)用户使用上一步获得的授权,向服务商授权服务器申请访问令牌。
(4)服务商授权服务器对客户端确认无误后同意发放访问令牌给客户端。
(5)客户端使用访问令牌向服务商资源服务器获取相应的数据。
(6)服务商资源服务器确认客户端访问令牌有效,向客户端开放相应数据。
OAuth 2.0授权协议共有4种授权方式:Authorization code(授权码)模式,Implicit(隐式)模式,Resource owner password credentials(账号密码)模式,Client credentials(客户端)模式。其中,授权码模式是目前OAuth 2.0中功能最完善、流程最严密的模式,因而被广泛使用。这4种授权方式的流程分别如图3—6所示。
图3 Authorization code授权模式
图4 Implicit授权模式
图5 Resource owner password credentials授权模式
图6 Client credentials授权模式
OAuth 2.0本身是一套非常严密的结构,但是一些开发者在实现、部署OAuth授权服务的时候因为疏忽而产生了很多安全问题,这些问题一旦被利用,将导致严重的后果。下面就列举一些OAuth 2.0授权协议在实现过程中容易造成的安全问题。
2014年5月,新加坡南洋理工大学研究人员王晶发现,一些提供OAuth服务的网站在对第三方应用进行OAuth授权过程中未对回调的统一资源标识符(Uniform Resource Identifier,URI)进行验证,导致回调的URI可以被修改为非原定URI,因此可以被用来钓鱼,是一个明显的跳转漏洞。这一漏洞被命名为“Covert Redirect”即隐蔽重定向漏洞。
在国内,该漏洞也被叫作OAuth redirect_uri回调污染。事实上该漏洞造成的危害不仅仅是可被用来钓鱼攻击,看下面的例子。假设某OAuth服务商使用授权码模式进行第三方应用的授权服务,某个第三方应用可以通过该服务商的OAuth接口绑定账号,以此来方便用户登录和使用。该客户端绑定账号的请求如下:
GET /authorize?which=Login&display=pc&response_type=code&client_id=100263567&redirect_uri=http://client.com/index.php/sign/callback&scope=get_user_info,add_pic_t,add_t HTTP/1.1
Host: server.com
现在某用户已经登录了该第三方应用,攻击者向他发送了如下一个URL:
http://server.com/authorize?which=Login&display=p c&response_type=code&client_id=100263567&redirect_uri=http://hacker.com/index.php&scope=get_user_info,add_pic_t,add_t
可以看出这是一个用于绑定账号的URL,并且将用于回调的redirect_uri修改成自己控制的页面http://hacker.com/index.php。此时,如果OAuth服务商存在隐蔽重定向漏洞,那么当该用户点击并授权以后页面会跳转至http://hacker.com/index.php?code=***。这时候该用户的授权码code将会被hacker.com捕获便遭到了泄露。对于一些网站来说,授权码code一旦泄露,将导致用户账号被劫持,国内腾讯、新浪微博等OAuth服务均出现过此问题。同时,对于第三方应用来说,如果其自身存在XSS或者没有做好页面防嵌入,也同样能造成授权码code的泄露。
OAuth 2.0当中定义了一个state参数,根据RFC 6749,其含义为:
state:RECOMMENDED. An opaque value used by the client to maintain state between the request and callback.The authorization server includes this value when redirecting the user-agent back to the client.The parameter SHOULD be used for preventing cross-site request forgery as described in Section 10.12.
即该参数用于在授权过程中请求和回调阶段的状态保持,用于防止该过程中产生CSRF攻击。然而事实却是很多OAuth服务开发者忘记或错误使用state参数,造成大量用户账号被劫持的安全事件。国内白帽子黑客horseluke给出了一个新浪微博的例子[2]。
某用户在登录了第三方网站a.com后想在该网站关联并绑定自己的新浪微博账号,于是就点击了该网站上给出的“绑定微博”按钮,该按钮的URL为http://a.com/index.php?m=user_3rd
_bind_sina。该用户点击以后浏览器将用户重定向至新浪微博OAuth授权页面,URL为:http://
api.weibo.com/oaut h 2/aut hor i ze?cl ie nt_id=999999&redirect_uri=http://a.com/index.php?m=user_3rd_
bind_sina_callback&response_type=code。随后用户对a.com给予了授权,新浪微博授权服务器生成了授权码code,浏览器将用户重定向至http://a.com/index.php?m=user_3rd_bind_sina_callback&
code=809ui0asduve,此时完成了账号绑定。
上述过程粗略地看并没有问题,但事实上完成账号绑定时的URL跟当前用户没有任何关系,因为该URL只能证明新浪微博用户信息,但无法证明a.com的用户信息。现在如果有两个用户同时发起绑定请求,登录到不同的微博账号,随后在获取到授权码code后双方互相交换code,这将会导致两个用户绑定的新浪微博账户也发生交换和改变。黑客正是利用这一点实现了劫持用户账号的目的,而这一过程也体现了state参数的重要性[3]。
2013年,国内著名的音乐圈APP啪啪被发现存在任意账号登录的严重漏洞,这一问题是啪啪在使用OAuth授权服务时产生的[4]。啪啪客户端为方便用户使用,提供了使用新浪微博、QQ登录的功能,登录的大致流程为:
(1)用户点击使用新浪微博或QQ登录,将弹出新浪微博或QQ的OAuth授权页。(2)用户授权以后啪啪客户端获得服务商提供的访问令牌。(3)啪啪客户端将访问令牌移交给api.papa.me已获取啪啪自己的认证字符串。(4)啪啪客户端得到认证字符串后获得操作该微博或QQ绑定的啪啪账号权限。
漏洞发现者在测试过程中,将第二步获得的访问令牌替换为其他应用在OAuth服务商获得的访问令牌,随后继续进行第三步和第四步,结果发现登录了另一个啪啪账号。该漏洞的关键在于当啪啪通过OAuth服务商获得授权信息(访问令牌、令牌有效期等)后,是将其作为参数匹配到自己的账号并自动登录或自动注册的。由于后续的匹配处理逻辑出现纰漏,甚至无验证机制,就直接导致了啪啪账号的任意登录。
可见,无论OAuth 2.0是多么严密安全的流程,对于OAuth服务商和其使用者来说,错误的实现和运用都可能会引发严重的漏洞,以至于大量用户数据和信息也将面临被劫持泄露的风险。针对目前发生过的一些安全问题,本文对于OAuth在实现和运用过程中有以下安全建议。
为了防止OAuth授权过程产生隐蔽重定向漏洞和redirect_uri回调污染,OAuth服务商应当对redirect_uri进行全路径校验,避免产生跳转漏洞。同时要加强验证过程和逻辑,避免被绕过。
为了防止访问令牌泄露,应当验证OAuth授权过程中的授权请求来源信息、第三方应用信息。例如在Resource owner password credentials(账号密码)授权模式中,用户将在OAuth服务商的个人账户密码移交给了第三方应用,如果第三方应用不被信任,则会产生用户数据泄露的风险[5]。
使用OAuth的第三方应用应当按照官方文档的描述,在请求授权和回调过程中正确使用state参数以防止产生CSRF漏洞,该参数与anti csrf token类似,要做到随机不可预测。
使用OAuth的第三方应用需要考虑在自动登录或者自动注册的过程中,验证OAuth服务商返回的授权信息,同时要验证该授权信息例如访问令牌是否为指定来源应用所颁发。第三方应用如果发现了访问令牌中的服务商给出的uid和自己在服务商绑定的uid不一致、非自身应用appkey授权的访问令牌、过期访问令牌等异常情况均需要全部撤销,并且要求这些异常用户重新授权登录。
由于一些OAuth服务商在Implicit授权模式中直接将访问令牌放进回调URL,这就增加了访问令牌泄露的风险,因此OAuth服务商应当避免第三方应用强制更换授权方式为Implicit模式。
[参考文献]
[1]佚名.RFC 6749.[EB/OL].(2017-12-29)[2018-03-05].http://www.rfc-editor.org/rfc/rfc6749.txt.
[2]阮一峰. 理解OAuth 2.0[EB/OL].(2014-05-12)[2018-03-05].http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
[3]维基百科.OAuth概念解析[EB/OL].(2017-02-15)[2018-03-05].https://en.wikipedia.org/wiki/OAuth.
[4]HORSELUKE.OAuth 2.0安全案例回顾[EB/OL].(2014-03-11)[2018-03-05].http://wooyun.jozxing.cc/static/drops/papers-598.html.
[5]∑-TEAM.OAuth安全指南[EB/OL].(2014-05-13)[2018-03-05].http://wooyun.jozxing.cc/static/drops/papers-1989.html.