weblogic0638_Java安全之Weblogic 2016-0638分析
Java安全之Weblogic 2016-0638分析
0x00 前言
續(xù)上篇文的初探weblogic的T3協(xié)議漏洞,再談CVE-2016-0638, CVE-2016-0638是基于 CVE-2015-4852漏洞的一個(gè)繞過。
0x01 環(huán)境搭建
補(bǔ)丁環(huán)境搭建
這里采用上次的weblogic環(huán)境,但是在這里還需要打一個(gè)補(bǔ)丁包,來修復(fù) CVE-2015-4852漏洞后,對(duì)該漏洞進(jìn)行一個(gè)繞過。
CVE-2015-4852的修復(fù)補(bǔ)丁為p21984589_1036_Generic,由于在互聯(lián)網(wǎng)上并沒有找到該補(bǔ)丁包,只能通過官網(wǎng)下載,官網(wǎng)下載需要購(gòu)買對(duì)應(yīng)的服務(wù),所以在這里找了p20780171_1036_Generic和p22248372_1036012_Generic這兩個(gè)補(bǔ)丁包,p21984589_1036_Generic是前面這兩個(gè)補(bǔ)丁包的集成。
因?yàn)榍懊娲罱ㄊ莇ocker的環(huán)境,需要將這兩個(gè)補(bǔ)丁包上傳到docker鏡像里面去,然后進(jìn)行安裝。
命令整理:
docker cp ../p20780171_1036_Generic weblogic1036jdk7u21:/p20780171_1036_Generic
docker cp ../p22248372_1036012_Generic weblogic1036jdk7u21:/p22248372_1036012_Generic
docker exec -it weblogic1036jdk7u21 /bin/bash
cd /u01/app/oracle/middleware/utils/bsu
mkdir cache_dir
vi bsu.sh 編輯MEM_ARGS參數(shù)為1024
cp /p20780171_1036_Generic/* cache_dir/
./bsu.sh -install -patch_download_dir=/u01/app/oracle/middleware/utils/bsu/cache_dir/ -patchlist=EJUW -prod_dir=/u01/app/oracle/middleware/wlserver/
cp /p22248372_1036012_Generic/* cache_dir/
./bsu.sh -install -patch_download_dir=/u01/app/oracle/middleware/utils/bsu/cache_dir/ -patchlist=ZLNA -prod_dir=/u01/app/oracle/middleware/wlserver/ –verbose
重啟weblogic服務(wù)。
/u01/app/oracle/Domains/ExampleSilentWTDomain/bin/startWebLogic.sh
這里看到weblogic 2015-4852的payload打過去,并沒有像以往一樣,創(chuàng)建一個(gè)文件。那么就說明補(bǔ)丁已經(jīng)打上了,已經(jīng)能夠修復(fù)該漏洞了。這里是切換了JDK7u21和cc1的利用鏈依舊沒打成功。
遠(yuǎn)程調(diào)試
接下來還是需要將里面的依賴包給拷一下。
mkdir wlserver1036
mkdir coherence_3.7
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/modules ./wlserver1036
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/wlserver/server/lib ./wlserver1036
docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./coherence_3.7/lib
下面來對(duì)該補(bǔ)丁進(jìn)行一個(gè)繞過。
0x02 補(bǔ)丁分析
補(bǔ)丁作用位置:
weblogic.rjvm.InboundMsgAbbrev.class :: ServerChannelInputStream
weblogic.rjvm.MsgAbbrevInputStream.class
weblogic.iiop.Utils.class
在分析漏洞前,先來看到一下,上一個(gè)漏洞點(diǎn)的補(bǔ)丁是怎么進(jìn)行修復(fù)的。
在這其實(shí)看到該resolveClass方法的位置,前面加多一個(gè)判斷。
前面判斷className是否為空,ClassName的長(zhǎng)度是否為零,但是重點(diǎn)是ClassFilter.isBlackListed方法。
這里先打一個(gè) CVE-2015-4852 exp過來,在該位置打個(gè)斷點(diǎn),跟蹤進(jìn)該方法,查看怎么進(jìn)行防護(hù)。
跟進(jìn)進(jìn)來后,先別急著看后面的,因?yàn)橄旅孢€有一個(gè)靜態(tài)代碼塊,靜態(tài)代碼塊中代碼優(yōu)先執(zhí)行,需要先來查看靜態(tài)代碼塊內(nèi)容。
這里前面有兩個(gè)判斷,判斷中都調(diào)用了兩個(gè)方法,來看看這兩個(gè)方法的實(shí)現(xiàn)。
一個(gè)是判斷是否為weblogic.rmi.disableblacklist,一個(gè)是判斷是否為weblogic.rmi.disabledefaultblacklist,寫法有點(diǎn)奇怪,可能是因?yàn)槭莄lass文件的緣故。
這兩個(gè)判斷為true的話,就會(huì)執(zhí)行來到下一步調(diào)用updateBlackList將后面的一系列黑名單的類傳入到里面去。
updateBlackList該方法從名字得知,就是一個(gè)黑名單列表添加的一個(gè)方法,將黑名單內(nèi)容添加到一個(gè)HashSet里面去。查看具體實(shí)現(xiàn)。
StringTokenizer 構(gòu)造方法:為指定的字符串構(gòu)造一個(gè)字符串tokenizer。
hasMoreTokens方法:返回與 hasMoreTokens方法相同的值。
nextToken 方法:返回此字符串tokenizer字符串中的下一個(gè)令牌。
總體的來理解就是構(gòu)造一個(gè)字符串,然后遍歷里面的值,然后調(diào)用processToken方法將該值傳遞進(jìn)去。
再來看到processToken方法。
里面判斷如果開頭是+號(hào),則截取第一位后面的值添加到黑名單的這個(gè)HashSet里面去。如果是-號(hào)則移除,如果開頭不是前面的+ -號(hào)則直接添加到黑名單里面去。
到這里靜態(tài)代碼塊就已經(jīng)分析完成了,總的來說其實(shí)就是將一些危險(xiǎn)的類,添加到了黑名單里的一個(gè)步驟。
黑名單列表為:
+org.apache.commons.collections.functors,
+com.sun.org.apache.xalan.internal.xsltc.trax,
+javassist,+org.codehaus.groovy.runtime.ConvertedClosure,
+org.codehaus.groovy.runtime.ConversionHandler,
+org.codehaus.groovy.runtime.MethodClosure
返回剛剛的ClassFilter.isBlackListed方法進(jìn)行跟蹤
最后這里調(diào)用了contains方法判斷 這個(gè)pkgName存不存在黑名單中,存在的話這里返回true。
返回到resolveClass方法可以看到這里為true,就會(huì)直接拋異常。
如果不存在于黑名單中,會(huì)來到else這個(gè)分支的代碼塊中調(diào)用父類的resolveClass方法。
而這一個(gè)點(diǎn),只是過濾的一個(gè)點(diǎn),下面來看看過濾的點(diǎn)都有哪些。
再來看下一個(gè)點(diǎn)MsgAbbrevInputStream的位置
這里也是調(diào)用ClassFilter.isBlackListed方法進(jìn)行過濾,和前面的是一樣的。以此類推。
0x03 工具分析
在CVE-2016-0638里面用到了weblogic_cmd工具,github地址。
下面來看看該工具的實(shí)現(xiàn),再談漏洞的繞過方式。
下載該源碼后,導(dǎo)入IDEA中,配置命令參數(shù)。
這里如果報(bào)錯(cuò)找不到sun.tools.asm包的話,需要將Tools.jar包手動(dòng)添加一下。在這我是使用jdk1.6進(jìn)行執(zhí)行的,使用1.8版本會(huì)找不到sun.org.mozilla.javascript.internal.DefiningClassLoader類
在Main的類中打個(gè)斷點(diǎn)進(jìn)行執(zhí)行。
前面都是代碼都是進(jìn)行一個(gè)配置,這里斷點(diǎn)選擇落在該方法中。
選擇跟蹤
繼續(xù)跟蹤WebLogicOperation.blindExecute方法。
前面判斷了服務(wù)器類型,重點(diǎn)在SerialDataGenerator.serialBlindDatas方法中,payload由該方法進(jìn)行生成。跟進(jìn)查看一下該方法如何生成payload。
在這先選擇跟蹤blindExecutePayloadTransformerChain方法。
在這里又看到了熟悉的面孔,CC鏈的部分代碼。
回到剛剛的地方,跟蹤serialData方法
在這里就看到了CC鏈后面的一段代碼,這組合成了一條CC1利用鏈。但是在后面調(diào)用了BypassPayloadSelector.selectBypass方法來處理在原生的利用鏈中本該直接進(jìn)行序列化的對(duì)象。
跟進(jìn)該方法進(jìn)行查看。
這里面還會(huì)去調(diào)用Serializables.serialize,依舊先跟蹤最里層的方法。
這傳入一個(gè)obj對(duì)象和out對(duì)象,進(jìn)行了序列化操作。然后將序列化后的數(shù)據(jù)寫到out對(duì)象中。
執(zhí)行完成后,返回上一個(gè)點(diǎn),剛才分析得知返回的是序列化后的數(shù)據(jù)。所以在處調(diào)用streamMessageImpl方法傳遞的參數(shù)也是序列化的數(shù)據(jù)。
跟蹤查看。
內(nèi)部是new了一個(gè)weblogic.jms.common.StreamMessageImpl的實(shí)例,然后調(diào)用setDataBuffer方法將序列化后的對(duì)象和序列化后的長(zhǎng)度傳遞進(jìn)去。
執(zhí)行完這步后,回到這個(gè)地方
后面的這個(gè)方法是進(jìn)行序列化操作的,這里又對(duì) streamMessageImpl的實(shí)例對(duì)象進(jìn)行了一次序列化。該方法在前面查看過了,這里就不跟進(jìn)去看了。
而最后來到了這里。
而后面這個(gè)方法就是構(gòu)造特定的數(shù)據(jù)包,使用T3協(xié)議發(fā)送payload。
0x04 漏洞分析
那么如果需要繞過的話,我們需要找一個(gè)類,他的類在內(nèi)部的readObject方法創(chuàng)建了自己的InputStream的對(duì)象,但是又不能為黑名單里面過濾掉的ServerChannelInputStream和MsgAbbrevInputStream里面的readObject方法。然后調(diào)用該readObject 方法進(jìn)行反序列化,這時(shí)候就可以達(dá)成一個(gè)繞過的效果。
在師傅們的挖掘中尋找到了weblogic.jms.common.StreamMessageImpl#readExternal(),StreamMessageImpl類中的readExternal方法可以接收序列化數(shù)據(jù)作為參數(shù),而當(dāng)StreamMessageImpl類的readExternal執(zhí)行時(shí),會(huì)反序列化傳入的參數(shù)并調(diào)用該參數(shù)反序列化后對(duì)應(yīng)類的這個(gè)readObject方法。
繞過原理如下:
將反序列化的對(duì)象封裝進(jìn)了 StreamMessageImpl,然后再對(duì) StreamMessageImpl 進(jìn)行序列化,生成 payload 字節(jié)碼。反序列化時(shí) StreamMessageImpl 不在 WebLogic 黑名單里,可正常反序列化,在反序列化時(shí) StreamMessageImpl 對(duì)象調(diào)用 readObject 時(shí)對(duì) StreamMessageImpl 封裝的序列化對(duì)象再次反序列化,這樣就逃過了黑名單的檢查。
在此先再來思考一個(gè)問題,weblogic.jms.common.StreamMessageImpl#readExternal()該方法是怎么被調(diào)用的呢?在前面分析原生readObject方法的時(shí)候發(fā)現(xiàn),其實(shí)readObject方法的底層還會(huì)去調(diào)用很多其他方法。
在Weblogic從流量中的序列化類字節(jié)段通過readClassDesc-readNonProxyDesc-resolveClass獲取到普通類序列化數(shù)據(jù)的類對(duì)象后,程序依次嘗試調(diào)用類對(duì)象中的readObject、readResolve、readExternal等方法。而在這里readExternal就會(huì)被調(diào)用。
那么下面來調(diào)試分析一下該漏洞。
還是先在weblogic.rjvm.InboundMsgAbbrev#ServerChannelInputStream.resolveClass地方打個(gè)斷點(diǎn),然后使用weblogic_cmd工具打一個(gè)payload過去,先來查看一下傳輸過來的數(shù)據(jù)。
這里可以看到獲取到的ClassName是weblogic.jms.common.StreamMessageImpl的對(duì)象,而不在再是AnnotationInvocationHandler對(duì)象。StreamMessageImpl不在黑名單中,這里的判斷不會(huì)進(jìn)行拋異常。
下個(gè)斷點(diǎn)直接落在StreamMessageImpl.readExternal中跟蹤一下。
看到調(diào)用棧這里就應(yīng)驗(yàn)了我們前面所提到的關(guān)于StreamMessageImpl.readExternal調(diào)用問題。
這里的var4為正常反序列化后的數(shù)據(jù),而后面會(huì)new一個(gè)ObjectInputStream類傳遞var4參數(shù)進(jìn)去。然后再調(diào)用readObject方法
執(zhí)行完這一步后,命令就已經(jīng)執(zhí)行成功。后面的是對(duì)CC鏈執(zhí)行命令的一個(gè)基本認(rèn)知,在此不做贅述。
參考文章
https://xz.aliyun.com/t/8443#toc-6
https://www.anquanke.com/post/id/224343#h3-6
0x05 結(jié)尾
其實(shí)摸清楚補(bǔ)丁的一個(gè)套路過后,再去基于補(bǔ)丁分析后面的漏洞會(huì)比較清晰。因?yàn)檠a(bǔ)丁無非就是再?gòu)腃lassFilter里面添加黑名單列表,這也是為什么weblogic修修補(bǔ)補(bǔ)又爆洞的原因,并沒有從根本原因去進(jìn)行修復(fù)。
總結(jié)
以上是生活随笔為你收集整理的weblogic0638_Java安全之Weblogic 2016-0638分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 100w氮化镓充电器_SHARGE闪极-
- 下一篇: #中delay函数_ECBM系列教程3: