Android应用:社会化授权登录及分享安全漏洞

一、漏洞发现

先说说场景吧,由于业务要求,需要对分享控件做了一次大的升级和重构,然后发现我们分享组件使用的是第三方的ShareSDK(专门封装分享API的组件,大部分童鞋应该都听说过),这本来也没什么问题。

然后,重构过程中遇到一个难以理解的事情,在工程assets目录下面有一个名为ShareSDK.xml的文件,在打开这个文件之后,我震精了,喝到口的咖啡全喷到了键盘上,文件内容是这样的:

这里写图片描述

第三方开放平台的应用注册信息都是明文写在这个文件中的,包括重要的AppId和AppSecret(图内容来自是ShareSDK官方demo)。这个时候,第一个考虑的问题还仅仅是隐私暴露,并没有考虑到安全漏洞方面。

当然,接下来就去看这样设计的原因,原来是ShareSDK内部调用第三方应用授权分享需要这些应用注册信息,为了方便开发者接入,所以采用这种文件静态注册的方式。

作为一个开发者老司机,无论是直觉上还是开发原则上,都隐隐觉得这种方式是有严重问题的。为什么呢?因为assets目录在打包过程中是原封不动地打进APK包内的,任何人不需要任何反编译工具就能直接从APK包内提取出来。那么,如果直接提取出来放到另一款应用中是不是意味着……

想到这里,已经惊出一身冷汗了,世纪大坑!世纪大坑!世纪大坑啊!

接下来就是验证的过程,步骤非常简单。 
1、找到一款接入ShareSDK组件的应用,将其安装包APK内的ShareSDK.xml解压提取出来。 
2、直接将项目的ShareSDK.xml替换为上一步的文件。 
3、调用分享

验证结果:除了微信相关的不能分享,QQ和新浪都分享成功了,并且显示分享内容来自XX应用,XX应用就是我们提取的那款应用了。


二、漏洞原因

当然,如果仅仅是这样,只能说是小漏洞,波及范围并不广。可惜事与愿违,市场上90%以上的应用都在受灾范围内,原因后面分析。

为了帮助理解,我们先来谈一谈社会化分享的机制。

首先,一款应用要接入社会化的授权登录分享等功能,需要到开发平台上去注册应用信息,注册信息包括应用包名,应用签名等等,以微信为例:

这里写图片描述

接着,应用注册成功后,我们会得到两个key,一个是AppId,一个是AppSecret(或AppKey):

这里写图片描述

当然,一般情况下,移动应用只需要AppId,而AppSecret主要是用在接口API调用。为了安全起见,微信开放平台都已经不再存储AppSecret,可想而知这些信息有多重要,所以在大家项目中无论是写在Java代码里还是配置在xml中,只要是明文,都是万万不可行的!

那么,第三方调用的机制流程是怎样的呢,以微信为例:

步骤1:项目应用中集成微信SDK,也就是libammsdk.jar。 
步骤2:通过AppId调用微信SDK发送请求,比如登录授权、分享等。 
步骤3:微信SDK将AppId、当前应用包名、请求信息发送到微信客户端。 
步骤4:微信客户端接收到AppId后,请求服务端得到我们注册在开放平台的应用包名、应用签名、权限等。 
步骤5:微信客户端比对注册的应用包名和步骤3中的应用包名,不一致调用失败。 
步骤6:微信客户端比对注册的应用签名和请求应用的签名(通过步骤3中的应用包名调用系统API查询),不一致调用失败。 
步骤7:调用相应的API,比如登录授权、分享等,当然还要看注册的应用是否有这些权限。

其中最关键是步骤5和步骤6,正是因为有了这两步的包名和签名校验,所以之前验证漏洞时微信分享调用失败。

新浪微博和QQ的第三方调用机制流程大同小异,但是QQ完全不做包名和签名校验,也就是省略了步骤5和步骤6,所以验证漏洞时分享成功。

新浪微博比较特殊,因为其除了客户端调用还是支持网页端调用,所以验证漏洞时调用客户端分享失败,调用网页端分享成功。

综上所述,校验包名和校验签名是防止恶意调用的防御手段,QQ和新浪微博网页这种不做校验的方式都是存在安全隐患的,只需要知道特定应用的AppId,就可以以其名义发起恶意的授权登录分享。遗憾的是,很多开发者不清楚AppId的重要性,直接暴露在代码或文件中。


三、漏洞升级

前面说了,事情并不仅仅是这么简单。校验包名和校验签名是防止恶意调用的防御手段,但是这种防御是否真的有用呢?

我们再来仔细梳理下流程,同样以微信为例:

步骤3:微信SDK将AppId、当前应用包名、请求信息发送到微信客户端。 
步骤5:微信客户端比对注册的应用包名和步骤3中的应用包名,不一致调用失败。 
步骤6:微信客户端比对注册的应用签名和请求应用的签名(通过步骤3中的应用包名调用系统API查询),不一致调用失败。

这是其中最关键的三个步骤,微信客户端接收到的AppId、应用包名都是来自微信SDK,而应用签名是通过应用包名调用系统API获取的,所以实质上校验的来源只有AppId和应用包名两个。

这里面有一个非常重要的但又非常容易忽略的点就是:系统查询到的应用签名,可能并不是发起调用的应用,而是手机上安装的指定包名的应用。 换言之,步骤3中发送到微信客户端的AppId和应用包名,如果就是被恶意攻击的应用的AppId和包名,并且手机上装有这款被攻击的官方应用,那么步骤5和步骤6就全部被绕过了。

剩下的难点就是如何通过第三方SDK发送指定的AppId和包名给第三方客户端了。

AppId容易得到,市场上几乎所有应用里面接入的社交化AppId都是明文形式写在代码里面的,比如AndroidManifest.xml(天坑!天坑!天坑!)。

最后一步就是伪装包名了,在Android中获取当前应用包名都是通过Context.getPackageName的方式,开发者调用SDK的时候传入的参数就有这个Context,那么事情就变得无比简单了!

这里写图片描述

这里写图片描述

另外,还有第二种方式,因为最终都是通过startActivity的方式调起第三方应用,参数都是通过Intent传递,我们可以在startActivity前将Intent中的参数包名替换掉,思路差不多,在此略过。

所以,只需要获取到指定应用的包名,第三方AppId,就可以伪装成这款应用发起第三方调用,而包名和AppId都是极其容易获取的,当然为了绕过签名校验手机还必须装有这款指定的官方应用。

下面,测试了国内几款接入微信分享功能的知名应用,截图如下:

这里写图片描述 这里写图片描述


四、漏洞危害

说完了漏洞,下面就要说这款漏洞的危害了,当然开发者节后也有的忙活了。

1、用户隐私盗取

很多应用程序都接有第三方登录授权的功能,有利于简化用户注册过程。利用这个漏洞,攻击者可以伪装成官方应用骗取用户授权,而且授权页面是真真正正的授权页,上面也确实显示的是真正官方应用的logo和应用名。

授权成功之后,攻击者拿到openId和access_token之后,再结合AppId和AppSecret,很容易就获取到用户的社交隐私,甚至如果抓包到接入第三方登录功能应用的登录接口,你的相关应用隐私也就一览无余了。

相对来说,微信授权登录还是比较安全的,因为授权结果是回调到WXEntryActivity的,由于应用applicationId的关系,回调的WXEntryActivity是难以被伪装的,所以暂时还未想到其它攻击手段,但依然是隐患。

2、虚假分享

和登录授权不同,分享是不需要数据回调的,直接就分享出去了,那么利用这个漏洞的可操作性就高了,而且非常简单。

攻击者可以给微信好友(群组)、朋友圈、QQ好友(群组)和新浪微博上肆意分享危害性质的信息网站链接,而在这些社交应用里面,会显示来自XX应用。比如利用此漏洞分享虚假新闻(来自XX头条),分享虚假视频(来自XX视频),分享虚假话题(来自X乎),分享红包优惠券(来自X东)等等。由于社交应用里面显示的是来自官方应用,所以可信任度非常高,真假难辨,骗取用户点击的几率可谓是100%,如果是钓鱼链接,后果难以想象。


五、漏洞反思

经过数个小时的测试,目前市场上主流应用都在此漏洞危害范围之内,几乎被全军尽墨,能够幸免的应用屈指可数,想想背后都是一身冷汗。

关于这个漏洞,从两个层面来分析下修复策略吧。

1、开发者

这个漏洞原理并不复杂,其中一个重要的因素就是开发者直接暴露出去AppId甚至AppSecret,由于开发者安全意识不够,未认识到它们的重要性。直接的后果就是暴露出去无法收回,即使后面版本处理了,历史版本里面仍然可以查到,可谓亡羊补牢为时晚矣!虽然这种事情难以避免,但仍然需要给我们一个血淋淋的教训。在此,总结出以下两点:

a、严禁明文暴露注册第三方平台的AppId、AppSecret,包括文件、代码、接口,至少要做一层简单的加密。 
b、接入ShareSDK授权登录或分享的,必须在代码中动态注册AppId、AppSecret,同样代码中明文用的也应该是加密后的值。

2、第三方开放平台

首先,鄙视下手Q,竟然连包名和签名都不校验,也不知道是为了简化开发者接入流程还是其它原因,这不是坑爹么。

对于微信和新浪微博等开放平台,需要重新思考下校验机制,目前的包名+签名校验方式肯定是不安全的了,当然现在是不可能整体更换方案了,修复针对点是保证授权分享调起者是真正的官方应用。个人有以下几点建议:

a、增加Context的校验,防止使用自定义的Context伪装包名(最简单)。 
b、授权登录回调禁用广播监听器等方式,使用指定Activity启动回调,难以被拦截和伪装,类似微信这种。 
c、接口API调用严禁明文暴露调用发起者的AppId、AppSecret,比如微信授权时chromium的log就能抓到这些信息。 
d、需要重视AppId,同时督促开发者保护好这些重要数据。

综上所述,强烈建议开发者按照以上几点排查和处理,同时希望第三方开放平台尽快更新SDK和客户端,修复此漏洞。

来源:CSDN-MegatronKing的博客

上一篇: Android 混淆从入门到精通

下一篇: 9款完美体验的HTML5/jQuery应用

分享到: 更多