Table of Contents
Initial access remains a key concern for most organizations today. While Entra Conditional Access policies (CAPs) are often seen as a way to mitigate risks, they may be perceived as questioning employees' trustworthiness. But is this perception justified? Does having multi-factor authentication mechanism with CAPs enforced enough to tackle threat actors? How to leverage malicious browser extension to obtain access tokens and circumvent Conditional Access Policies by targeting MS Graph? What mitigations can we apply and, most importantly, how can we detect CAPs bypass?
At Black Hat EU 2024, TEMP43487580 delivered a talk on this topic, shedding light on a specific attack path. Dirk-Jan, who had previously worked on the same issue, disclosed the relevant client ID in a tweet. In his tweet, he pointed to the 'Company Intune Portal' app, and, as Dirk put it, 'cat is out of the bag.' The client ID in question is: 9ba1a5c7-f17a-4de9-a1f1-6178c8d51223
.
On December 20, 2024, an article by JUMPSEC labs demonstrated the reproduction of this technique with introduction to their tool “TokenSmith” that automates this procedure. Mitiga decided to test the capabilities and, within minutes, successfully bypassed the policies, gaining access to the scoped resource – specifically, MS Graph - from a non-compliant, unmanaged, and untrusted device. This technique involves phishing a user's credentials, and the level of access to the Graph API depends on the privileges of the compromised user.
With the rise of malicious browser extensions, we combined this technique with a browser extension which seamlessly granted us a valid access_token and gave us access to MS Graph API.
To recreate the bypass, we would need the ability to complete the authentication flow, which would primarily be achieved through successful phishing or MiTM (which we will discuss later) and includes one of the following pre-requisites:
Open a browser and enter the following URL:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=9ba1a5c7-f17a-4de9-a1f1-6178c8d51223&scope=openid+offline_access+https%3A%2F%2Fgraph.microsoft.com%2F.default&response_type=code&redirect_uri=ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-2666988183-1750391847-2906264630-3525785777-2857982319-3063633125-1907478113
Breakdown of the authorization request
https://login.microsoftonline.com/common/oauth2/v2.0/authorize
- Base URL for MS login services, referring to all Microsoft accounts and specifying an OAuth 2.0 authorization request version 2.0.
client_id=9ba1a5c7-f17a-4de9-a1f1-6178c8d51223
- Our unique identifier for the application we target, Microsoft Intune Company Portal
scope=openid+offline_access+https%3A%2F%2Fgraph.microsoft.com%2F.default
- Scoping the authorization to OpenID Connect authentication, getting a refresh token to maintain access without logging in again and requesting Microsoft Graph API permissions.
response_type=code
- Specifying we request authorization code which will later be exchanged for access token.
Redirect_uri=ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-2666988183-1750391847-2906264630-3525785777-2857982319-3063633125-1907478113
- This will be the redirect URI after authentication is complete, typically used to send authorization code back to the app.
Once MFA is completed, the login screen gets stuck in a loop with the loading dots. This happens because the browser is attempting to redirect to the ms-appx-web://
URL, but the app isn't correctly handling the redirect or the authorization code, causing the process to stall.

By utilizing developer tools or any proxy tool you may be using (e.g., BurpSuite), we can observe the console error:
‘Failed to launch https://ms-appx-web://microsoft.aad.brokerplugin/S1-15-2-2666988183-17503...1907478113?code=1.AV8AXXX
’...


Success! We got our code. This can now be used to grant us a valid JWT access token.
Redeeming access token from OAuth2:
Now, we would need to craft a POST request towards OAuth2 API endpoint of Microsoft login host. Our path is ‘/token’ and the request body should look like this:
‘client_id=9ba1a5c7-f17a-4de9-a1f1-6178c8d51223&redirect_uri=ms-appx-web://Microsoft.AAD.BrokerPlugin/S-1-15-2-2666988183-1750391847-2906264630-3525785777-2857982319-3063633125-1907478113&grant_type=authorization_code&scope=offline_access%20https%3A%2F%2Fgraph.microsoft.com%2F.default&code=1.{Paste the code we received}AV8AXXX…9I&session_state=00134’
Sample of how the request should look like:

Feel free to modify the user-agent accordingly – can assist in your hunting efforts later for detection creation.

If the request is successfully crafted, we should receive a Bearer access token along with the associated scope. This will provide us with valuable insight into the privileges assigned to the target user and the level of access they possess.
For the final step of the initial access phase, let's collect our Bearer token and craft a new request, this time targeting the Graph API host.
Consider using Graph Explorer. Our example includes a GET request for the target user profile. This should return the basic information on this user.

As seen in the image above, we will specify the authorization “Bearer”, followed by the full access token we redeemed previously from OAuth2 endpoint.

There you go, an unmanaged, non-compliant, untrusted device, outside of the organization scope of legitimacy and trusted device OS, far from being compliant – granted full access to Graph API.
- Application Layer Protocol (T1071)
- Web Protocol (T1701.001) – The act of HTTP request manipulation to bypass specific conditional access controls.
There are a few techniques we can leverage to steal credentials and claim MFA token, these usually involve:
Here at Mitiga, our incident responders bring a wealth of expertise, drawing from backgrounds in Red Teaming, Purple Teaming, and Blue Team operations. This diverse skill set has provided us with a keen understanding of the ease with which attackers can bypass various credential collection techniques to gain full access, particularly through conditional access bypass mechanisms.
In recent times, the rise of malicious browser extensions has become a significant concern. A common attack scenario involves the use of a malicious extension to capture valid access tokens, which can then be leveraged by an attacker in a Browser in The Middle (BiTM) attack.
A BiTM attack occurs when an attacker intercepts, manipulates, or monitors communication between the victim's browser and the web application. By embedding themselves in the browser session, they can access sensitive data, including authentication tokens, without the user's knowledge.

In the example, Chrome extension creates a vulnerability by enabling a "browser-in-the-middle" attack, where it intercepts and steals sensitive information during the OAuth2 login process. The extension automates the login flow, monitors network traffic, and extracts critical data from the "Location" headers in responses from https://login.microsoftonline.com/appverify. These headers often contain OAuth tokens or redirect URLs, which could be used for session hijacking or credential theft. Operating silently in the background, the extension sends the captured data to an attacker-controlled server, making it a stealthy tool for stealing authentication information without the user's knowledge. This underscores the importance of securing OAuth flows and carefully managing the permissions granted to browser extensions.
How do we stay ahead of these threats? Glad you asked. Here’s a list of key actions to consider:
- Regularly audit successful authentication from non-compliant and unmanaged devices.
- Require MFA for all user accounts to enhance login security.
- As a best practice, it is recommended to minimize the permissions granted to the Graph API to the lowest necessary level.
- Continuously monitor Microsoft Graph activity logs to observe anomalies.
- Consistently analyze any unusual volume of blocked access attempts to resources via non-interactive and interactive sign ins.
And always remember - Zero Trust isn’t just a framework, it’s the gold standard for minimizing risk. When it comes to initial access, the best mitigation is the trust you don’t give. Control, verify, and stay vigilant.
By taking advantage of our forensic data lake, within minutes we were able to hunt for this scenario. The data lake gives us the ability to query big chunks of data within a few minutes and gather clues that could be indicative of an attack or preserved as legitimate activity, this leaves our clients a peace of mind, knowing we are proactively hunting their environment for such attacks.
As JUMPSEC labs explained in their blog post, there’s no certain way of defending against CAPs bypass. We would need to keep-an-eye out for successful authentications with errorCode: 0, whilst identifying non-compliant devices, with interactive sign in to the vulnerable client.
To hunt for this activity, we would need to follow this schema:
Tweak this query as needed to receive the right results.
Our product offers detection coverage for an attempt of Conditional Access Policy bypass, with a broader look of the technique as well as our advanced detection engine with applied insights to reduce the noise and focus on what matters only.
Conditional access policies are a solid start in the fight against initial access attacks, but they’re just the tip of the iceberg. Every authentication is a potential entry point, and that’s where the real action happens. At Mitiga, we don’t just check boxes - we bring the latest tech and a team of experts to continuously monitor, identify, and shut down attacks before they can even breathe. We're here to keep your defenses sharp and your data locked down, no matter what’s coming your way.
To get in touch with our cloud security experts, set up a demo today.
UPDATE: As of today, security expert @dirk-jan shared on LinkedIn that the previously identified vulnerability in Microsoft Graph has been addressed. The resolution involves fully descoping the resource permission, which had previously allowed unauthorized access. By adjusting the permissions granted to MS Graph, this fix mitigates the risk of unauthorized data access. This change enhances security by ensuring that access controls are better aligned with least-privilege principles, thereby reducing the overall attack surface for organizations using MS Graph.