By Steven Seeley
Note: This article is one in a technical series by Trenchant of L3Harris Technologies.
Intro
In 2022, I conducted research against VMWare Workspace ONE Access and was able to find a remote code execution vulnerability triggerable by an authenticated administrator. Although authentication is required, past authentication bypass vulnerabilities have been published. As an aside, if you’re interested in this sort of work, here at Trenchant we perform vulnerability research against a wide variety of interesting and challenging targets!
VMWare’s vendor advisory can be found here.
Motivation
Full chain author | AB | RCE |
---|---|---|
mr_me | CVE-2022-22955 | CVE-2022-22960 |
Kai Zhao & Steven Yu | CVE-2022-22973 | ? |
Petrus Viet | CVE-2022-31659 | CVE-2022-31659 |
After I built the Hekate 0-click exploit, which chains an authentication bypass with other vulnerabilities, I saw that Kai Zhao of ToTU Security Team and Steven Yu reported CVE-2022-22973, another authentication bypass without chaining any remote code execution.
Later on, Petrus Viet bypassed the patch for CVE-2022-22973 (patched as CVE-2022-31659) and chained it with another remote code execution vulnerability he found (CVE-2022-31659).
A new RCE vulnerability could be combined with Kai Zhao and Steven Yu’s authentication bypass to achieve unauthenticated remote code execution. VMWare try very hard not to allow any post-authentication RCE vulnerabilities, especially because these flaws have been exploited in the wild.
Vulnerability Analysis
I was up late one night and reading about Java bean validation related vulnerabilities, and I realized this is an area I hadn’t investigated initially when auditing this target. Since an RCE would allow completing a full chain, I decided it was time to dive in one last time.
In Alvaro’s excellent post, he mentions that the vulnerable sink to be looking for is javax.validation.ConstraintValidatorContext.buildConstraintViolationWithTemplate with a partially controlled error message, so I went about my journey to find such a sink which lead me to the com.vmware.horizon.catalog.validation.TypeInfoValidator class:
At [1] the validator loops through the errorMessages property and gets the first string value from the HashSet and proceeds to call buildConstraintViolationWithTemplate. I continued to look for anything that calls addErrorMessage at [2] since this method populates the errorMessages property.
I failed at finding anything of use and was about to give up when I found this interesting method inside of the TypeInfoValidator class:
Naturally, I wanted to know how the errorMessages list is derived in order to influence the return value of getErrorMessageKey at [3]. I dived into the
com.vmware.horizon.catalog.utils.saml.transformation.ClaimTransformationHelper class to inspect the validateClaimTransformations method:
At [4] the code loops through the supplied claimTransformations and calls getRules. At [5] claimRules is cast to an ArrayList of ClaimRule instances and stored in rules. Then at [6] the code calls validateClaimRuleCondition with the attacker-supplied rules.
The getCondition method is called on the attacker-supplied ClaimRule instance that was passed directly to the scriptEngine.eval sink at [7]. Because Java bean validation occurs on user-supplied data, it was likely that we could reach this injection sink with influenceable data.
Reaching validateClaimRuleCondition
Looking for calls to validateClaimTransformations I found a few results:
The second result is the com.vmware.horizon.catalog.validation.SamlTypeInfoValidator class that exposes the validate method.
This is called by the two child bean validation classes Saml11TypeInfoValidator and Saml20TypeInfoValidator in their isValid implementations.
At this point I started to look for implementations with any of the annotations @ValidSaml11TypeInfo, @ValidSaml20TypeInfo or @ValidWSFed12TypeInfo.
The classes com.vmware.horizon.api.v2.catalog.Saml11AuthInfo, com.vmware.horizon.api.v2.catalog.Saml20AuthInfo and com.vmware.horizon.api.v2.catalog.wsfed.WSFed12ResourceInfo all implement the custom bean validator as an annotation.
Looking for validation
At this point, we have three classes that can reach the vulnerable sink and these classes need to be validated in order to reach that sink. After some searching, I found a @PostConstruct at [8] inside of the
com.vmware.horizon.catalog.impl.CatalogServiceImpl class that is called after the initialization of the catalogService bean service:
After more searching, I found the com.vmware.horizon.catalog.rest.resource.AbstractCatalogResource abstract class implements this service:
At [9] we see that the class auto wires the CatalogService. Naturally, I then looked for child classes of AbstractCatalogResource and I found two interesting examples:
These are interesting because they use the following three types from the com.vmware.horizon.catalog.rest.media package:
- Saml11CatalogItem
- Saml20CatalogItem
- WSFed12CatalogItem
These types expose a JSON property that maps back to their associated AuthInfo types. For example, let’s inspect the Saml20CatalogItem class:
Exposure
Looking at the com.vmware.horizon.catalog.rest.resource.CatalogItemsResource class we can find several methods that expose the vulnerable sink:
At [11] the user needs to be at the admin level to reach this endpoint, however, several authentication bypasses existed in this application in the past and these can be chained with this vulnerability.
Also, note that not all methods to reach the vulnerable code are listed here. I have provided two as proof of concept.
Proof of Concept
This PoC requires the target’s hostname and admin credentials. Chaining with CVE-2022-22973 is an exercise for the reader 🙂
Automation
Manual
Stack Trace