← Return to overview

Device Code Phishing Forensics: What We Learned Investigating BEC in the Wild

Jun 2, 2026
Martin Warmer
By: Martin Warmer, Davy Boekhout and Jorn Pieterse

Business Email Compromises (BEC) are among the most prevalent cyber incidents out there and the biggest risk to companies, yet almost no one is talking about them. Over the years, attacks have evolved from simple pages that steal your password to full-blown attacker-in-the-middle proxies designed to bypass MFA and steal session tokens.

In this blog, we explain how device code phishing is returning at scale, how users are tricked, and what defenders can do to prevent, detect, and investigate these attacks. We cover detection in Entra ID using Sentinel, prevention with Conditional Access policies, stopping Microsoft 365 phishing in the browser, and forensic investigation techniques, including cases where one session ID appears to belong to two different people.

The return of device code phishing

April 1st started with the kind of phishing reports we receive all the time from customers. While reviewing one of them that was clearly malicious, the initial analysis was “ah yes, classic device code phishing”. But more of them appeared, on the same day.

That day, we had gone from sometimes seeing device code phishing in customer reports to seeing four in a single day. And it kept rising from that day onwards. Attackers clearly started scaling it.

What is BEC? BEC is one of the most common kinds of security incidents happening at companies of all sizes. The initial access is usually obtained by tricking the user into signing in on a fake Microsoft login page, the so called Attacker in the Middle (AitM). Logins originating from these fake pages can be detected in the Entra sign-in logs, and can also be blocked by AitM Block, our browser extension we developed.

Now what is device code phishing? It’s a phishing attack misusing Microsoft’s device code login flow, where the user must enter a code in the official Microsoft site to login another device. This flow is originally intended to be used in situations where a full browser is not available, like a video conferencing setup or a DevOps pipeline. As these sign-ins happen on the real Microsoft website, even a conscious user can be fooled by this.

While device code phishing itself is not new (see this excellent blog post by Dirk-jan Mollema for context), we have observed a sharp rise in adoption of this technique in in-the-wild phishing frameworks in the past few months. So our experts dove into it.

The forensics: why device code phishing is so hard to spot

Let’s start with the last phase of a BEC: the attack has been detected and the impact needs to be determined. When doing forensic analysis of a compromised Microsoft account, the default method is to collect the Unified Audit Log (UAL). This contains a complete overview of all actions taken using the account. This leaves the investigator with the job of distinguishing between activity of the real user and the attacker.

Typically, once you’ve found the initial compromise, it is usually quite easy to follow the attacker. Every sign-in on a new device is given a new session ID, which makes it easy to filter out attacker activity from the UAL based on that ID.

However, for device code sign-ins, the session ID is shared between the attacker and the real user. This means that we need a more detailed method of tracking the credentials stolen by the attacker.

Luckily, Microsoft made linkable token identifiers generally available in July 2025. These include unique token identifiers, which are unique for every access token generated by Entra. The UAL only contains regular interactive sign-ins. Therefore, we need to download the non-interactive sign-in logs from Entra to track all unique token identifiers.

When the phishing page has no login form

To investigate an account which has been compromised by device code phishing, we need to obtain both the UAL and the non-interactive sign-in logs. If we’re lucky, we can simply mark all sign-ins with originalTransferMethod “deviceCodeFlow” and use the corresponding unique token identifiers to filter the UAL, thereby obtaining a clear overview of all Exchange related activity of the attacker.

In case the user also uses device code sign-ins legitimately, we need to use other attributes such as the IP address or user-agent to get the unique tokens issued to the attacker. These tokens can then be used to filter the UAL and get attacker activity.

Stopping the attack at the source: browser-extension detection

As much as we love a thorough forensic investigation, prevention is always better than the cure. Every BEC we don’t have to investigate is a customer who didn’t suffer one. The walkthrough above is what we do when prevention fails.

The latest release of AitM Block, our free browser extension built to detect and block Adversary-in-the-Middle (AitM) phishing attacks targeting Microsoft 365 and Azure login pages, brings device code coverage and helps minimise these walkthroughs. You will find the extension on the Chrome Web Store.

Catching static landing pages

Detecting AitM phishing was a relatively manageable problem because the threat actor has to render a fake login form on a domain they control. The look-alike domain, the form pointing at the wrong action URL, the mismatch between brand and host – there were always signals to find.

Device code phishing has none of that at the moment of the attack. The login is real, the domain is real, the MFA prompt is real. The only place where the threat actor can be observed is on the social-engineering page that delivers the code to the victim. So that’s where our extension looks.

We match against the two real device-code endpoints – microsoft.com/devicelogin and microsoftonline.com/common/oauth2/deviceauth – and, in the same document, look for a short alphanumeric code. A page is flagged when both patterns appear in the same document, including iframes the page has loaded. This covers static landing pages. 

Catching single-page-application phishing kits

Static HTML matching catches the straightforward case. Modern phishing kits look more like single-page applications: a small JavaScript bundle that fetches the device code from Microsoft on the fly. They need to do that, because the code expires every fifteen minutes, so phishing kits can’t use static device codes. The page is essentially blank when our scanner first looks at it.

To catch these, we instrument the page itself. Within a small script injected into the page’s main world, we wrap fetch, XMLHttpRequest, and window.open, watching for the response shape that’s unique to RFC 8628: a JSON object containing both device_code or user_code and verification_uri or verification_url.

Not many legitimate non-Microsoft endpoint returns that combination. If we see it on a page that isn’t Microsoft itself, the page is initiating a device code flow; the exact thing a phishing kit needs to do to acquire its codes. The window.open hook covers the cruder kits that don’t bother with their own UI and simply pop a tab to microsoft.com/devicelogin after a click.

Catching encrypted loaders (EvilTokens)

Some kits go further still. Sekoia recently published research on a kit nicknamed EvilTokens, which ships its phishing UI inside a small AES-GCM-encrypted blob. A loader script decrypts the blob at runtime and writes the result into the page with document.write and a TextDecoder. The point is to defeat static signature scanning. Antivirus engines and HTML-based detectors looking at the page as delivered see only an encrypted blob and a generic decryption call, not a phishing page.

We catch this by matching the loader rather than the payload: the combination of crypto.subtle.decrypt with AES-GCM plus a document.write of TextDecoder output is rare enough in legitimate code to be a clean signal on its own. We have to act before the decryption fires. Once document.write runs, the MutationObserver we’d otherwise rely on is detached from the freshly-rewritten document.

For our customers running our extension, device code phishing is intercepted on the page that delivers it, before the victim ever lands on Microsoft, before any code is entered, before any token is issued. The forensic process described in the first half of this article remains our last line of defence. The new version of the extension ensures we have to use it less often.

Detecting device code phishing in Entra logs

The simplest way to detect phishing attempts using the device code flow is to check the Entra sign-in logs. Any sign-in where AuthenticationProtocol == “deviceCode” can be marked as suspicious and investigated. However, a lot of Entra tenants have at least some legitimate device code sign-ins.

Common device code use cases

The most common use cases for device code sign-ins are developers and administrators logging in from a terminal program like “Microsoft Azure CLI” or “Microsoft Graph Command Line Tools” or “Azcopy”. But there is a long tail of other logins which we have seen in our research. Physical devices like printers are signing in using device codes. Microsoft applications like Dynamics 365 Warehouse Management also regularly use it, as can be seen in the documentation.

Phisher-favourite apps: Microsoft Office and Microsoft Authentication Broker

The most popular app for phishers is currently “Microsoft Office”, which is a FOCI (Family of Client IDs) application. FOCI applications allow an attacker to exchange their refresh token for almost all applications in the M365 ecosystem. This app doesn’t normally use device code, so any hits are likely to be an attack.

Another phisher favorite app is “Microsoft Authentication Broker”, which allows you to register a device in Entra. Device code usage is rare for this app, but does occur for e.g. video conferencing equipment. However, when you see the resource “Microsoft Graph”, you can be sure it is not a legitimate sign-in.

The advantage of using this application is that you can upgrade the refresh token to a Primary Refresh Token (PRT). To do this, the phisher first has to register a device and request a PRT using that device identity. The PRT is valid for all applications and survives session revocation. Deleting the device does invalidate the PRT, so be sure to check for newly registered devices. An often seen device name is “DESKTOP-” followed by 6 or 8 hexadecimal characters. This differs from the Windows default which generates 7 alphanumeric characters, providing another detection capability.

KQL detections for Sentinel

Phishers will keep updating the exact applications, device names and resources accessed, so be sure to keep an eye out for new combinations. Detecting most of the current phishing kits can be done using the following KQL queries:

Detecting Sign-ins

SigninLogs
| where ResultType == 0
| where AuthenticationProtocol == "deviceCode"
| where AppId == "d3590ed6-52b3-4102-aeff-aad2292ab01c" or 
    (AppId == "29d9ed98-a469-4536-ade2-f981bc1d605e" and 
     ResourceIdentity == "00000003-0000-0000-c000-000000000000")
// Filter out sign-ins from trusted named locations
| mv-apply nld = todynamic(NetworkLocationDetails) on (
    summarize TrustedNamedLocations = countif(nld.networkType == "trustedNamedLocation")
)
| where TrustedNamedLocations == 0

Detecting device registrations with suspicious device names

AuditLogs
| where OperationName == "Register device"
| mv-apply Resource = TargetResources on (
    summarize TargetDevice = take_anyif(Resource, Resource.type == "Device")
)
| extend RegisteredDeviceName = tostring(TargetDevice.displayName)
| where RegisteredDeviceName matches regex @"^DESKTOP-[0-9A-F]{6,8}$" 

Blocking device code sign-ins with Conditional Access

Audit legitimate use first

Before blocking device code sign-ins, the first thing to check is whether they are actively used. This can be done in the Entra UI, by going to “Monitoring & health > Sign-in logs”. Filter these logs by adding a filter where “Authentication Protocol” is “Device Code” and expand the date range to, e.g., one month. This will show you which accounts are using the device code sign-in flow. For these users, a decision has to be made, for example, to switch to a different sign-in method, exclude them from the block, or allow access from a specific IP, such as the company office IP addresses.

Building the Conditional Access Policy

Using this information, you can create a Conditional Access Policy (CAP) which blocks access for device code sign-ins. To do this, make sure it includes all users, all resources and all network locations initially and add exclusions as necessary.

Then select “Conditions > Authentication flows > Device code flow” as condition. Finally, configure the policy to “Block access” and enable it.

As always with CAPs, be careful to not lock yourself out. For more detailed instructions, see the Microsoft documentation.

Why “All resources” matters (the Auth Broker bypass)

Be sure to make the CAP apply to “All resources”. Otherwise, the phishing attempts which use “Microsoft Authentication Broker” will be able to bypass the CAP.

This is a deliberate design decision by Microsoft. It allows devices to be enrolled into the environment while not yet compliant or connected to the VPN, which is necessary to receive e.g. the Intune configuration to become compliant and able to pass other CAPs limiting, for example, Exchange or VPN access to compliant devices. This situation is described in the “Phishing the phishing resistant” talk by Dirk-Jan Mollema.

Conclusion: defence in depth against device code BEC

Device code phishing represents the latest evolution of the cat-and-mouse game of Business Email Compromise (BEC). At Eye Security, we are dedicated to reducing the impact of BECs for our customers. To do this, we work on the problem from all angles:

  • Conditional Access Policies can block device code phishing attempts where possible;
  • MDR service based on Sentinel detects compromised accounts within minutes using the KQL queries shared above, allowing us to intervene and prevent further damage;
  • Eye Security’s AitM Block browser extension detects phishing pages that use device code phishing and warns users preemptively;
  • and finally, we have the in-house expertise to run a fine-tooth comb through the Unified Audit Logs during forensic investigations of device code phished accounts.

In this article, we’ve shared our knowledge about these three areas, which we trust will make a significant impact against device code BECs.

About Eye Security

We are a European cybersecurity company focused on 24/7 threat monitoring, incident response, and cyber insurance. Our research team performs proactive scans and threat operations across the region to defend customers and their supply chains.

This research was conducted by the Eye Security Threat Research Team, dedicated to detecting and disrupting emerging attack techniques across Europe.

Learn more about Eye Security at https://eye.security/ and follow us on LinkedIn to help us spread the word. You are also invited to read our corporate blog for customers and partners about AI Leak Block.