安卓系统服务漏洞 的挖掘与利用 龚广安全研究员奇虎 360 @oldfresher
主要内容 安卓的 Binder 机制 攻击界面介绍 挖掘系统服务漏洞 漏洞实例介绍 CVE-2015-1528 的利用
安卓的 Binder 机制
攻击界面
第一层系统服务接口 ggong@ggong-pc:~/develop/aosp/lol51$ adb shell service list Found 97 services: 0 sip: [android.net.sip.isipservice] 1 phone: [com.android.internal.telephony.itelephony] 2 isms: [com.android.internal.telephony.isms] 3 iphonesubinfo: [com.android.internal.telephony.iphonesubinfo] 4 simphonebook: [com.android.internal.telephony.iiccphonebook] 5 isub: [com.android.internal.telephony.isub] 6 nfc: [android.nfc.infcadapter] 81 acvvity: [android.app.iacvvitymanager] 82 user: [android.os.iusermanager] 83 package: [android.content.pm.ipackagemanager] 89 media.camera: [android.hardware.icameraservice] 90 media.player: [android.media.imediaplayerservice] 91 SurfaceFlinger: [android.ui.isurfacecomposer] 96 android.security.keystore: [android.security.keystore]
第二层系统服务接口 class IMediaPlayerService: public IInterface { public: DECLARE_META_INTERFACE(MediaPlayerService); virtual sp<imediarecorder> createmediarecorder() = 0; virtual sp<imediametadataretriever> createmetadataretriever() = 0; virtual sp<imediaplayer> create(const sp<imediaplayerclient>& client, int audiosessionid = 0) = 0; virtual sp<iomx> getomx() = 0; virtual sp<icrypto> makecrypto() = 0; virtual sp<idrm> makedrm() = 0; virtual sp<ihdcp> makehdcp(bool createencryptionmodule) = 0; virtual sp<imediacodeclist> getcodeclist() const = 0; virtual sp<iremotedisplay> listenforremotedisplay(const sp<iremotedisplayclient>& client, const String8& iface) = 0;...
Chrome 沙箱 安卓中的 Chrome 沙箱 shell@hammerhead:/ $ ps -Z grep chrome u:r:untrusted_app:s0 u0_a52 com.android.chrome u:r:untrusted_app:s0 u0_a52 com.android.chrome:privileged_process0 u:r:isolated_app:s0 u0_i0 com.android.chrome:sandboxed_process0 public stavc void addservice(string name, IBinder service, boolean allowisolated)
(gdb) plist svclist next 0xb6c4be38: u"acvvity" Chrome 沙箱 $2569 = {next = 0xb6c50100, handle = 16, allow_isolated = 1, name = 0xb6c4be38} 0xb6c50118: u"user" $2570 = {next = 0xb6c500d8, handle = 15, allow_isolated = 0, name = 0xb6c50118} 0xb6c500f0: u"package" $2571 = {next = 0xb6c500b0, handle = 14, allow_isolated = 0, name = 0xb6c500f0} 0xb6c500c8: u"display" $2572 = {next = 0xb6c50088, handle = 11, allow_isolated = 1, name = 0xb6c500c8}
弱点
类比
The simplest Fuzzer
发现的漏洞 CVEs Android Bug ID Vulnerability Descrip9on CVE-2015-1474 18076253 A local applicavon could escalate privileges to system due to an integer overflow in the GraphicBuffer class CVE-2015-1528 19334482 Integer Overflow in Android libcuvls can be exploited to get system_server permission CVE-2015-1525 18262893 A local applicavon could cause a denial-of-service to the audio_policy app CVE-2015-1530 18226810 An integer overflow in Android media could be exploited to get media_server permission CVE-2015-1529 19385640 Integer overflow could cause a denial-of-service to SoundTriggerHwService CVE-2015-1527 19261727 Integer overflow leading to heap corrupvon in IAudioPolicyService.cpp CVE-2015-1526 A local applicavon could cause a denial-of-service to media_server CVE-2015-1537 20222489 A local applicavon could escalate privileges to media_server due to an integer overflow in IHDCP
CVE-2015-1530
CVE-2015-1525
CVE-2015-1474
CVE-2015-1528 此漏洞在最新的 Android 5.1 上暂时还没修复
CVE-2015-1528
分步提权
漏洞利用难点 通过 Binder 调用利用堆破坏漏洞 障碍处理请求的线程池地址空间布局随机化 (ASLR) 只能写相邻连续空间 DEP 不能加载 SO 文件 解决办法 挂起 N-1 个线程 信息泄露 覆盖 je_malloc 元数据实现任意写 ROP 从内存中加载 SO execmem, execmod?
Je_malloc 的一个特性 不同的线程分配的空间在不同的内存块中 (Chunk) Je_malloc 中 chunk 的分布
多个 Binder 服务线程 控制 Binder 服务线程是为了堆风水 Mediaserver 中的 Binder 服务线程
挂起 N-1 个线程 BufferQueue IGraphicBufferProducer setbuffercount apachbuffer requestbuffer IGraphicBufferConsumer system_server, surfaceflinger,mediaserver 都会用到 BufferQueue, 都会向外导出 IGraphicBufferProducer 接口, 通用性好
挂起状态的线程栈
堆内存泄露 IGraphicBufferProducer->requestBuffer 继承
堆内存泄露
地址信息泄露 泄露堆地址 在泄露的堆内容中搜索特定结构 泄露多个模块基址 搜索函数指针 泄露栈地址 搜索 pthread_internal_t structrue
pthread_internal_t 泄露栈的位置
任意地址写 ü 每一个大小类别维护一个指针表 (gdb) p je_small_bin2size_tab $24 = {8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 640, 768, 896, 1024, 1280, 1536, 1792, 2048, 2560, 3072, 3584} ü 指针表描述结构 ü (gdb) p je_arenas[0].tcache_ql.qlh_first.tbins[11] $9 = {tstats = {nrequests = 17}, low_water = 62, lg_fill_div = 1, ncached = 63, avail = 0xb6003f60} ü 指针表内容 (128) (gdb) x/63xw je_arenas[0].tcache_ql.qlh_first.tbins[11].avail 0xb6003f60: 0xb6057f80 0xb6057f00 0xb6057e80 0xb6057e00 0xb6003f70: 0xb6057d80 0xb6057d00 0xb6057c80 0xb6057c00 0xb6003f80: 0xb6057b80 0xb6057b00 0xb6057a80 0xb6057a00 0xb6003f90: 0xb6057980 0xb6057900 0xb6057880 0xb6057800 0xb6003fa0: 0xb6057780 0xb6057700 0xb6057680 0xb6057600
绕过 Selinux 的限制 加载执行 so 文件的流程
Shell 成功利用后得到被攻击服务进程的 shell
SurfaceFlinger 和 System_Server
利用代码 hpps://github.com/secmob/ PoCForCVE-2015-1528