Whether you’re a SOC analyst or a detection engineer, understanding Microsoft email infrastructure is advantageous for investigating and resolving email-based threats. If you’re working at a Microsoft shop, you may have already seen Microsoft’s recent Phishing actors exploit complex routing and misconfigurations to spoof domains blog. That post gives a great overview of how adversaries are taking advantage of misconfigurations that can happen when a SEG (secure email gateway) is placed in front of Microsoft, as we can see from this line:
The phishing attack vector covered in this blog post does not affect customers whose Microsoft Exchange mail exchanger (MX) records point to Office 365; these tenants are protected by native built-in spoofing detections.
That post mentions a lot of topics you may have read about on our blog before, like Tycoon2FA PhaaS, Direct Send, AITM, fake invites, and more. After reading that post, though, we decided we wanted to talk about some of the ways attacks can be detected using information in typical Microsoft email headers. This blog will have some overlap with their blog, but will extend it by focusing on phishing detection within these headers.
While this will get in the weeds about email infrastructure, this post isn’t being written for email experts. It’s for anyone that wants to know more about how Microsoft headers could be used during investigations, like IT admins, Exchange admins, security folks, the overwhelmed help desk analyst at a 10 person company, and if you’ve made it this far, you too.
In each section, we’ll look at:
- A brief summary of what the header field is
- Why it can be useful to IT and security teams
- An example threat hunt in MQL. Start your free account if you want to try it out.
TL;DR on headers
Headers are data and metadata in email that helps a message get from outbox to inbox. They can include:
- Sender
- Recipient
- Content type
- Transport info
- Authentication and more
Aside from getting a message delivered, headers can also provide valuable information in IT troubleshooting and security investigations. In this post, we’ll mostly be looking at Microsoft-specific headers, but we’re going to start with an authentication header that spans all providers.
Authentication-Results header
One of the most common headers, no matter if you’re using Microsoft or not, is the Authentication-Results header. When it comes to detecting spoofing, authentication issues, sender account compromise, and more, this is the main header you will reference.
This header is used to verify and validate that a message was not forged and that it did not fail authentication along its path to your inbox. We’re going to look at a few of the important pieces of this header so that you can understand what to look for when investigating emails.
The three main authentication standards used in this header are:
- SPF (Sender Policy Framework): A record in DNS that specifies which mail servers are authorized to send email on behalf of your domain, helping receiving servers detect forged sender addresses.
- DKIM (DomainKeys Identified Mail): A cryptographic signature on outgoing emails that receiving servers can verify against a public key in your DNS, proving the message wasn't tampered with in transit.
- DMARC (Domain-based Message Authentication, Reporting & Conformance): A record in DNS that evaluates both SPF and DKIM and then passes a status and a handling recommendations along to the receiving server. When an email fails those checks, DMARC sends a failure report to help monitor a domain's email activity.
Here is an example of the typical authentication header and its fields:
This header usually starts with spf=[value] and then has a few other keys and values. When it comes to security, we care mostly about the later half of the string where it states dmarc=pass action=none and compauth=pass reason=100. These pieces of information give us several detection opportunities.
SPF overview
SPF authentication looks at the MAIL FROM envelope value to verify that an email is sent from an email server authorized to send emails for that domain. To configure SPF, organizations set up a TXT record in their domain’s DNS that explicitly states where a domain’s email should be sent from. The format looks like:
In human terms, this record is saying: Only Microsoft 365 mail servers (spf.protection.outlook[.]com) are authorized to send email for this domain. Fail anything else (-).
On the recipient side, there is an Administrative Management Domain (ADMD) where handling is configured. This determines what happens to emails based on their SPF status. For example, an ADMD could allow soft failed messages to arrive into a quarantine rather than go to an inbox. In a very strict environment, they could outright reject soft failures.
Security scope
For security, we don’t care too much about pass (not spoofed) or none (not configured), but we do care about fail, softfail, and temperror (rare), as these indicate something went wrong when trying to validate SPF.
In general, SPF is not often used for detections. Instead, practitioners will look at the DMARC status, since it is created by evaluating both SPF and DKIM. We’ll look at that shortly.
DKIM overview
DKIM is used to validate that content within an email (EML file) has not been altered in transit. DKIM does this by using a public and private key pair. The sender email admin will generate a key pair and store the public key in a TXT DNS record (never the private key). This key is then used for a digital signature on delivery. To get in the weeds about DKIM, check out this doc from Microsoft.
Here’s the format of a DKIM TXT record:
Security scope
Just like with SPF, security practitioners generally do not build detection mechanisms around DKIM, just DMARC.
DMARC overview
While the first two methods verify that the email is from the correct MAIL FROM and that it hasn’t been tampered with, they don’t address From: spoofing. DMARC does, though. In order for DMARC to pass (a.k.a. DMARC alignment), it looks at SPF, DKIM, and the From: header.
DMARC first looks at the status of SPF and DKIM. If either pass, it will then verify that the domain of the sending server for the passing authentication method matches the domain of the From: address.
- If SPF passes, DMARC will verify that the
MAIL FROMdomain matches theFrom:domain. - If DKIM passes, DMARC will verify that the DKIM
d=domain matches theFrom:domain.
If either of those methods pass AND the sending domain matches the From: domain, then DMARC passes. Even if SPF passes and DKIM fails, DMARC passes.
On the flip side, even when both SPF and DKIM pass, if neither can match the From: domain to the sending domain, then DMARC fails.
For security teams, DMARC is the best option for detecting spoofing. For IT teams, DMARC also comes with failure reporting, so you can see when attackers are attempting to spoof you. Just like with SPF, the admin will create a TXT record for DMARC. Here’s an example showing some of the available fields:
v: version of DMARCp: policy for failures on the domain level (reject, quarantine, none)sp: policy for failures on the subdomain level (reject, quarantine, none)pct: percentage of messages to apply the policy toruf: where to send per-message failure reportsrua: where to send aggregate failure report
You may be looking at the pct field and wonder why anyone would set this below 100. Generally, this value is adjusted during implementation testing and will be set to 100 in production.
Unfortunately, many organizations do not set up SPF, DKIM, and DMARC correctly or enforce reject within their policies. This leaves a security gap that is very easy to resolve. If you’re not sure if SPF, DKIM, and DMARC are configured properly, we’d recommend looking into it ASAP.
Security scope
DMARC results are useful in investigations of attacks that come from generally trusted senders. For example:
- Account spoofing: If DMARC is not aligned, it could be a solid indicator of a spoofed email. In these attacks, the email address may look legitimate, but the infrastructure it’s sent from is not authorized, indicating the spoof.
- Account compromise/BEC: If DMARC is aligned, but the email shows other clear indicators of malicious intent, it’s a strong signal that the (typically trusted) account has been compromised. In this case, a larger investigation would be required, including potentially reaching out to the security team for the compromised sender.
Now that we’ve covered these important authentication headers, let’s dig into some Microsoft-specific types. These headers provide insights into behavior with your mail infrastructure as well as opportunities for detection.
compauth: Microsoft Composite Authentication
Taking authentication validation a bit further, Microsoft offers compauth. If you are a Microsoft shop, you will likely use compauth as your authoritative means of validating authentication, as it goes beyond DMARC by using SPF, DKIM, DMARC, ARC (Authenticated Received Chain), spoof intelligence, sender reputation, and behavioral signals to do implicit authentication. Then, for each message received, a numeric reason code is provided which indicates success, failure, or neither, along with some explanation.
compauth gives organizations more security granularity, as well as more flexibility. This flexibility means Microsoft 365 can be configured to override statuses that you would assume would cause a failure. For example, compauth could be configured to pass even if DMARC fails (ex: ARC pass overrides a DMARC fail). This opens up the door for attackers who can find a way to sneak past certain configurations.
A full list of compauth reason codes can be found here, but here are some we think are valuable from a security standpoint.
108: DKIM fails, compauth passes
This code will arise when a message fails DKIM because of a modification to a message, but compauth still passes because the modification was made by trusted infrastructure (configured by the email admin). As an example, a 108 will likely occur when an SEG adds a banner to an email.
For security and IT teams, a 108 status can be used to identify compromised infrastructure. If an attacker has compromised a trusted piece of infrastructure, they could send a spoofed attack, slightly modify it with the compromised server so it gets a 108 reason code assigned, and then have it land in a target inbox. In this scenario, since attack will be coded as a 108 it will pass compauth.
To use these messages to identify compromised servers, threat hunters can search for all messages flagged as malicious that also have a 108 status. Here’s an example hunt:
Reason 451: Complex routing bypasses compauth
Reason 451 is specifically cited in the blog linked at the start of this post as an example of a “complex routing situation.” Complex routing could happen a few ways, like an MX routing that goes to a SEG first, or something as simple as the attacker using a distribution list (or Microsoft 365 group) to deliver the message. In that example, even though DMARC failed, compauth was bypassed due to route complexity, and a configuration on that server ended up sending it to spam via an oreject (override reject action). As a note, all 4xx reasons indicate that compauth has been bypassed entirely (compauth=none).
Because compauth is completely bypassed by a 451, it offers up a threat hunting opportunity. The below threat hunt catches authentication failures that "slipped through" due to policy configuration choices, meaning messages that should have been blocked, but were instead kicked over to spam. These represent potential spoofing attempts against domains without strict enforcement. Using this MQL with other suspicious indicators could help locate attacks that should have been quarantined (never reaches inbox), not marked as spam (reaches inbox). Remember that for attackers, the primary goal is to get through security, not hit an inbox. If they reach a spam folder, there is still a chance for success.
Reason 601: Identifying spoofing attempts
Reason 601 indicates DMARC/SPF failures where the attacker attempted to spoof your own domain. While a 601 can be a direct indicator of domain spoofing attacks targeting internal trust, they can also happen when a third-party app isn’t properly configured to send from your domain.
In the case of an attack, an external sender tried to impersonate someone within your organization, but failed implicit authentication. “Implicit” authentication includes evaluating things like IP reputation, sender history, etc., and is used when “explicit” authentication (DMARC, SPF, etc.) isn’t correctly configured.
Hunting down 601 messages can be helpful to security and IT alike. Security teams can use it to find spoofing attempts, and IT can use it to find improperly configured third-party apps, relays, legacy tools, and more. Here’s an MQL hunt for finding them:
Reason 905: Enforcement bypass
Reason 905 occurs when DMARC authentication failures bypass enforcement due to tenant allow policies for an “on-premises Exchange environment or a non-Microsoft service” that sits between the sender and Microsoft 365. An example of a “non-Microsoft service” would be an SEG.
In the case of a 905, messages that failed authentication were delivered anyway because an admin policy explicitly permitted them. This could indicate overly permissive allow-lists being exploited by attackers spoofing "trusted" domains. This is similar to 451, but since it’s a different reason code, it presents another threat hunting opportunity.
X-Forefront-Antispam-Report
X-Forefront-Antispam-Report is a Microsoft-specific header that’s applied by Microsoft Exchange Online Protection (EOP). This header tells you a great deal about how a message was handled by EOP. Here’s an example X-Forefront-Antispam-Report and what the fields mean:
CIP, CTRY, and LANG are self-explanatory, but the handling information is right after that (full list here):
SCL: Spam confidence level from-1(not checked) to9(very likely spam).SFV: Spam filter verdictSKS: marked as spam before filteringSPM: marked as spamSKN: bypassed filtering via a transport ruleSFE: safe, not filteredSKI: skipped filtering because the source IP was in the connection-filter IP Allow List
CAT: Verdict categorySPM: spamPHSH: phishSPOOF: spoofBULK: bulk mailMALW: malwareGIMP/UIMP: impersonation
SFTY: Safety indicator. Here are some examples for spoofing and phishing:9.19: domain impersonation9.20: user impersonation9.25: first contact safety tip triggered
PTR: reverse DNS of the connecting IP
These values can be useful for threat hunting. Similar to 451 threat hunting, we can use spam labeling as a signal along with other malicious signals to see if attacks have been mislabeled. Here’s an example hunt:
Impersonation hunting
Beyond spam, we can use this header to find impersonation attempts. These emails aren’t necessarily in a spam folder and their location is dependent on configuration choices:
Phish hunting
Just like with impersonation hunting, we can do the same for phish. The below hunt will find any emails labeled as phish and can be used with other malicious signals to find attempts that haven’t been quarantined:
Misconfiguration hunting (this one’s for IT)
There are other ways we can use this data, especially when wanting to identify misconfigurations within an environment. Using the below threat hunt along with the spam hunt, you can find messages that reached a user’s mailbox even though they were on a Block Senders list:
- Skipped spam filtering
- Released from quarantine
- On user’s Blocked Senders list
X-MS-Exchange-Organization-* headers
The following X-MS-Exchange-Organization-* family of headers are unique, as they are considered internal to Microsoft and they are stamped by Exchange during transport by EOP. This also means these headers are actually stripped/added at organization boundaries. We’re going to look at a few of these headers. For length, we won’t include hunts for every header.
X-MS-Exchange-Organization-InternalOrgSender
The InternalOrgSender header has a boolean value which indicates whether the sender is marked as internal or not. Typically a sender is marked internal based on whether it is a tenant mailbox, an authorized hybrid on-premises server, or a properly configured inbound connector.
The InternalOrgSender header works in conjunction with the MessageDirectionality and AuthAs headers to determine if a sender is considered internal or external. We’ll cover those two headers later in this post.
From a spoofing perspective, the most important combination to be aware of for this header is:
InternalOrgSenderisTrueAuthAsisAnonymousMessageDirectionalityisIncoming
What this combination means is that the message is from within your organization, but it’s being sent anonymously, and somehow is coming from outside your organization. Generally speaking, internal messages are internal, not anonymous and directionality is originating, not incoming. This could be benign, but it could also be indicative of a spoofed message or an infrastructure misconfiguration. In any case, it is worth investigating further. The below hunt can be used to find these messages:
Here’s a full list of combinations and what they could mean:
X-MS-Exchange-Organization-MessageDirectionality
The MessageDirectionality header provides context as it relates to how the message arrived in the environment. This header is an internal header that is applied/stamped by EOP based on the transport rule that was applied to the message, thus indicating directionality:
- Originating: The message originated inside the org: an Exchange Online mailbox, or on-premises Exchange arriving over an inbound connector of type
OnPremises(hybrid). These messages are less scrutinized for internal to internal validation like SPF validation, spoof verdicts, phishing detection, and anti-impersonation controls. - Incoming: The message arrived at an accepted domain without matching an
OnPremisesconnector; treated as external, full EOP filtering applies.
From a security perspective, message directionality is something that can be trusted. This value can’t be spoofed, so if a message says it’s from an internal sender but has an incoming directionality, you can treat that message as suspicious. It’s a great signal to use in a hunt, which we’ve used in a few of the different samples above and below.
X-MS-Exchange-Organization-ASDirectionalityType
This header has a numeric value which indicates its directionality (similar to MessageDirectionality), but is provided by Microsoft’s anti-spam pipeline in EOP. It’s what the anti-spam service uses to track directionally. It has three possible values:
1: incoming from outside the organization2: outgoing to outside the organization3: intra-organization
This is different from the MessageDirectionality, but the two should always align (just from different perspectives and independent of each other). If you’re using one, you likely don’t need to use the other.
X-MS-Exchange-Organization-AuthSource
AuthSource is the FQDN of the Exchange server that authenticated the incoming message. This value is useful for security purposes when used in conjunction with AuthAs: Internal. Since AuthSource should be an internal server, AuthAs should be Internal. If it’s not, it is an indication of spoofing. Here’s an example threat hunt:
X-MS-Exchange-Organization-AuthAs
AuthAs is a straight forward header that is helpful for identifying internal spoofing. It has two values: Anonymous and Internal. If a message gets the value Anonymous, that means it was sent from a mailbox outside of your org (ie. not authenticated internally). As covered earlier, this in combination with X-MS-Exchange-Organization-MessageDirectionality is an indicator that either that a message is a spoof of an internal sender or there is a misconfiguration. As a note, this header is similar to X-MS-Exchange-CrossTenant-AuthAs and can be used in lieu.
As covered above, the values for X-MS-Exchange-Organization-MessageDirectionality are Originating and Incoming. See the table below for more details on the different scenarios:
We already used these fields for a security hunt up above, so for IT teams, we can use the below hunt to look for possible misconfigurations. In this case, we’ll find unauthenticated messages marked as originating internally that have bypassed the spam filter check.
⚠️ Critical: MessageDirectionality > AuthAs
When X-MS-Exchange-Organization-MessageDirectionality: Incoming is present,
the message came from outside the organization, regardless of whatX-MS-Exchange-Organization-AuthAs says. This scenario occurs when:
- Mail is redirected internally from an external message
- Complex routing causes Microsoft to stamp internal auth on inbound mail
- Hybrid Exchange environments produce conflicting header signals
From a security perspective, messages with AuthAs: Internal +MessageDirectionality: Incoming should be treated with heightened scrutiny, as they represent a conflict between trust signals and spoofing signals. Here’s a hunt for that:
X-MS-Exchange-Organization-SCL
We looked at this briefly at the start of this section, but SCL provides insight into the EOP spam confidence level determination for a message. The hunt below can used to surface the messages EOP has flagged as mid to high confidence spam in order to see if you need determine if SCL policies should be adjusted at all:
X-MS-Exchange-Organization-PCL
PCL is the phishing confidence level. You can use it the same way you’d use the SCL level.
PCL is a legacy Exchange/Content-Filter construct, effectively deprecated in Exchange Online (modern signals are CAT/SFTY/compauth).
X-Microsoft-Antispam
X-Microsoft-Antispam is a broad name for a (currently) narrow header. As of publication, this header is used for assigning a BCL (bulk complaint value) level. The value assigned correlates to the amount of complaints received for a type of bulk mail (ie. marketing spam). Microsoft uses unsubscribe, send to spam, and other actions to aggregate sender infrastructure data to calculate this value. Here’s a hunt that can be used similar to the PCL and SCL hunts:
X-Microsoft-Antispam-Mailbox-Delivery
The X-Microsoft-Antispam-Mailbox-Delivery header tells you where a message ended up – inbox, junk folder, quarantine, or delete – and why it ended up there. Here’s an example:
As of publishing, this header is not well documented, so here is a table of values that we find helpful:
The contents of this header can be very useful for hunts. For example, using these values, we can see which emails have been allowlisted so they reach a user’s inbox instead of spam. With that info, an admin could adjust the SCL for mail that’s set to spam that users actually want.
This header is also good for identifying messages flagged as malicious that are getting through because of a white list configuration. For example:
We can also find messages that are delivered to a user’s custom folder based on a user controlled filter. This is indicative of a few things like a custom mail rule or content filter based on the user preferences:
X-Blog-Conclusion
This has been just a small sampling of a much larger Microsoft header ecosystem, but these are all headers we’ve found useful for threat hunting. More often than not, we use them in tandem with other signals to refine our hunts.
We hope this blog helps you understand a little bit about the nuances and specifics around Microsoft email headers, especially if you are investigating, troubleshooting, or hunting for threats in environments. If there are any headers we didn’t mention that you use regularly, reach out on X or LinkedIn (linked below) and let us know. Happy hunting!
Get the latest
Sublime releases, detections, blogs, events, and more directly to your inbox.






.avif)