February 28, 2022
Contributed by Cody Craig, Cyber Investigator, CYDERES
Threat actors have been observed dropping malicious Java Class files during Log4Shell exploitation. The sample reviewed in this post showed indication that it came from an attack that exploited the Log4Shell vulnerability via Apache in VMware Horizon. A deeper look into the capabilities and use of the malicious Java Class file observed is essential for defenders to better understand and defend their environments against the threat.
Attack Overview
Recently, the U.K. National Health Service (NHS) digital security team observed an unknown threat actor actively targeting VMware Horizon servers to establish web shells. The attack observed by the NHS showed indication that the initial payload was a variation of $ jndi : ldap : // payload } as it was exploiting the Log4Shell vulnerability in the Apache Service of VMware Horizon servers. The attack cycle outlined by the NHS, and currently being observed in the wild, is to use a malicious Java Class to execute PowerShell scripts. These PowerShell scripts are leveraged to replace the instances of ‘nssm.exe’ with a modified version of the file ‘lib\absg-worker.js.’ The code injected into this modified file will look for a specific URI (line #194), and if this URI is observed, commands from the ‘data’ section are executed (line #197), giving the threat actor a web shell on the server.
Figure 1: File Modification
Additional phases of this attack cycle observed by our team included enumerating system and domain information and modifying a ‘web.xml’ file. The enumerated data was saved as a ZIP file with a ‘.js’ extension, likely to remain hidden during reconnaissance. Modifying the ‘web.xml’ file occurred during the same time frame that the new Java Class was dropped on the server. This modification reflected the addition of a new listener allowing the malicious Class file to access requests sent to the VMware Horizon server.
Java Class Analysis
To allow the Class to capture the data from a webListener or servletContext, the Class implements the ServletRequestListener interface. This interface is for receiving notification events about requests coming into and going out of the scope of a web application. The Class will access these requests and begin to cross-check cookies with a hashed value.
Figure 2: Gathering Strings for Checking Against Cookies
To gather these hashed values, the Class file will use environmental variables of ‘USERDOMAIN’ and ‘COMPUTERNAME’ (line #35) as a base string. This base string will either be appended with ‘cla,’ ‘js,’ or nothing prior to being passed into the private hash function (lines #36 – #42).
The Class file will later use this string to determine what actions to take. To do this, access to the request must be obtained. The function requestInitialized is leveraged to access the entire request from the ServletRequest and sets it to be accessible (line #94). This value is stored in the ‘request’ variable (line #95).
Figure 3: Gaining Access to the Request
Once the request is accessed, the Class file begins checking the name of the request cookie against the hashed strings composed of the ‘USERDOMAIN’ and ‘COMPUTERNAME’ environmental variables. This leverages the GetCookieValue function by passing the function the request and the various hashed strings. If the cookie from the request and the hashed string is a match (line #50), the value of the cookie is returned.
Figure 4: GetCookieValue Function
The first if statement from the requestInitialized function is likely leveraged as a flag to determine if code execution is possible. This recon statement passes the request and the value of ‘TagCookieStr’ to the GetCookieValue function (line #97). If a value is returned, which would indicate that the cookie value matches the hashed value, a response header is added (line #99).
Figure 5: Recon to Check if Code Can Be Executed
The next if statement passes the request and the value of ‘TagClassStr’ to the GetCookieValue function. If this returns a value other than null (line #101), the function will decode the request (line #105) after setting the amount of space needed. From here, the function takes the thread that the current process is running on and grabs its Class loader (line #106). This allows the Class to use the definedClass function with the parameters of the Class loader and the decoded value (line #107). The definedClass function uses these parameters to take the decoded value and load it as a Java Class returning a Class object. This new Class object starts running on the thread that the current process is running on.
Figure 6: Gathering Content-Length
The last if statement passes the request and the value of ‘TagJavaScriptStr’ to the GetCookieValue function. If this returns a value that is not null (line #111), it will save the returned value to a variable that is then base64 decoded (line #113). After this value is decoded, it is executed via the JavaScript engine available (line #115).
Figure 7: Utilizing the TagJavaScriptStr value
All of the if statements above from the requestInitialized function above are executed when the request hits the VMware service before the request hits its endpoint inside the virtual machine.
Figure 8: Java Class Flow
Indicators of Compromise and Threat Hunting
Security teams looking to leverage this information for threat hunting opportunities can look for the modification of ‘web.xml’ files on their VMware instances as well as new Java Class files being written unexpectedly. Threat hunts for obfuscated and abnormal information in the Cookie fields of web requests related to VMware Horizon and new ZIP file creation could also be an indication of exploitation attempts. Additionally, organizations should reference the VMware security advisories related to VMware Horizon.
To learn more about threat hunting and how our team can help accelerate your cybersecurity program, please connect with a security specialist here.
The newly combined Herjavec Group and Fishtech Group team is made up of best-in-class, global talent and some of the most highly respected professionals in cybersecurity. With decades of experience and lessons learned, we want to share our insights with you. From the Cyber Playbook is a blog series where our diverse, specialized thought leaders will discuss all things cybersecurity. Every month one of our experts will provide advice and insights based on their extensive experience in the infosec industry. Feel free to connect with us about topics and questions you would like to see covered.