从最近几年开始,做平台的公司都流行起Open API。这是一个非常好的理念,也受到广大开发者的欢迎。如今,开发一款软件,你可以很容易地集成微博、微信、人人网等流行社交媒介的分享功能,做一个社交应用变得越来越简单。
主流社交媒介要集成到第三方应用中,最重要的入口就是安全便捷的授权认证系统。让用户在享受一键分享和各种社交乐趣的同时,又不用担心帐号安全和隐私泄露等问题。而对于一些有特殊目的的组织或个人来说,攻占这个授权认证系统意味着自己获取了信息传播的入口和渠道,数量庞大地社交入口往往能带来巨大的社会效应。所以,这个入口就成了软件安全攻防双方的必争之地。
而本文所要讲的就是当前最为流行的新浪微博Android客户端SSO授权认证入口的一个安全缺陷。此缺陷使得第三方APK在一定条件下可以不通过授权,在不需要人为操作的情况下就可以操作Android手机用户的微博。包括关注、评论、发微博等OpenAPI中提供的功能。
一、新浪微博授权认证方式的演变:
首先让我们简单回顾一下新浪微博OpenAPI这几年授权认证方式的演变历程,并了解一下各自的安全性问题。
1、最开始是Basic认证。
即是通过http协议的authorization头来传递认证信息。认证信息包括用户名和密码,仅通过base64对用户名密码做加密。基本相当于明文传输。所以出于账户安全考虑,经过一段时间后就被废弃不用了。
2、然后切换为XAuth认证。
XAuth认证其实就是OAuth认证的简化版。OAuth的原理不做详细说明。大致流程是:
A、第三方应用到授权服务器请求一个授权令牌(request token&secret)
B、引导用户到授权服务器请求授权
C、用访问令牌到授权服务器换取访问令牌(access token&secret)
D、用访问令牌去访问得到授权的资源
它的安全保障是,所有http请求都采用非对称加密算法对请求进行了加密。所以网络上传输的数据理论上是安全的。
但XAuth认证是OAuth认证的简化版,它允许第三方应用从用户的输入中获取到用户的帐号和密码,而无法保证第三方应用对用户的帐号和密码进行了足够安全地保护。特别还有一些流氓软件本身就会记录用户的信息。所以微博帐号的安全还是存在较大的风险。
3、采取了更安全更便捷的OAuth2.0认证。
OAuth2.0比OAuth1.0更安全更便捷主要是两个方面。
更便捷。OAuth2.0的认证流程比OAuth1.0更简单。只需要三步:
A、引导用户到授权服务器,请求用户授权,用户授权后返回 授权码(Authorization Code)
B、客户端由授权码到授权服务器换取访问令牌(access token)
C、用访问令牌去访问得到授权的资源
更安全。token不再需要secret,并且也不再需要对token进行加密。但OAuth2.0采用了https安全协议,在安全保障更胜一筹。
并且OAuth2.0第三方应用不再接触到用户的帐号和密码,用户直接跳转到新浪微博的认证界面进行登录。第三方应用仅获取登录成功之后的结果。从而保障了用户帐号的安全。
但是OAuth2.0认证在移动终端的应用上也存在一定问题。主要倒不是安全上的,而是用户体验上的。跳转到授权页面在移动终端上体验不好,授权流程相对复杂,导致授权的转化率受到影响。因此,新浪微博结合新浪微博客户端一起推出了它的第四代授权认证:SSO认证。
4、通过微博客户端的SSO认证。
SSO的全称是Single Sign On,中文名是单点登录。当第三方应用与新浪微博客户端为互相信任的应用系统时,仅需要一次授权登录就可以在一定期限内,不再重复登录授权而不受限制地调用新浪微博Open API提供的各种服务。
这种授权方式与新浪微博客户端紧密结合,当用户有登录新浪微博客户端时,只需要一键授权就能完成授权流程,非常便捷。另外第三方应用通过微博客户端进行授权认证,不会直接接触到用户的账号密码,账户安全也能得到保障。
SSO是一种非常好的移动终端认证方式,并且利于本身客户端的推广。安全性和便捷性都不错。但由于SSO的基础是客户端和第三方应用需要互相信任,而这个信任关系本身的安全性存在缺陷。因此就会出现其他非信任应用能够冒充信任应用获得授权认证,从而对用户的微博进行操作的情况。这就是我们本文中将做进一步阐述的内容。
二、如何冒充信任应用,获取客户端的授权:
在Android应用中使用过新浪微博SSO认证的朋友们都知道,针对新浪微博的授权,官方提供了较详细的文档和封装得足够简单的SDK供大家使用。由于本文内容与这些技术细节关系不大,所以在此就不做细述,不了解的朋友可以去新浪微博开放平台的官网上了解相关内容。
事实上,新浪微博对于信任应用的认证环节相当地弱。具体来说只需要两个关键信息:CONSUMER_KEY和REDIRECT_URL。
CONSUMER_KEY即第三方应用在新浪微博开发平台网站后台申请到的APP KEY。
REDIRECT_URL即第三方应用在后台填写的OAuth2.0的授权回调页网址。
当这两个信息匹配时,新浪微博就会认为是对应的第三方应用发起了合法的请求。授权流程就会正常进行。如果这个第三方应用已经在之前做过了授权,那么它就可以直接获取access_token,然后就可以操作用户的微博了!
现在我们假设:
1、用户的Android手机已经安装了新浪微博客户端并已经登录。(应该95%以上的手机满足此假设吧)
2、用户曾授权过一些主流第三方应用进行微博分享操作。例如camera360、美图秀秀、网易新闻等。(此假设应该也有90%以上的用户满足吧)
3、用户的新浪微博端只登录了单用户帐号。多用户帐号在SSO授权时需要用户手动选择帐号,所以需要人为干预。(此假设也应该有90%左右用户满足吧)
在满足前面三个条件的情况下,只需要我们再获取到用户曾经授权过的第三方应用的CONSUMER_KEY和REDIRECT_URL就可以通过官方的SDK调用,在不需要人为操作的情况下操作Android手机用户的微博了!
于是我们的问题集中在了如何获取第三方应用的CONSUMER_KEY和REDIRECT_URL上。
很多朋友也许会认为,CONSUMER_KEY和REDIRECT_URL对于SSO授权认证系统的地位就相当于非对称加密算法的私钥,属于非常隐私的、应该被保密起来的信息,我们如何可以获取到呢?
这里需要注意的是,私钥之所以安全,是因为它是物理隔离的。私钥的信息理论上只存在于软件发布商的单机上,任何发布到公众的信息中都不包含私钥信息。因此,除非特殊途径(例如拿到软件发布商的电脑把私钥拷贝出来,或者软件发布商头脑发晕,把私钥给发了出去),我们认为私钥信息是绝对安全的。
而CONSUMER_KEY和REDIRECT_URL是授权过程中需要的信息,因此把必须在软件的运行时出现,因此这个信息从理论上来讲是发布到公众的信息。通过一系列逆向、静态、动态分析,我们可以获取到这些信息。因此它是不安全的。
正巧,几个月前闲暇之时,曾对一些如今比较流行的Android应用做过这方面的技术分析。自己通过逆向获取到了这些应用的相关信息,如下图:
注:没列出来的应用并不证明没有此安全问题。
这些应用都是现在最为流行的一些应用。为了不引起公众影响,我对其中的关键信息进行了适度的隐藏。
因此只要你曾经授权这些第三应用(以及其他第三方应用),那么从理论上来说,软件安全的攻方,就可以通过逆向获取这些应用的CONSUMER_KEY和REDIRECT_URL,通过官方提供的SDK,在你不知情的情况下,操作你的新浪微博帐号了。
三、新浪微博的下一代授权认证方式:
针对目前SSO授权认证安全缺陷的情况,新浪微博推出了下一代SSO认证,即SSO2.0。
事实上SSO授权认证从去年推出以来,这个问题很快就被发现,如果不是现在推出了SSO2.0,我可能还会继续憋着不说。毕竟破解不是关键,关键是推动软件安全不断进步。
在理解了现在的SSO授权认证机制及其缺陷后,SSO2.0很好理解。SSO2.0主要就是为了防止非信任的第三方应用冒用信任的第三方应用的身份。既然CONSUMER_KEY和REDIRECT_URL本身的信息安全都无法保障了,那该如何防止?
这又回到了很早以前我曾讨论过的如何防止应用被破解的问题上,应用的身份如何防止被冒名顶替?最简便且理论安全的方法就是通过签名对比认证。而这正是新浪微博SSO2.0所采用的方式。
在新浪微博开放平台网站后台,对第三方应用绑定包名和签名。这样当非信任应用采用信任应用的CONSUMER_KEY和REDIRECT_URL进行认证请求时,由于包名和签名对应不上,服务器和微博客户端就会拒绝认证通过,从而补上了SSO1.0的安全缺陷问题。
当然,SSO2.0也不是绝对安全的,它也存在自身的薄弱环节。不过,这就不是本文的讨论范围了。