SBN

Hunting 0-days in Cisco DCNM with ShiftLeft Ocular

Hunting 0-days in Cisco Data Center Network Manager (DCNM) with ShiftLeft Ocular

Since the CVEs are now public, it’s time to show how ShiftLeft Ocular was used to discover three zero-day vulnerabilities in Cisco DCNM in a matter of hours while sipping some coffee and ranting about the incessant rains in Berlin. The adventure began when our security team came across this blog by Source Incite that showcased their process of discovering some security bugs in Cisco Data Center Network Manager (DCNM). Very insightful stuff. While we were discussing the blog, Niko downloaded the DCNM installer in the background and before we knew it we were knee-deep in the CPGs generated by Ocular. In this blog, we describe what happened next and how we found the bugs in a short span of time.

The Security Advisories

Before we begin, here are the security advisories released by Cisco about the bugs in question a few months after we responsibly disclosed it to them:

Discovery Process

The complete DCNM installation consists of huge quantities of Java code that are mostly part of the jars that the installer installs on the system. Unlike other approaches to hunt bugs where we would have to install DCNM and try to exploit it, ours was done purely by static analysis of the jars. So all we needed was the DCNM installer executable files for version 11.2.1 and 11.3.1.

Unpacking the Installer

  • Interestingly the windows installer can just be unpacked using unzip utility: unzip dcnm-installer-x64-windows.11.2.1.exe -d /tmp/uz
  • After successful extraction, we see a large zip file that we should also unpack: /tmp/uz/InstallerData/Disk1/InstData/Resource1.zip
  • The interesting web applications are in /tmp/uz/InstallerData/Disk1/InstData/$DCNM_SOURCE_PATH$/out/temp/dcnm-san
  • We can now see a lot of jars. An interesting one that we targeted was dcm.ear which contains multiple files like vinci.war. There is also a fm.war which is of interest to us
  • Note that we are completely blind as of now. We don’t know what all these packaged war and jar files do

We will now discuss automated and manual analysis using ShiftLeft Ocular with SQLi and Information Disclosure as an example to showcase how similar bugs can be discovered in other projects.

Discovering SQLi with Automated Analysis

Present in vinci.war inside dcm.ear, part of DCNM 11.3.1 Windows Installer

We were ready to do some in-depth auditing but started by checking what Ocular had found on its own. Unfortunately for DCNM, and to our fortune, Ocular just made it too easy 🤷

It took almost 5 minutes to find it and another 5 minutes to verify it in code. The process was to simply to start Ocular shell and just run the following commands to import code, generate an automatic security profile, and print the security findings:

$ sl ocular
...
 █████╗   ██████╗ ██╗   ██╗██╗      █████╗  ██████╗
██╔═══██╗██╔════ ╝██║ ██║██║ ██╔══██╗ ██╔══██╗
██║ ██║██║ ██║ ██║██║ ███████║ ██████╔╝
██║ ██║██║ ██║ ██║██║ ██╔══██║ ██╔══██╗
╚██████╔╝╚██████╗ ╚██████╔╝███████╗██║ ██║ ██║ ██║
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝
Version: 0.3.113
Type `help` or `browse(help)` to begin
ocular> importCode("vinci.war")
ocular> run.securityprofile
ocular> cpg.finding.p

The above command prints a long list of automatically discovered vulnerabilities using Ocular’s dataflow tagging and analysis. We then filtered the long list simply by searching for titles related to SQL Injection and Ocular magically returned a vulnerability along with the exact data-flow:

Let’s explain a bit more about how Ocular’s engine could generate the above finding. As Ocular creates the CPG from code, it also tags certain sources and sinks based on the knowledge that we have embedded in it. For example, in this case, Ocular understood that the getStaticReceiverOperationmethod has some parameters that may be attacker-controlled and that this method is a handler for a route as well. Ocular was also able to understand that the parameter ticket is the exact one that is attacker-controlled since it is a query parameter. Now Ocular also understands that executeQuery is an important sink and if an unsanitized dataflow exists between these two points in code, then it is almost certain that it will be a vulnerability of type SQLi. And Voila! 🎉 It generates a “security finding” with all this information. The flow generated along with the finding clearly shows the ticket variable flowing down from the getStaticReceiverOperationProgress() source method in the file PMNFlowManager.java and eventually reaching the executeQuery sink method from the Java SQL library. We could follow it up with another Ocular query that gives us the web-routes for which getStaticReceiverOperationProgress() method is the handler:

ocular> cpg.method.name("getStaticReceiverOperationProgress()")
.tag.name("EXPOSED_METHOD_ROUTE").value.l
...
List("pmn/progress/{ticket}")

This can help the pen-testers re-verify this. And this is exactly what the Cisco PSIRT team did when we disclosed this route and the attached dataflow to them!

So now we can go on and verify in the code if we really want to be sure:

PMNFlowManager.java

@GET
@Path(value = "/progress/{ticket}")
public Response getStaticReceiverOperationProgress(@ApiParam(value = "ticket", required = true) @PathParam(value = "ticket") String ticket) {
StatusCode res = StatusCode.Success;
Object returnstatus = null;
Object errorDetail = "";
String desc = String.format("Invoked get static receivers operation process with ticket: %s.", ticket);
try {
PMNLog4jLogger.info((Object)(desc + " call getStaticReceiverOperationProgress with ticket:" + ticket));
HashMap < String, Object > progress = new HashMap < String, Object > ();
List srs = StaticReceiverDAO.fetchAll((String) ticket);

StaticReceiverDAO.java

public static List < StaticReceiver > fetchAll(String ticket) {
if (ticket != null) {
String SQL_SELECT_ALL_STATIC_RECEIVER_MATCHING_TICKET = “SELECT host_ip, source, multicast_ip, device_ip, interface_name, deploy_status, creation_time, modified_time, pod, vrf from pmn_static_receivers where deploy_status=’” + ticket + “‘“;
rs = stmt.executeQuery(SQL_SELECT_ALL_STATIC_RECEIVER_MATCHING_TICKET);

Discovering Information Disclosure with Manual Analysis

Present in SanAnalytics in jaxws-san.jar which is part of dcm.ear inside DCNM 11.3.1 Windows Installer

After covering a fully automated analysis, let’s see how we actually used our brain this time along with Ocular’s assistance to find the next bug. This one involved understanding usual suspects of authentication bypass and finding if we actually had one in the code. We again loaded up Ocular and imported jaxws-san.jar Our approach now can be summarized as follows:

  • Find if there is some method that is used for validation etc. Usually, such methods may have names like isValid* etc.
  • See who calls those validation methods and whether the validation method is itself secure or not.

To do that, we can use the following Ocular Query:

ocular> cpg.method.name(".*\\.isValid.*").callIn.method.name.l
...
List("doFilter")

So it clearly shows that the validity function is called by a doFilter method. Further investigation by Ocular shows that it has a web-route ( SanAnalysis/auth/*) linked to it which is defined as a <filter-mapping> route in web.xml. Its time to now confirm if that request data actually reaches the sanitization method. To achieve this, we crafted some queries that mark all the incoming calls to methods with isValid* in their name as sinks and see if there are incoming flows to it.

So, quite clearly, we have a valid flow from the servletRequest from doFilter to isValidToken. But what is actually happening in isValidToken? For this we just used Ocular to print the code expressions of the method and manually verify what the validity function is doing. And of course, it's not very pretty as you can see below 😉

AuthFilter.java

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
if (AuthFilter.isValidToken(servletRequest)) {
chain.doFilter(request, response);
servletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
servletResponse.setHeader("Pragma", "no-cache");
servletResponse.setDateHeader("Expires", 0 L);
} else {
servletResponse.sendError(401);
}
}
public static boolean isValidToken(HttpServletRequest servletRequest) {
Object token = null;
return true;
}

SanAnalysis.war/WEB-INF/web.xml

<filter>
<display-name>AuthenticationFilter</display-name>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>com.cisco.sananalytics.filters.AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/SanAnalytics/auth/*</url-pattern>
</filter-mapping>

The last remaining XSS vulnerability was also discovered with a similar mix of automated and manual analysis to confirm the data-flow, so we can skip this since more information about that is already in the Cisco disclosure. So all in all, it was a fun hacking session with the folks here at ShiftLeft.

These bugs were discovered by Niko Schmidt, Niklas Jacob and myself during our routine meetings and I would like to thank the other two researchers!

Keep Calm and Hack On!


Hunting 0-days in Cisco DCNM with ShiftLeft Ocular was originally published in ShiftLeft Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.


*** This is a Security Bloggers Network syndicated blog from ShiftLeft Blog - Medium authored by Suchakra Sharma. Read the original post at: https://blog.shiftleft.io/hunting-0-days-in-cisco-dcnm-with-shiftleft-ocular-a3091bb8ef29?source=rss----86a4f941c7da---4