Author: WhiteHatHui Security Research Institute @kejaly
Proofreading: WhiteHatHui Security Research Institute @r4v3zn
Coherence component is a core component in WebLogic and is built into WebLogic. For official introduction of Coherence component, please refer to: [https://www.oracle.com/java/coherence/]
This article covers the following vulnerabilities: CVE-2021-2135, CVE-2021-2394, CVE-2020-2555, CVE-2020-2883, CVE-2020-14645, CVE-2020-14825, CVE-2020-14841, CVE-2020-14756.
In recent years, deserialization vulnerabilities in the WebLogic Coherence component have been frequently reported. However, there is no public summary of historical deserialization vulnerabilities in the WebLogic Coherence component, which makes it difficult for those who want to learn or understand deserialization vulnerabilities in the WebLogic Coherence component. Therefore, this article provides a summary and analysis of historical deserialization vulnerabilities in the WebLogic Coherence component.
Regarding the architecture of the deserialization vulnerability exploitation chain in the Coherence component, it can be divided into two parts: one is based on the ValueExtractor.extract
exploitation chain architecture, and the other is based on the ExternalizableHelper
exploitation chain architecture.
To understand the history of deserialization vulnerabilities in WebLogic's Coherence component, it is necessary to first understand some interfaces and classes that are frequently involved in Coherence component deserialization vulnerabilities. They often appear in Coherence component deserialization vulnerability exploitation.
com.tangosol.util.ValueExtrator
is an interface:
In Coherence, many classes with names ending in Extrator
implement this interface:
This interface declares an extract
method, and ValueExtractor.extract
is the key to Coherence component historical vulnerabilities (part of the ValueExtractor.extract
chain).
There is a com.tangosol.io.ExternalizableLite
in the Coherence component, which extends java.io.Serializable
and declares two methods readExternal
and writeExternal
.
The com.tangosol.io.ExternalizableLite
interface is similar to the native java.io.Externalizable
in the JDK, but be careful not to confuse them.
The serialization and deserialization of the implementation classes of the com.tangosol.io.ExternalizableLite
interface are accomplished through the ExternalizableHelper
class.
Let's take a closer look at how the ExternalizableHelper
class serializes and deserializes classes that implement the com.tangosol.io.ExternalizableLite
interface. Here, we will take the readObject
method as an example, and readers can refer to the writeObject
method on their own:
If the passed DataInput
is not a PofInputStream
(the DataInput
passed in the ExternalizableHelper.readObject
of the Coherence component historical vulnerabilities is not a PofInputStream
), the ExternalizableHelper#readObject
method will call the ExternalizableHelper#readObjectInternal
method:
In readObjectInternal
, different branches will be entered based on the value of nType
:
For objects that implement the com.tangosol.io.ExternalizableLite
interface, it will enter the readExternalizableLite
method:
As we can see from readExternalizableLite
, at line 1125, the class is loaded according to the class name, the object of this class is instantiated, and then its readExternal()
method is called.
When analyzing the deserialization exploitation chain, we can divide it into four parts: the chain header, the dangerous middle node (vulnerability point), the calling location of the dangerous middle node (trigger point), and finally the exploitation chain tail that uses this node to cause harm.
In the Coherence component's deserialization exploitation chain architecture based on ValueExtractor.extract
, the dangerous middle node is the ValueExtractor.extract
method.
The extract
method in ReflectionExtractor
contains reflective invocation of any object method:
With ChainedExtractor
and ConstantExtractor
, it can achieve a transform
chain call similar to cc1.
CVE-2020-2555, CVE-2020-2883
The extract
method in MvelExtractor
executes any MVEL expression (RCE):
During serialization and deserialization, m_sExpr
participates in the process:
Therefore, m_xExpr
is controllable, which can lead to arbitrary command execution using MvelExtractor.extractor
.
CVE-2020-2883
The extract
method in UniversalExtractor
(unique to Weblogic 12.2.1.4.0) can call the get
and is
prefix parameterless methods in any class, which can be combined with jdbsRowset
to remotely load malicious classes to achieve RCE through JDNI.
For more details, please refer to: https://nosec.org/home/detail/4524.html
CVE-2020-14645, CVE-2020-14825, CVE-2020-14841
The extract()
method in oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor
can call the getAttributeValueFromob ject()
method of any AttributeAccessor
, assigning Accessor
to MethodAttributeAccessor
to achieve arbitrary invocation of any class's parameterless method.
For specific details, please refer to: https://cloud.tencent.com/developer/article/1740557
MethodAttributeAccessor.getAttributeValueFromob ject
is essentially using the existence of arbitrary parameterless method calls in MethodAttributeAccessor.getAttributeValueFromob ject
, which was also used in CVE-2021-2394.
CVE-2020-14825, CVE-2020-14841
There is an arbitrary call to AttributeAccessor.getAttributeValueFromob ject(obj)
in filterExtractor.extract
, and assigning this.attributeAccessor
to MethodAttributeAccessor
can result in arbitrary parameterless method invocation.
For details about readAttributeAccessor
, please refer to CVE-2021-2394: https://blog.riskivy.com/weblogic-cve-2021-2394-rce漏洞分析/ and https://www.cnblogs.com/potatsoSec/p/15062094.html.
CVE-2021-2394
Many dangerous ValueExtractor.extract
methods have been mentioned above. Now let's see where ValueExtractor.extract
methods are called.
In LimitFilter.toString()
, there is an arbitrary ValueExtractor.extract
method call:
As this.m_comparator
is involved in serialization and deserialization, it can be controlled:
We just need to assign this.m_comparator
to a malicious ValueExtractor
to achieve arbitrary ValueExtractor.extract
method calls. The toString
method can be triggered using BadAttributeValueExpException
, which is used in CC5.
CVE-2020-2555
The ExtractorComparator.compare
method is actually a bypass for the patch of CVE-2020-2555. The fix for CVE-2020-2555 modified the Limitfiler.toString
method, which means modifying the place where ValueExtractor.extract
method is called. CVE-2020-2883 found another place where ValueExtractor.extract
is called, which is ExtractorComparator.compare
.
In ExtratorComparator.compare
, there is an arbitrary (because this.m_extractor
participates in serialization and deserialization) call to the ValueExtractor
extract
method.
The Comparator.compare
method can be triggered through PriorityQueue.readobject
used in CC2.
In addition, in weblogic, the BadAttributeValueExpException.readobject
can also implement calling any comparator.compare
method:
CVE-2020-2883, the fix is to blacklist ReflectionExtractor
and MvelExtractor
.
CVE-2020-14645 uses com.tangosol.util.extractor.UniversalExtractor
to bypass, and the fix is to blacklist UniversalExtractor
.
CVE-2020-14825 and CVE-2020-14841 use oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor.LockVersionExtractor
for bypass.
When analyzing the exploit chain architecture of ExternalizableHelper
, we can still divide the chain into four parts: a chain head, a dangerous middle node (vulnerability point), another place that calls the dangerous middle node (trigger point), and finally a chain tail that exploits this node to cause harm.
In the exploit chain architecture of ExternalizableHelper
, the dangerous middle node is the ExternalizableLite.readExternal
method.
WebLogic filters for deserialized classes are performed when loading classes, so the classes loaded in ExternalizableHelper.readExternalizableLite
are not restricted by the blacklist.
The specific reason is: WebLogic's blacklist is based on JEP 290. JEP 290 checks whether the class to be deserialized is a class in the blacklist based on the class name obtained during readObject
. Here, loadClass
is directly used to load the class, so it is not restricted by WebLogic's blacklist. (It can also be understood in this way: JEP 290 is targeted at blacklisting classes when deserializing by checking the class to be loaded. Here, the class is loaded directly through loadClass
, which is not deserialized. Of course, in the subsequent readExternal
, it is still restricted by WebLogic's blacklist because it goes through the deserialization process.)
The WebLogic blacklist mechanism can refer to: https://cert.360.cn/report/detail?id=c8eed4b36fe8b19c585a1817b5f10b9e, https://cert.360.cn/report/detail?id=0de94a3cd4c71debe397e2c1a036436f, https://www.freebuf.com/vuls/270372.html.
The readExternal
method of com.tangosol.util.aggregator.TopNAggregator.PartialResult
will trigger any comparator.compare
method.
Roughly, the principle is:
javaCopy code
On line 149, the comparator is passed as a parameter to the constructor of TreeMap.
Then on line 153, this.add is called, which calls this.m_map.put, which means calling the put method of TreeMap, which leads to the call of comparator.compare().
For a detailed analysis, please refer to: https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ
Then calling comparator.compare
can lead to ExtractorComparator.compare
and achieve RCE.
CVE-2020-14756 (January)
The first exploitation of ExternalizableHelper
appeared in CVE-2020-14756. It exploits the fact that ExternalizableHelper
deserialization loads classes through loadClass
, so it is not restricted by the blacklist previously set by WebLogic. For specific exploits, please refer to: https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ.
The fix for CVE-2020-14756 is to check the Datainput
passed to the readExternalizable
method, and if it is an ObjectInputStream
, call checkObjectInputFilter()
to check it. checkObjectInputFilter
specifically checks using JEP 290.
CVE-2021-2135 (April)
The fix solution for the above patch only checks the case where the DataInput
is an ObjectInputStream
, but does not filter other types of DataInput
.
Therefore, we only need to find other places where the readExternalizableit
function is called and the parameter passed in is not an ObjectInputStream
.【ObjectInputStream
is generally the most common and usually comes in the form of a chain where the upstream is the common readObject
, so the patch may only pay attention to the case of ObjectInputStream
.】
Therefore, the method used to bypass CVE-2021-2135 is to set the parameter type passed to the readExternalizableit
function to BufferInput
.
There are two places in ExternalizableHelper
that call readObjectInternal
, one is readObjectInternal
, and the other is deserializeInternal
. deserializeInternal
first converts DataInput
to BufferInput
:
So just find the place where ExternalizableHelper.deserializeInternal
is called.
And ExternalizableHelper.fromBinary
(on the same level as ExternalizableHelper.readObject
) calls deserializeInternal
, so just find a place where ExternalizableHelper.fromBinary
is used for deserialization to connect to the later (CVE-2020-14756) exploitation chain.
Then find the places where the getKey
and getValue
methods of SimpleBinaryEntry
are called, which contain calls to ExternalizableHelper.fromBinary
.
Then in the equals
method overridden in com.sun.org.apache.xpath.internal.objects.XString
, tostring
is called, which in turn calls getKey
method.
In ExternalizableHelper#readMap
, map.put
is called which in turn calls equals
method.
In com.tangosol.util.processor.ConditionalPutAll
, ExternalizableHelper#readMap
is called in readExternal
method.
Then, the AttributeHolder
chain is used to exploit the vulnerability.
For more details, please refer to: https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg
The April vulnerability fix is: Add simpleBianry
to the blacklist.
private static final Class[] ABBREV_CLASSES = new Class[]{String.class, ServiceContext.class, ClassTableEntry.class, JVMID.class, AuthenticatedUser.class, RuntimeMethodDesc riptor.class, Immutable.class};
In the filterExtractor.reaExternal
method, the readAttributeAccessor()
method directly creates a new MethodAttributeAccessor
object.
Subsequently, in the filterExtractor.extract
function, a call to this.attributeAccessor.getAttributeValueFromObject
will lead to the invocation of any parameterless method.
CVE-2021-2394 (April)
In the April patch, filtering was applied to the DataInput
stream of OIS, so instantiating a malicious class directly through newInstance
has been prevented (CVE-2021-2135 bypassed the filter using bufferinputStream
). Therefore, it is necessary to find another readExternal
method that is not on the blacklist.
CVE-2021-2394 exploits the filterExtractor.readExternal
method to achieve the attack.
For more information, please refer to: https://blog.riskivy.com/weblogic-cve-2021-2394-rce漏洞分析/ and https://www.cnblogs.com/potatsoSec/p/15062094.html
The triggering points of ExternalizableHelper.readExternal
are ExternalizableHelper.readObject
and ExternalizableHelper.fromBinary
. In CVE-2021-2135, the fix for CVE-2020-14756 only focused on ExternalizableHelper.readObject
and added restrictions only in that method, but did not consider ExternalizableHelper.fromBinary
, leading to a bypass.
ExternalizableHelper.readObject
can be triggered using com.tangosol.coherence.servlet.AttributeHolder
, which implements the java.io.Externalizable
interface and calls ExternalizableHelper.readObject(in)
in its readExternal
method.
The triggering of ExternalizableHelper.fromBinary
is more complex and can be referred to at: https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg
Many of the weblogic Coherence deserialization vulnerabilities are related, and for a specific vulnerability, it is likely to use some of the previous vulnerabilities in the chain. In fact, not only weblogic, but other deserialization chains in Java are also like this, and many situations involve one chain using a part of another chain. Therefore, in the learning process, it is important to summarize and analyze the vulnerabilities of a component or library together. Finally, I hope this article can help other friends who are learning deserialization.
https://nosec.org/home/detail/4524.html
https://cloud.tencent.com/developer/article/1740557
https://blog.riskivy.com/weblogic-cve-2021-2394-rce%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/
https://www.cnblogs.com/potatsoSec/p/15062094.html
https://cert.360.cn/report/detail?id=c8eed4b36fe8b19c585a1817b5f10b9e
https://cert.360.cn/report/detail?id=0de94a3cd4c71debe397e2c1a036436f
https://www.freebuf.com/vuls/270372.html
https://mp.weixin.qq.com/s/E-4wjbKD-iSi0CEMegVmZQ
https://mp.weixin.qq.com/s/eyZfAPivCkMbNCfukngpzg
[Goby Official URL](https://gobies.org/)
If you have a functional type of issue, you can raise an issue on GitHub or in the discussion group below:
- GitHub issue: https://github.com/gobysec/Goby/issues
- Telegram Group: http://t.me/gobies (Community advantage: Stay updated with the latest information about Goby features, events, and other announcements in real-time.)
- Telegram Channel: https://t.me/joinchat/ENkApMqOonRhZjFl
- Twitter:https://twitter.com/GobySec