Skip to main content
VulnerabilityIntuneConditional Accessentra-idMAM

VULN-172966: Satisfying Entra ID App Protection Conditional Access With a Self-Attested MAM Enrolment

Rawson Wade16 min read
VULN-172966: Satisfying Entra ID App Protection Conditional Access With a Self-Attested MAM Enrolment

This is the technical in-the-weeds how MAM works companion to: Inside Microsoft Intune MAM: What Your Mobile App Protection Actually Protects.

TLDR

Microsoft Mobile App Protection policies are a policy enforcement layer for genuine application clients on mobile devices. By simply spoofing the API calls made to the Intune MAM service, an authenticated session can authorise itself past Conditional Access policies to access a protected service. This extends beyond just Microsoft products into all MAM protected applications in the App Protection ecosystem.

Summary

FieldDetail
Tracking IDVULN-172966 (Microsoft Security Response Centre)
ClassConditional Access policy bypass / insufficient client and device attestation
Affected controlEntra ID Conditional Access grant "Require app protection policy" (app-based CA)
VectorAuthenticated. Requires a refresh token (AiTM phishing, device-code phishing, or infostealer theft) that can register a device
Reported severityModerate (as classified by MSRC)
StatusReported 3 Feb 2026, closed as fixed by MSRC 25 Jun 2026
ResearcherRawson Wade, Modern 42

Affected environment

The behaviour shows up in a fairly ordinary BYOD setup, the sort a lot of enterprises run:

  • Entra ID Conditional Access with a grant control requiring an app protection policy for the Office 365 resources (Exchange Online, SharePoint Online, Teams).
  • Intune App Protection Policies (MAM without enrolment) scoped to those apps on personal Android and iOS devices.
  • Device registration for BYOD gated by MFA, which is the common default.

No admin rights are needed. No compromise of a genuine managed device is needed. The only real cost of entry is a valid refresh token for the target user, plus the willingness to read a bit of OAuth traffic.

Before you read on

I am not going to re-explain the enrolment "dance" from first principles here. The deep-dive walks through the legitimate Company Portal broker flow, the certificate pinning on the MAM registration endpoint, and where the microsoft_enrollment_id header comes from. Read that first if any of the following feels like it skips a step. This piece assumes you already know what a Primary Refresh Token (PRT) is and why device registration matters.

The vulnerability, stated plainly

Here is the crux, and I want to keep it tight because everything else is just detail hanging off it.

The "require app protection policy" grant control is satisfied when the token request presents a MAM microsoft_enrollment_id and declares the client is protapp capable. The problem is what stands behind that enrolment ID. The MAM service accepts an application instance registration built entirely from client-supplied device and app metadata, and the compliance verdict for that instance is reported back to the service by the same client. In other words, the thing the policy leans on to decide "this is a protected app on a managed-enough device" is, as far as I could tell, self-attested.

So the trust chain reads: Conditional Access trusts the enrolment ID, the enrolment ID trusts a compliance status, and the compliance status trusts whatever the client felt like sending. Nothing in that path made the caller prove it was a real instance of Teams or Outlook, or that the "device" was a physical handset rather than a Python script with a requests session.

Preconditions

  1. A refresh token for the target user, and with it the ability to register a device. In most tenants device registration needs an interactive sign-in with an MFA claim once, after which you hold a PRT and can derive refresh tokens that carry the device identity. There are a few realistic ways to reach that starting point, none of which require touching a managed device. More on that in a second.
  2. Knowledge of the first-party client IDs and resource identifiers involved. These are public.

That is it. Point 1 is the whole ballgame, and BYOD device registration is designed to be easy, because if it were painful nobody would enrol their personal phone.

Getting that first token is the easy part

I want to sit on this, because "attacker holds a refresh token" can read like hand-waving. It is not. Here are three routes that turn up in real intrusions, and none of them need you to lay a finger on a compliant or managed device.

Adversary-in-the-middle phishing. A reverse-proxy phishing kit (the Evilginx family and its many cousins) sits between the user and the genuine Microsoft login page. The victim types their password and completes MFA against the real page, and the kit walks off with the authenticated session and the refresh token. Registering a device from there is just another authenticated call. The user saw a normal login and a normal prompt, and nothing felt off.

Device code phishing. Rather than cloning a login page, the attacker kicks off a device-code flow and sends the victim a genuine Microsoft URL with a short code to enter. The victim authenticates on the real Microsoft page, which is exactly why this one works so well, and the resulting tokens land with the attacker. Those tokens can be good enough to register a device and start the enrolment described below. There is no dodgy-looking domain for anyone to spot.

Infostealer and spyware. The token might not need to be phished at all. Commodity infostealers and mobile spyware pull tokens, PRT material, and session cookies straight off an endpoint the user has already signed into. Here the token was minted on a genuine device by a genuine user, and the attacker simply lifts it. No login, no prompt, nothing to relay.

The common thread: the attacker needs one valid token, once. After that, the enrolment flow does not care how it was come by.

What about phishing-resistant auth?

Fair question, and it does help, but it is worth being honest about where it helps and where it does not.

Moving device registration onto phishing-resistant methods (FIDO2 keys, passkeys, certificate-based auth) takes a real bite out of the first two routes. If there is no shared secret and no relayable prompt, an AiTM proxy and a device-code lure have far less to grab. That is a genuine improvement and worth doing.

Where it runs out of road is token theft. If an infostealer lifts a refresh token or PRT off a device the user already signed into with a passkey, the strength of that original sign-in does not travel with the stolen token. The token already exists, so there is nothing left to phish. Closing that gap is what device-bound tokens and Token Protection are for, and coverage across clients and platforms is still patchy, so I would not lean on it as a solved problem just yet. Phishing resistance raises the floor. On its own, it does not put the data behind glass.

Walkthrough: every endpoint that gets called

I reproduced the flow with a small tool of our own that simulates a MAM client. It is roughly eight HTTP calls. No SDK, no Company Portal app, no rooted handset. The sequence below is the entire exploit path. I have deliberately left the request bodies out, both because they are not the interesting part and because there is no need to hand over a copy-paste kit.

And the same thing as a flat endpoint table, since that is usually what you actually want when you are trying to follow along:

#MethodEndpointWhat it does
1POSTlogin.microsoftonline.com/{tenant}/oauth2/v2.0/tokenBaseline. Ask for the target resource directly. Comes back AADSTS53009.
2POSTlogin.microsoftonline.com/{tenant}/oauth2/v2.0/tokenTrade the refresh token for one scoped to the MAM service resource.
3POSTmamservice.manage.microsoft.com/proxy/StatelessApplicationManagementService/ApplicationInstancesRegister an application instance. Returns an instance key.
4GET.../ApplicationInstances(guid'{key}')/ActionPull down the policy and payload identifier assigned to the instance.
5POST.../ApplicationInstances(guid'{key}')/UpdateStatusReport the instance's compliance state back to the service.
6POST.../ApplicationInstances(guid'{key}')/GetStatusRead the recorded compliance verdict back out.
7POSTlogin.microsoftonline.com/{tenant}/oauth2/v2.0/tokenAsk for the target resource again, this time presenting the enrolment ID and declaring protapp capability.
8GETResource API (Teams / Outlook / Graph mail)Use the issued access token to read corporate data.

Step 1: the block, so we know the control is live

First call is the honest one. Ask the token endpoint for the target resource with nothing special attached. If the CA policy is doing its job, you get knocked back with AADSTS53009 ("Application needs to enforce Intune protection policies"). This is the baseline that proves the control is actually switched on for this user and resource. If this call succeeds, there is no policy to bypass and you can stop reading.

Steps 2 to 6: enrol yourself and mark your own homework

Now the interesting bit. Call 2 swaps the scope to the MAM service resource and gets a token for it. Note that a refresh token minted from a device registration is happily accepted here, which is the hinge the whole thing swings on. The device identity does the heavy lifting; the app identity does not have to prove much.

Call 3 registers an application instance. The device fields (manufacturer, model, OS version, patch level, "device health") and the app fields (package name, version, SDK version) are all supplied by the caller. In my testing the service took them at face value and handed back an instance key. Call 4 fetches the policy assigned to that instance. Calls 5 and 6 are where it gets a bit cheeky: the client tells the service its own compliance state, then reads it straight back as "compliant." The verdict the platform later relies on is the verdict the client just posted to it.

Step 7: collect the token the policy said no to

Same token endpoint as step 1, same resource, but this time the request carries the microsoft_enrollment_id from the instance we just created and declares the client capable of app protection via the xms_cc / protapp capability claim. That combination flips the outcome. Conditional Access now considers the app-protection requirement met and issues the access token it refused in step 1.

Step 8: read the data

With a valid access token, the rest is just using the API. In the PoC I pointed it at Teams, but the same enrolment satisfied the grant for the other Office 365 resources sitting behind the same policy, so pivoting to a mailbox was a matter of asking for a mail-scoped token and calling the endpoint. Here is the part that tends to land with people: reading a target's email from tooling that never touched a real phone.

Why it works

Peel it back and the root cause is an attestation gap, not a bug in a single endpoint.

  • The app instance is self-described. Registration accepts device and app metadata from the caller. Nothing I saw required the caller to be a genuine, signed instance of the app, and nothing checked whether the "device" was physical or emulated.
  • Compliance is self-reported. The client posts its status and the client reads it back. The service appears to treat the compliance verdict as something the client tells it, rather than something the platform independently proves.
  • Conditional Access consumes the outcome, not the evidence. By the time the grant control looks at the request, all it sees is an enrolment ID and a capability claim. It trusts those. It does not, as far as I could observe, re-derive whether the enrolment was ever earned honestly.

Stack those together and the "require app protection policy" grant becomes a check that the caller claims to be app-protected, which is a weaker statement than most people assume they are buying.

Impact

Within the scope MSRC classified as Moderate, the practical effect is that an actor holding a user's refresh token can reach the corporate data that the app-protection policy was specifically meant to gate: mail, files, and chat. Two properties make it worth caring about:

  • Location and device independence. Once issued, the resulting tokens were not, in my testing, re-checked against device compliance or network location. An enrolment minted from anywhere works from anywhere.
  • Low skill floor. This is not nation-state kit. If you can drive an interception proxy and read OAuth, you are most of the way there. A disgruntled insider with moderate chops is squarely in scope.

I want to be careful not to oversell it. This is a post-authentication bypass. It does not defeat MFA on the initial sign-in, and Microsoft closed the case as fixed. But if MAM was your data-loss boundary for personal devices, the boundary was more of a suggestion than a wall.

The part that should give you pause: a side door around zero trust

Here is the strategic version of the problem, and it is bigger than one bypassed grant control.

Most shops that care about this have spent real money making the device a trusted signal: Intune enrolment, compliance policies, device-bound Conditional Access, attestation where they can get it. That is the whole idea of zero trust, leaning access decisions on strong, verified signals instead of "they knew a password." For managed devices, that machinery is genuinely solid.

MAM is the pragmatic concession for the phones you cannot manage. "We do not own the device, so we will manage the app instead." Reasonable on paper. The catch shows up when a resource is set to accept a compliant device or an app protection policy, which is a very common pattern for mail and files. You now have two doors into the same room. One is the hardened, attested, expensive one. The other is MAM. And if the MAM door can be walked through without a genuine device or app behind it, an attacker is not going to politely queue at the hardened one.

That is the uncomfortable bit. You can pour budget into the compliant-device path and an actor with a single stolen token can reach the same mailbox through the softer parallel control. The strongest gate on the street does not count for much if the fence beside it has a gap. Whether this actually bites you comes down to your Conditional Access design. If your sensitive resources demand a compliant device outright, rather than "compliant or app-protected", the MAM door does not reach them. If they accept either, it might. Worth checking which one you have actually built, rather than which one you think you built.

Detection and hunting

While you are confirming your tenant has picked up the fix, a few things are worth watching. None of these are silver bullets, and some will be noisy in a big BYOD estate, so tune before you alert.

  • Device registrations that do not look like humans. Registrations from unexpected geographies, or a register-then-delete pattern, or a spike of registrations against one user. If your staff are all in Australia, a registration out of somewhere else at 3am deserves a look.
  • MAM app registrations with thin or odd metadata. Managed app registrations can be listed via the Microsoft Graph managedAppRegistration endpoint. Watch for device names, models, or SDK versions that do not match your real fleet.
  • Resource access shortly after a fresh registration. A brand new device registration followed within minutes by MAM enrolment and then mailbox or SharePoint reads is a shape worth flagging.
  • Refresh token usage from new networks. Sign-in logs showing the same user's tokens surfacing from a second country in a short window.

Mitigations

The fix for VULN-172966 sits with Microsoft and MSRC closed it on 25 June 2026, so the first move is simply to confirm your tenant reflects the corrected behaviour. Beyond that, the compensating controls are the same ones we lay out in the deep-dive, and they are worth having regardless of any single vulnerability:

  • For sensitive resources, require a compliant device outright rather than "compliant or app protection". If MAM is a parallel path to the same data, it is only as strong as its weakest branch.
  • Require MDM or compliant devices, not just MAM, for your sensitive data tiers and sensitivity labels.
  • Constrain device registration by location, time, or access packages where your architecture allows it.
  • Move device registration onto phishing-resistant MFA to raise the cost of the phishing routes, while remembering it does little against a token lifted from an already-authenticated device.
  • Turn on Token Protection to blunt refresh token theft from legitimate devices, and treat it as partial cover while client and platform support is still filling in.
  • Monitor device registrations properly. Alert on the odd ones rather than assuming they are all benign.

Disclosure timeline

  • 3 Feb 2026: Reported to the Microsoft Security Response Centre.
  • 11 Mar 2026: Behaviour confirmed by MSRC and classified as Moderate.
  • 25 Jun 2026: Closed as fixed by MSRC.

A closing thought

I will leave you with the same slightly uncomfortable idea I keep coming back to. MAM is genuinely useful at what it was built for, which is enforcing policy inside cooperative apps. The trouble starts when it gets sold, or bought, as a security boundary that keeps determined actors out. On the evidence of this one, it might be fairer to think of MAM as a policy engine for apps that agree to play along, and it may just be a touch over-marketed as a control. Match the control to the risk, and do not let a tick-box in a Conditional Access policy convince you the data is behind a wall when it might only be behind a polite request.

If you want a hand pressure-testing your own Entra ID or Intune posture, book in a session with one of our engineers.

Rawson Wade

Written by

Rawson Wade

Labs Lead, Modern 42

Rory leads Modern 42's Labs team with deep expertise in Microsoft Entra ID and Azure identity platforms. He has delivered countless IAM and PAM implementations for Australian government and largest enterprise.

© Posts are provided 'as is' under the AGPL 3.0 license unless otherwise stated

Topics

  • VULN-172966
  • Intune MAM bypass
  • Conditional Access bypass
  • app protection policy bypass
  • microsoft_enrollment_id
  • AADSTS53009
  • MSRC
  • protapp

We use cookies

We use cookies and similar technologies to help personalise content, measure the performance of our site, and provide a better experience. By clicking Accept, you consent to the use of all cookies.
Learn more.