Ivanti has recently published an advisory for CVE-2023-38035. The vulnerability has been added to CISA KEV and is described as an authentication bypass in the Ivanti Sentry administrator interface. This new vulnerability comes on the heels of an in-the-wild-exploited vulnerability in Ivanti EPMM (CVE-2023-35078). In this post we will take a deep dive into how this new vulnerability can be used to give an attacker the ability to remotely execute code as the root user. You can find our PoC here.
The advisory contains rpm files that we can use to patch supported versions of Ivanti Sentry. We use the tool rpm2cpio
to examine the contents of these files to start to get an idea of how the patch works.
We find two more rpm files, one described as mi-mics
and another described as mi-system-scripts
. Let’s see what’s in the mi-mics
rpm.
From this file listing, we are quickly drawn to mics.war
. We assume that mics.war
contains majority of the code for the Sentry web interface. Next, let’s pull a vulnerable mics.war
from a live system and compare the contents.
Luckily for us, there aren’t that many differences considering we are comparing Sentry version 9.12
with 9.18
. After some digging, we notice that a service has been removed from the remoting-servlet.xml
file.
We also see that the endpoint for services/
has no authentication requirements.
We see that the removed service should expose the interface described by com.mi.middleware.service.ConfigService
and should be implemented in the configServiceHandler
class. Let’s see if we can find those classes.
It appears we can find the ConfigService
interface in common-10.6.0.1s-1.jar
and the implementing class, configServiceHandler
, in mics-core-9.12.0-R9.12.0.jar
. Let’s see what interface the service offers.
Let’s take a step back and see how we are supposed to call these functions. We know from the advisory that this should be an HTTP vulnerability, but these functions don’t look like your typical HTTP endpoints. If we look back at remoting-servlet.xml
from earlier we see that this service references a class called SentryMicsHessianServiceExporter
. We have never heard of Hessian before, but after some searching on the internet it appears to be a type of binary/XML RPC. http://hessian.caucho.com/doc/
We can use the python-hessian
package to try to connect this this service.
Here, we can see that its pretty easy to call methods from this service. The only complicating factor is that there doesn’t seem to be an easy way to disable SSL certificate checking. To get around this, we monkey patch HTTPSConnection
used by python-hessian
.
At first, it seems like there is a command injection in the doMICSServiceOperation
endpoint. This endpoint ultimately calls Java’s Runtime.exec
with attacker controlled arguments. However, it is really just an argument injection, not a full command injection. The endpoint passes the string /usr/bin/sudo /sbin/service <attacker input> <attacker input>
to Runtime.exec
. It appears on this system, Runtime.exec
does not run this command through a shell so the normal bash command substitutions won’t work. It seems challenging to get RCE using attack path. Shifting our attention, we notice that there are some changes to httpd configuration files for similar hessian endpoints.
Let’s take a look at the MICSLogService
.
After some searching, we find an interesting method named uploadFileUsingFileInput
This function takes a SystemCommandRequestDTO
and passes it to a thread (new 1(this,requestDTO)
, this is a decompiler artifact). Let’s take a look at what this thread does.
We can see on line 44, attacker controlled input is passed into rt.exec
. This time, our input is passed directly to the function so we don’t have to worry about not having shell parsing like last time. We just need to figure out how to pass a SystemCommandRequestDTO
which has the following form.
We can simply pass a Python dictionary with the same layout. Our updated PoC now looks like this with a curl
payload.
There aren’t any definitive IoCs that we have found so far. However, any unrecognized HTTP requests to /services/*
should be cause for concern. The endpoint that we exploited is likely not the only one that would allow an attacker to take control of the machine.
Ivanti Sentry doesn’t offer a standard Unix shell, but if a known exploited system is being forensically analyzed, /var/log/tomcat2/
contains access logs that can be used to check which endpoints were accessed.
Lastly, there are logs in the web interface that might be of use to check for any suspicious activity.
We were able to successfully utilize an exposed endpoint to execute arbitrary commands without any authentication. Shodan shows that this product has over 500+ instances exposed on the internet.
We recommend that any affected users of this product patch and verify that it is not exposed externally to the internet if possible.