Blog: Vulnerability Advisory

MS Enterprise app management service RCE. CVE-2022-35841

Ceri Coburn 13 Oct 2022

TL;DR

A remote command execution and local privilege escalation vulnerability has been fixed by Microsoft as part of September’s patch Tuesday.

The vulnerability, filed under CVE-2022-35841, affects the Enterprise App Management Service which handles the installation of enterprise applications deployed via MDM.

An unprivileged user can exploit the vulnerability both locally and, in some cases, remotely and gain SYSTEM level access on vulnerable hosts.

Finding a target

Back in May I was on the lookout for new coercion techniques we could use for our Red Team operations. Attacks like the printer bug discovered by Lee Christensen (@tifkin_), and PetitPotam discovered by Giles Lionel (@topotam77), are still leveraged today and I was interested in obtaining other potentials to add to the list.

Many of the techniques to date rely on various MS-RPC specifications, but I was interested in looking at DCOM based interfaces instead. DCOM is similar to RPC, and in fact is built on top of it. Many lateral movement techniques also utilise DCOM, for example the MMC20.Application COM object and it’s ExecuteShellCommand method. Often blog posts mention empty launch and access permissions as the basis for enumeration of other potential interesting COM objects. Here is an example of the launch and activation permissions for MMC20.Application.

When permissions are missing on a specific application, access and launch permissions revert to the defaults. The defaults allow Administrators both local and remote activation, therefore unprivileged users are out of luck. So, this got me thinking, are there any applications that do specify launch and activation permissions that permit anyone to interact with the interface locally or remotely that are privileged services? I wrote a quick C# app that enumerated all registered AppId’s in the registry and ignored any that were not marked as LocalService. Applications hosted as services was important at the time as I wasn’t interested in coercion of my own credentials, which would be the case if the COM object was activated as the authenticated user. After running the tool, I ended up with this list of applications.

AppId: {0868DC9B-D9A2-4f64-9362-133CEA201299}, Name: sppui
AppId: {1538524A-8AC3-4C33-BF0C-C2F9CE51DD50}, Name: SharedRealitySvc
AppId: {2A947841-0594-48CF-9C53-A08C95C22B55}, Name: XblAuthManager
AppId: {2ED83BAA-B2FD-43B1-99BF-E6149C622692}, Name: WaaSMedicSvc
AppId: {42C21DF5-FB58-4102-90E9-96A213DC7CE8}, Name: EntAppSvc
AppId: {478B41E6-3257-4519-BDA8-E971F9843849}, Name: Radio Management Service
AppId: {4839DDB7-58C2-48F5-8283-E1D1807D0D7D}, Name: ShellServiceHost
AppId: {5E176815-9A63-4A69-810F-62E90D36612A}, Name: cdpsvc
AppId: {C5D3C0E1-DC41-4F83-8BA8-CC0D46BCCDE3}, Name: Xbox Live Game Saves
AppId: {C63261E4-6052-41FF-B919-496FECF4C4E5}, Name: EntAppSvc
AppId: {CCFDD24D-CEAB-458B-A4F1-F884973395DF}, Name: sppui
AppId: {FFE1E5FE-F1F0-48C8-953E-72BA272F2744}, Name: EntAppSvc

The EntAppSvc service piqued my interest only because it seemed to have multiple applications registered by the same service. A quick confirmation in OleView.NET showed that the Everyone SID had launch and activation permissions.

Digging Deeper

COM objects can expose multiple interfaces, each with their own methods that can be executed by the caller. Similar to a REST endpoint for example. With a target application now worth investigating, next it was time to see what interfaces the application exposed.

Many of the interfaces exposed were typical and implemented by many different COM objects, so the main functionality appeared to be implemented via the IEnterpriseModernAppManager interface. Using OleView.NET once again, we can decode the interface and determine what methods are exposed.

The interface exposed 5 methods, each one accepting 2 or 3 strings as arguments. The next goal was to see if we could figure out names of these functions as this would be an indication of behaviour.

Firing up x64dbg and attaching to the svchost.exe belonging to the Enterprise App Management Service helped with this. Since the generic service host process was used for hosting, the service itself seemed to be implemented inside EnterpriseAppMgmtSvc.dll. Belonging to Microsoft, we should hopefully have the benefit of public symbols that we can also search for using the debugger. A quick search for EnterpriseModernAppManager (the name of the interface) resulted in the following symbols.

The class EnterpriseModernAppManger looks to be exposing 5 functions exactly matching the prototypes found via OleView.NET. The BSTR type in the definition is the equivalent to short* parameters in the debugger. BSTR’s are typically UTF16 character strings, or unsigned shorts which are 16bit per character.

Based on the names of the exposed methods, my goals had now changed from coercion to exploitation. Since this DCOM interface could be activated both locally and remotely by anyone, could we install something via calling these functions?

First up was the InstallApplication method. At this stage the parameters were unknown, so invocation of the method was attempted with bogus string values. Immediately I was greeted with an access denied error. Whilst the DCOM activation permissions seem to allow Everyone, internally within the method additional validation was taking place. Losing hope, I decided to try the ProvisionApplication function instead, again using bogus parameter values. This time I was greeted with an error indicating the formatting of arguments was incorrect. Hmm, does this mean no security checks were being performed?

Using Ghidra, I had a quick look at the pseudo C code for the ProvisionApplication function which led to a function called ParseHostedInstallParameterString.

Immediately I could see that it was expecting an XML string as one of the parameters.

Further on down the same function, I could see references to strings such as PackageUri which looked promising. Turning to Google to look for clues I ended up finding this page.

https://docs.microsoft.com/en-us/windows/client-management/mdm/enterprise-app-management#provision-apps-for-all-users-of-a-device

Provision for the win

It seems the Enterprise App Manager Service deals with MDM where providers such as InTune can provision and install Windows Store applications. Ghidra only seemed to include string references to attributes belonging to the Application XML element, therefore the conclusion was that one of the parameters was expected to be the Application XML element documented on MSDN. Through a process of trial and error, the second argument of the ProvisionApplication method seemed to be the XML string. Resulting in a prototype like this.

uint ProvisionApplication(string unknown1, string xml, string unknown2);

Windows Store apps require signed packages to install unless developer mode is enabled.I first attempted to install the official Netflix appx package. After invoking the ProvisionApplication function pointing to the Netflix installer, the app ended up being installed for all users shortly after initial logon. Provisioning seems to mark packages for installation automatically as soon as a user logs on. So far so good, but Windows Store applications run inside a sandbox.

Microsoft also introduced the MSIX application installer format, similar to appx in structure but these types of installers have better support for Win 32 style applications including the installation of Windows services. The manifest for the MSIX requires a few capabilities set to indicate that we want to leverage services and run with full trust. Whilst these types of applications are unlikely to be approved for the Windows Store, enterprises can via MDM.

I went out and purchased a personal code signing certificate to sign the MSIX bundle, but equally an attacker with no morals could use any code signing certificate, including internally trusted CAs through AD CS or leaked certificates that could be potentially lurking on the dark web. Once the MSIX was built and signed, opening in explorer shows the elevated nature of the package.

Here I created a sample msix application called SmackX. The application simply installs a privileged service that executes a PowerShell script on startup:

Local privilege escalation

Up until now, all actions against the Enterprise App Manage DCOM interface were performed against the local machine. Invoking the ProvisionApplication method with our crafted MSIX package resulted in the SmackX application along with its service being installed and started.

Remote execution

As mentioned at the start, DCOM objects can be activated both locally and remotely. In addition to the COM default permissions, which in our case has been overridden by the Enterprise App Manager application specifically to allow everyone remote activation, COM security has the concept of limits.

As the name suggests, the limits are an extra level of protection to prevent overly zealous applications configuring weak permissions for their own COM objects. So, whilst exploitation can also be performed remotely, the account you are using either needs to be a member of the Distributed COM Users group or the Performance Log Users group for remote launch and activation to succeed.

Proof of Concept code

I have published a POC project on GitHub called ProvisionAppx that leverages the vulnerable DCOM interface and will allow any authenticated user to install an msix / appx installer.

Disclosure

Microsoft Security Response Center (MSRC) requested that no technical details or POC should be published until 30 days after the release of the fix.

  1. 29th May 2022 – Initial disclosure to with detailed description and C# code to provision a package
  2. 17th June 2022 – Contacted MSRC as case was put on hold with more information required.
  3. 22nd June 2022 – MSRC request sample MSIX package, code signing cert purchased and MSIX app provided
  4. 30th June 2022 – MSRC confirmed issue and started developing a fix
  5. 12th September 2022 – Fix released as part of September Patch Tuesday
  6. 13th October 2022 – Blog released 30 days after CVE publication