Call4Cloud | MMP-C | Autopilot | Device Preparation

Close Encounters of the Microsoft Azure Attestation

Patch My Pc | install & update thousands of apps

This blog will be about my first and second encounters with Microsoft Azure Attestation(MAA) and how this new kind of attestation will be dropped down from Intune to your device. If you ask me, it certainly looks like it uses the new Microsoft Attestation Client Agent.

1. Introduction


Almost every day, Fiddler just runs in the background (hoping to spot some more funny MMP-C stuff). When Fiddler runs, I always make sure I am routing all the traffic through Fiddler using Netsh. If you can add some certificates to Fiddler (Intune, Azure, MMP-C), you can spot more excellent stuff.

Using Fiddler to decode Intune MDM or Graph traffic (call4cloud.nl)

Something else caught my eye as I was trying to burn down some theories.

Afbeelding met tekst, Lettertype, schermopname  Automatisch gegenereerde beschrijving

As shown above, suddenly, I had some failing requests in my Fiddler trace… Mmm, I wasn’t looking for that, but who cares? When taking a closer look, those URLs looked familiar. As shown below, these URLS correspond with the new Microsoft Azure Attestation (MAA) that was announced last month.

Afbeelding met tekst, schermopname, Lettertype  Automatisch gegenereerde beschrijving

Support tip: Update endpoints to support Microsoft Azure Attestation service for Windows 11 – Microsoft Community Hub

When looking up the URLS and reading the article, it tells us that not that “much” will change, only the health attestation endpoint (HAS Endpoint). We need to ensure our firewall isn’t blocking HTTPS (443) for these attest.azure.net URLS I mentioned earlier.

If you block these URLs, MAA will NOT work, and you will end up in a world of pain. Why? Let me tell you!

  • You configured compliance policies (Bitlocker etc)
  • You are blocking devices with conditional access if they aren’t compliant

If your device can’t send its attestation report/evidence to the MAA, whoopsie, you are pretty much done for, as your device can’t communicate if it’s compliant or not

So attestation at his finest! I love Attestation… TPM Attestation, Device Health Attestation… So why not add Microsoft Azure Attestation to that shortlist? So I decided to feed the MMP-C monkey in my brain a few nuts (or beers) to keep him quiet and have a closer look at what was actually happening, AKA failing.

2. Looking at what happens

When taking a closer look at what’s happening, we will notice some funny things the moment our device is syncing with Intune. When the device syncs with Intune, a lot of “garbage” (NodeCache) is sent back and forth to make things work.

If we take a closer look at that incoming CSP NodeCache stuff, we will notice (besides the plaintext admin password …) that the HealthAttestationCSP is being delivered to our device. This one will trigger the client’s attestation!

Afbeelding met tekst, Lettertype, nummer, schermopname  Automatisch gegenereerde beschrijving

After this “Trigger Health Attestation CSP” is delivered to our device, it will reach out to attest.azure.net to start the attestation. While reaching out to the attestation service, it produces one good and one bad request (read part 7 as it is now fixed), and it looks like it retries a second time with the same parameters. So, let’s start with the first good request.

It looks like Intune is now somehow sending out this TriggerAttestation CSP to our device to initialize the Attestation and, with it, the required parameters. So, let’s zoom in a bit.

Afbeelding met tekst, schermopname, Lettertype, nummer  Automatisch gegenereerde beschrijving

As shown above, a nice identifier called RPID, with the well-known Contoso domain. The name we always use for testing/demoing stuff, right? Besides the rpid, we also notice the endpoint we need to allow in our firewalls and some other stuff like the nonce and cv. Of course, we need to authenticate ourselves to the service, so we need our aadtoken.

When comparing this with the official docs, yeah… looks good!

Afbeelding met tekst, schermopname, Lettertype  Automatisch gegenereerde beschrijving

When also taking a closer look at the aadtoken, that one also seems pretty valid.

Afbeelding met tekst, Lettertype, schermopname, informatie  Automatisch gegenereerde beschrijving

This was the initial payload we received from Intune to trigger the actual attestation. Let’s take a look at the two posts to the service and start with the first request to determine what is sent over to the attestation service

3. The Working request

So, with the TriggerAttestation CSP in our pocket, the first request to the attestation service is being sent out. This request is triggered by the HealthAttestationClientAgent (origins from 2022, but got updated 01-08-2023)

When we look at the first request the HealthAttestationClientAgent sends to the attestation service, it holds a lot of base64 encoded stuff.

Afbeelding met tekst, Lettertype, nummer, informatie  Automatisch gegenereerde beschrijving

When we zoom into the “bearer token”, we notice that this one is, of course, the aadtoken we got earlier. Nothing fancy going on here! If we scroll down a bit, we will notice the actual “data” in the request that is sent out to intunemaape8.attest.azure.net

Again (as always, base64encoded), when decoding it, we will notice that it mentions the aikcert payload.

This one performs the first step in the attestation operation and will continue until it receives the “report” (Attestation Result Token). So, let’s take a look at the first response to the initial request. As shown below, the response payload

Afbeelding met tekst, Lettertype, lijn, schermopname  Automatisch gegenereerde beschrijving

Let’s find out what’s inside, shall we?

As shown above… for now, it doesn’t tell me much… but I pretty much assume it’s required, and it seems successful, so let’s move on to the failing one

4. The failing one

So with the TriggerAttestation CSP in our pocket and the first successful request for the AIK cert, it again sends out a request to the same service but this time, besides the required bearer token a lot of other information.

Afbeelding met tekst, Lettertype, schermopname, document  Automatisch gegenereerde beschrijving

Again a nice base64encoded request. If we decode it, we will notice that this base64encoded command holds another base64encoded “payload”

Afbeelding met tekst, Lettertype, schermopname, wit  Automatisch gegenereerde beschrijving

If we decode it again, we will notice the actual attestation request with the boot TCG logs and all of the other stuff the old-school DHA needed to fetch. Just before the request is sent, we will notice that the new and fancy HealthAttestationClientAgent.exe is trying to fetch this data.

If you don’t know what I am babbling about, please check this blogpost first (and take some aspirin)

Device Health Attestation Flow | DHA | TPM | PCR | AIK (call4cloud.nl)

And to finish off your headache…. Please read this one also, as it gives a deep dive into the previous deep dive

Health Attestation Certificate | Bitlocker | Secure Boot (call4cloud.nl)

If you read them!! Good!! Let’s switch back and take a look at the decoded payload

Afbeelding met tekst, Lettertype, schermopname, wit  Automatisch gegenereerde beschrijving

That’s a lot of data. Let take a closer look if we split them apart and take a closer look at them

Afbeelding met tekst, schermopname, Lettertype, lijn  Automatisch gegenereerde beschrijving

The Payload/Enclave from the screenshot above contains the: The AIKCert, AIKPub, BootClaim, Attestkey, ServiceContext, and the SRTM_Resume

When comparing this to the JWS attestation payload example from Microsoft, it does seem valid. I am only missing some parts. As in my request, I am only noticing the srtm_resume_log (TBS_TCGLOG_SRTM_RESUME AKA The log associated with PCRs 0-15 for the most recent resume from hibernation) and not the other stuff Microsoft is mentioning in their docs

Afbeelding met tekst, schermopname, Lettertype  Automatisch gegenereerde beschrijving

So, our request is sent over to the service. At this moment, the Azure Attestation service needs to evaluate it against a configured policy. If that process is successful, the service should send back the report/attestation token to the device.

Let’s take a look at how the service responds to the “good evidence” that was sent over to the service

The error mentions that the request is invalid or does not meet policy requirements. I guess it’s 50/50. Or the request is invalid (mmm… it doesn’t look like it) or doesn’t meet the policy requirements.

That’s odd… I was expecting to get back the attestation report (Attestation Token) which should be forwarded to the MDM service (Intune… or?) So where does it fail?

Please read part 7 of this blog, as that one shows you the request with a working response, and with it we have the required Attestation Report

5. Microsoft flows

To know where it breaks, I first started looking at the first flow Microsoft provided us with

Azure Attestation service

Mmmm… that actually doesn’t tell me anything new or where it breaks… after looping through Microsoft their docs, I stumbled upon another flow… a way way better one!

microsoft azure attestation flow

So “something” for “some reason” breaks at Microsoft when the evidence is handed over to the Attestation service. For now, let’s take a look at a small recap, and from there on you can ask yourself some questions (not going to share mine… for now)

Somehow, the TriggerAttestation will start the attestation process, and the new Healthattstationagent will communicate with the service (if it aint blocked by the firewall……) and will hand over the evidence… and from there on, it “dies” …..but why??

6. My flow

This blog was written after creating my own flow. While writing this blog, I stumbled upon the second flow from Microsoft, and it looks pretty much the same as I had in my head.

7. The Working Request

A couple of weeks after releasing this blog, I decided to try it again to find out if the attestation process was working.

So I opened Fiddler and started syncing my device with Intune, but somehow my device wasn’t receiving the TriggerAttestation CSP any longer. That’s weird? But who cares, right? We already know what the TriggerAttestation looks like! With this information, we can fire it off ourselves! The only thing I needed to do was fetch myself a new AADtoken.

$test1 = @'
    <SyncBody>
        <Exec>
            <CmdID>VERIFYHEALTHV2</CmdID>
            <Item>
                <Target>
                    <LocURI>
                        ./Vendor/MSFT/HealthAttestation/TriggerAttestation
                    </LocURI>
                </Target>
                <Data>
                   {"rpid":"https://www.endpoint.microsoft.com/attestation","endpoint":"https://intunemaape8.neu.attest.azure.net/attest/tpm?api-version=2022-08-01","nonce":"9F35A496DDC0B67798DF","aadToken":"AADTOKEN","cv":"beac6726-9c35-4fe9-85d7-7a0f1d0d4596"}
                </Data>
            </Item>
        </Exec>
        <Final/>
    </SyncBody>
'@

send-localmdmrequest -SyncML $test1

After firing off this PowerShell command, my device was indeed reaching out to the Health Attestation service but this time it looks like it is succeeding.

This time no invalid data but a nice new base64 encoded payload and in it the Attestation Report!

Just like we did with the other payloads, we can decode it again to get ourselves some more information about what’s inside.

After copy-pasting the information to a JSON formatter, the contents became more clear. Let’s start at the top. We will notice that it contains 3 Certificates.

When converting these nice base64 encoded values to some certificates, we will notice that those contain the Microsoft Azure Attestation certificates

But what else does the report (GetAttestReport) contain? This report contains the outcome of all the attestation measurements! When taking a closer look, we will notice that it indeed contains everything that was configured in the attestation policy (even when we didn’t configure that Attestation Policy because Microsoft did that for us)

This nice Attestation report could also be fetched when using the HealthAttestationCSP.

$test1 = @'
    <SyncBody>
        <Get>
            <CmdID>VERIFYHEALTHV2</CmdID>
            <Item>
                <Target>
                    <LocURI>
                        ./Vendor/MSFT/HealthAttestation/GetAttestReport
                    </LocURI>
                </Target>
            </Item>
        </Get>
        <Final/>
    </SyncBody>
'@

send-localmdmrequest -SyncML $test1

If you fire off that command, you will notice that the content is, of course, Bas64. You can decode it and decode it again to get the same details as we noticed in Fiddler

8. Remote Tasks

Niklas Tinner noticed that a new remote task had been added we could define in the Intune Roles. As shown below this RemoteTask is named: InitiateDeviceAttestation

The funny thing is, that it’s not only available in Graph… It’s also added to the Intune UI when you are adding a custom role!!!! “Initiate Mobile Device Management (MDM) attestation if device is capable for it”

That sounds exactly like what I am describing in this blog above!! How cool would it be if we could trigger device attestation with a remote task from Intune?

Damn… Even when it doesn’t fix the Bitlocker Reboot (which is obvious) it’s pretty pretty cool. I guess we need to keep an eye out for a GitHub Pull Request

memdocs/memdocs/intune/remote-actions/device-management.md at main · MicrosoftDocs/memdocs · GitHub

Until then… We need to wait a bit until it’s there Intune!

Conclusion

I am pretty amazed about the new Attestation Health agent and the corresponding DLLs. I am even more amazed that this new attestation is triggered after a device sync. Of course, we are still stuck about when the device creates the TCGlog (at boot), so the required reboot will still need to take place to get the device compliant, but I am assuming the new service is way faster and way more reliable!

Leave a Reply

Your email address will not be published. Required fields are marked *

  −  1  =  1

Proudly powered by WordPress | Theme: Wanderz Blog by Crimson Themes.