Skip to main content

Introduction

Device and patch management is a significant security endeavour to tackle in any organisation. Tools such as Microsoft Endpoint Configuration Manager (ConfigMgr) allow organisations to centrally manage their devices and the patches of these managed devices. While central management means it is easier to perform, it also means that any security issue in the configuration of the software will have far-reaching implications.

Over the past couple of years, I have been investigating and adding to my understanding of how ConfigMgr’s OSD (Operating System Deployment) mechanisms work and what can be extracted from them as an attacker. When it comes to ConfigMgr, much of the research that has been published in the past month has focused on Network Access Account credentials and obtaining these from various attack perspectives (see [1],[2],[13] and older references mentioning the possibility [3]). This post adds to this picture by detailing a mechanism of recovering additional credentials from ConfigMgr by discovering and decrypting credentials configured in Task Sequences.

Given my upcoming DEF CON talk on this topic, I will be primarily discussing my observations from the perspective of a new OSD deployment, as this is where my own research focus has been placed; however, I will attempt to highlight parallels with recently published work where appropriate. Special mention should be made of all the references I have included in this post and the recent uptick in published work focusing on ConfigMgr. It is awesome to see the community dig into the details of such a ubiquitous piece of software that so many people and enterprises rely on!

What is OSD?

Operating System Deployment in ConfigMgr involves all the supported methods that it provides to upgrade or install a new operating system on a host [4]. The main deployment methods supported are:

  • Preboot Execution Environment (PXE)-initiated deployments
  • Bootable, Stand-alone and Prestaged media deployments – in essence, these are a set of files of various formats that can be used to initiate and either partially or fully complete the OS deployment process. These files are usually packaged and distributed via ISO, bootable USB or WIM file
  • Leveraging an existing ConfigMgr client running on a machine

In my experience, one of the most common aims of using OSD in enterprise environments is fully deploying a domain-joined machine on a new laptop, workstation or server. In this kind of scenario, it is likely that a media or a PXE-initiated deployment will be used, as there is no existing OS installed on the machine, or the aim is to wipe and rebuild the machine.

At a high level, all of these OSD methods will boot into a Windows Preinstallation Environment (WinPE) – this is effectively a stripped-down version of Windows running off of a RAM disk – and will run a packaged ConfigMgr client executable that will communicate over HTTP or HTTPS to ConfigMgr Management Points (MPs). MPs serve as the main hosts that provide “policy and service location information to clients”. [5] The specific details of the attacks that I’ve identified against these OSD methods will be discussed in my upcoming DEF CON talk.

How does a ConfigMgr client communicate with Management Points?

In terms of client communications, the key thing to know from a security perspective is that a ConfigMgr client (whether deployed in WinPE or on a domain machine) initially uses a client certificate to authenticate itself to MPs.  The mechanism used to generate or obtain this certificate varies based on how the client is deployed, but it must use this to authenticate itself to the server when requesting policy settings. As an example, [1] discusses how this certificate is registered by a client running on a domain machine and under which conditions a new client would be approved by ConfigMgr.

It is worth making some general notes on how these clients work:

  • Once a ConfigMgr client is running on a host, it communicates with the MP to determine what policies to apply and tasks to do. It uses HTTP or HTTPS to communicate with the server depending on the server configuration. HTTPS, however, requires the necessary certificates to be issued from a trusted CA. The client is also able to use mutual TLS for the communications, if it is configured to do so. The specific configuration options that control this are listed under Communication Security in Site Configuration in the ConfigMgr Console (see [6]):
    • HTTPS only – Requires clients to use HTTPS when talking to MPs
    • Use client PKI certificate (client authentication capability) when available – Requires client to use Mutual TLS when it is available
  • The cryptography used to protect sensitive data sent over the network, as well as that used to authenticate clients, is based on CryptoAPI [7][8]. I discovered this by debugging the client (TSMBootstrap.exe) in a WinPE environment using x64dbg, as seen in Figure 1. Since WinPE is simply a stripped-down version of Windows, it can run Windows executables that it has the necessary libraries for.
Figure 1: Using x64dbg in WinPE to view a call to CryptDecryptMessage to decrypt a Task Sequence
  • As I progress with the explanation, I will be referring to the functions from CryptoAPI that are used to perform signing and decryption of data by clients. Much of the lower-level crypto backing these functions is discussed in [1] from the perspective of a client deployed to a standard domain-joined Windows workstation. [8] also provides a high-level description of all the cryptography used by the various features and components in ConfigMgr
Authenticating Policy Requests

ConfigMgr clients are authenticated by sending specific HTTP headers and POST data to MP servers that is signed using the client’s certificate. A description of the applicable data that is signed follows:

Field Signed Field Description
CCMClientID CCMClientIDSignature This is the GUID of the ConfigMgr client. For OSD clients deploying a new OS, this is obtained from the ConfigMgr server before running the ConfigMgr client.
CCMClientTimestamp CCMClientTimestampSignature This is the time as generated by the client in ISO 8601 format
ClientToken ClientTokenSignature This is built by appending CCMClientTimestamp to CCMClientID as follows: “ClientToken:’ = CCMClientID + ‘;’ + CCMClientTimestamp”

The signing expected by ConfigMgr has changed over the years, but for modern versions, SHA1 and SHA256 signing is accepted for every field. Signing is performed using the CryptSignHash function of CryptoAPI. SHA256 signing is specifically required if Require SHA256 is set in the Signing and Encryption site settings in the administrative console (shown in Figure 2), and this is set by default for installations of recent versions of ConfigMgr (I’ve confirmed this on at least v2203).

Figure 2: Site signing and encryption settings in the ConfigMgr Console

Both the standard Windows client, as well as clients running during OSD, appear to make use of the same HTTP endpoint (/ccm_system/request) and authentication scheme when retrieving the URLs of the policies to be applied by the client. ClientToken/ClientTokenSignature are used to authenticate this request, while CCMClientID/CCMClientIDSignature and CCMClientTimestamp/CCMClientTimestampSignature are used to authenticate the subsequent downloads of the policies by clients.

Step-by-Step description of ConfigMgr HTTP Traffic used for policy download

Regardless of the mechanism by which a certificate is obtained, once a ConfigMgr client possesses a valid certificate, it goes through the following process to determine what policies it needs to apply:

  1. The client makes a request to the /ccm_system/request endpoint on the MP with a multipart-form encoded Msg and RequestAssignments XML request. A request of this type issued by an OSD client is shown in Figure 3.
Figure 3: HTTP request to MP with RequestAssignments XML request
  1. The client uses its certificate to authenticate this request by supplying and signing a ClientToken value in the Msg portion of the request (the first part of the multi-part form). As described earlier, the signature for this is generated using CryptSignHash. The server will validate this ClientToken and signature, if it is sent by the client or if signing is required by the site. The Require Signing setting is configured in the site’s Signing and Encryption settings (refer to Figure 2 to see this setting). While ConfigMgr requires signing by default, I have seen it disabled before and this allows the client authentication values contained under the Hooks2 XML tag to be deleted entirely while permitting the request to succeed, as shown in Figure 4.
Figure 4: Removal of client authentication for RequestAssignments when signing is not required
  1. Comparing the Msg and RequestAssignments XML messages in Figure 3 – as generated by a client running in WinPE as part of OSD – to the Msg and RequestAssignments messages discussed in [1] shows that the corresponding requests look slightly different. This implies that despite being deployed in an entirely different way, an OSD client and a client running on a domain-joined computer make notably similar requests to MPs.
    • There are key differences, however, that appear to make the requests not fully interchangeable, in my limited testing up to this point. The specifics around which XML fields in both the Msg and RequestAssignments messages are required for which deployment scenarios and exactly how MPs determine which assignments to allocate to a client is an area for future work…
  1. The response to RequestAssignments is a ReplyAssignments XML document that is zlib compressed. This contains the locations of all the policies that are available or should be applied by the agent. By parsing the ReplyAssignments XML message, it is possible to determine the URLs to download policy files. The format of ReplyAssignment is shown in Figure 5.
Figure 5: ReplyAssignments XML Message structure
  1. The agent then builds a request to the URLs specified to download policies. CCMClientID and ClientTimestamp and the corresponding CryptSignHash signed values (CCMClientIDSignature and ClientTimestampSignature) must be supplied as HTTP headers to allow for successful policy retrieval; regardless of site signing requirements. These can either be a SHA1 or SHA256 signed hash, depending on site configuration for signing discussed earlier.
  1. Once policies have been retrieved, it can be observed that a number of these downloaded policies are encrypted. Encrypted policies can be decrypted by providing CryptDecryptMessage from the Wincrypt API with the client’s certificate. Over the course of my research, I downloaded all the policies available to OSD clients on various client estates and discovered that there are three main categories of encrypted policies that I consistently saw. These policies can be reliably identified by the PolicyCategory attribute of the Policy tags in the ReplyAssignments XML message. Extracts of the relevant PolicyCategory tags in ReplyAssignments XML message for the policies that were observed to be encrypted are shown in Figures 6, 7 and 8. The relevant PolicyCategory attributes were:
    • NAAConfig – Network Access Account Configuration
Figure 6: NAAConfig policy tag
    • TaskSequence – Task Sequence policies
Figure 7: TaskSequence policy tag
    • CollectionSettings – Collection Variables
Figure 8: CollectionSettings policy tag
  1. Retrieving and decrypting these policies reveals the corresponding policy XML documents. These are shown in Figures 9, 10 and 11. As can be seen, in these specific policy files, certain tags are marked with an attribute secret=“1”. The contents of these tags are encrypted using 3DES with a keystream in the XML field. Since the key isn’t secret, the ConfigMgr functions that deal with this refer to it as obfuscation. The name attribute of XML tags that I have observed to make use of these obfuscated strings are:
    • For the NAAConfig: NAAUsername and NAAPassword
    • For Task Sequences: TS_Sequence
    • For Collection Variables: Name and Value
Figure 9: Decrypted NAAConfig XML document structure
Figure 10: Decrypted TaskSequence XML document structure
Figure 11: Decrypted CollectionSettings XML document structure

An example of retrieving the credentials associated with each of these policy documents is shown in Figure 12.

Figure 12: A screenshot of PXEThief, my Python tooling that can retrieve credentials from a Task Sequence that is published to PXE (and other OSD) clients

Task Sequences

Since OSD involves updating or installing a new OS; the specific tasks and the order of them are important in making sure that a machine comes out on the other end functioning correctly and with the right image and software deployed. As a simple example, on a new laptop, you can’t install an OS before you have formatted the disk you want to install to. The tasks that need to be performed to do this successfully are defined in ConfigMgr Task Sequences. These task sequences are defined in the ConfigMgr console, as shown in Figure 13.

Figure 13: Task Sequences in the ConfigMgr console

When editing Task Sequences, it is possible to see and edit the specific tasks and the order of tasks to be performed, as shown in Figure 14.

Figure 14: Task Sequence editor screen

Task Sequences are typically used to deploy or upgrade Operating Systems but can also be used to automate tasks on hosts across an environment, wherever a ConfigMgr client is installed. Broadly speaking, the tasks that can be automated would fall into several main categories [9]:

  • Application installation
  • Software updates installation
  • Setting configuration
  • Running command-line or PowerShell commands

As part of OSD or task automation, additional credentials might be required. One example of this was shown in Figure 14, where credentials were provided in order to join a machine to a domain. The main types of credentials that can be embedded in Task Sequences are [10]:

  • “Task sequence domain join account”
  • “Task sequence network folder connection account”
  • “Task sequence run as account”
  • Local administrator credentials for the machine [11]
  • Credentials for storing captured OS images on a network share [12]

The account that I have most often seen in practice is the “Task sequence domain join account”, as the main objective of many production Task Sequences is to build new machines in an enterprise environment. Figure 12 shows recovery of a variety of these credentials using the tooling that I am due to release at DEF CON 30 in August.

Conclusion

The bigger picture of the disclosures in this post, and many of the recent ConfigMgr research that has been published, is that the credentials that are distributed to ConfigMgr clients are being deployed into environments where they can be compromised. This means that care should be taken when creating and assigning permissions to these accounts.

When talking about something as ubiquitous as the Network Access Account, the attack surface is effectively every single system and host with a ConfigMgr client running or installed and, as indicated in [1], seems to at least extend as far as any authenticated domain user with the ability to join a machine to the domain. However, with the right level of access to a target network, it would be possible for other client credentials configured in ConfigMgr to be compromised, as described in this post. Thankfully, the attack surface for other accounts is reduced when compared to the NAA, but from what I have seen in practice, it is common for all of the credentials configured for ConfigMgr to be assigned elevated privileges on the domain. In general, leakage of any of these credentials would mean the compromise of privileged domain credentials that could be used for further attacks against a domain.

The main takeaway from this research is that if you are entering a password into ConfigMgr, least privilege is critical. ConfigMgr is not a black-box that can magically protect the credentials that it distributes to clients. With the current level of understanding of how these credentials are stored and distributed, the configuration advice Microsoft is giving in [10] is more critical than ever. This is necessary to ensure that the accounts configured and distributed to domain-joined hosts and OSD scenarios are not putting AD environments at an elevated level of risk.

On a closing note, the credentials disclosed in Task Sequences naturally form part of the more complete attack paths that can be executed against ConfigMgr’s OSD methods; the full details around how these methods work and the attacks that I identified form part of my upcoming DEF CON talk on the 12th of August 2022, so look out for them then 😉

P.S. It should be noted that the ConfigMgr policies I talked about earlier do not have to be downloaded over TLS – sensitive policies are always encrypted, but the use of TLS is strictly dependant on the Communication Security site settings in ConfigMgr. Furthermore, making use of Enhanced HTTP plays no role in how policy download happens; rather, Enhanced HTTP only kicks in after policies have been retrieved, when actual packages (applications, OS images etc.) are being downloaded by a ConfigMgr client.

References