Last year I gave a talk at BSides Canberra 2024. “From external to the CEO, a modern approach to Outlook mail spoofing” demonstrated some effective techniques to exploit message parsing within Microsoft’s email ecosystem and deliver convincingly spoofed email to an Outlook user’s inbox. You can watch the recorded version of the talk on YouTube:

There’s nothing new in this blog post (at least nothing that I’m ready to talk about yet 👀) but I hope it serves you well as an easy-to-digest version of that talk.

A quick SMTP refresher

Before diving in, it’s worth noting that my understanding of SMTP wasn’t built overnight. A lot of this came from hands-on experimentation, reading through RFCs, and poking at different email clients to see how they interpret the same message. If you’re new to email protocols, don’t worry, we’ll start with some key concepts and I’ll explain the rest as we go.

First of all, it’s worth remembering that the “traditional” email flow is most relevant in the context of email that traverses the Internet. Giants like Microsoft and Google have built their own substantial email ecosystems, and when mail travels between two users in the same such ecosystem, it’s handled “within the black box” so to speak. The techniques in this post all exploit the way in which Microsoft’s infrastructure parses Internet mail, requiring us to target the external-to-internal path.

The Simple Mail Transfer Protocol (SMTP) was first proposed in RFC 821 as a way for users to send emails over the Internet via sending and receiving servers. The protocol has since been extended upon many times, namely with the introduction of Multipurpose Internet Mail Extensions (MIME) and Extended SMTP (ESMTP).

When an email is sent, it typically travels through a number of stages before reaching its final destination.

  • Sender’s Mail User Agent (MUA): The email client where the message is composed (e.g., Thunderbird)
  • Mail Submission Agent (MSA): Receives email from MUA. Typically authenticates the connecting user and ensures they can send mail from the email’s stated address.
  • Mail Transfer Agent (MTA): Processes and transfers emails
  • Mail Delivery Agent (MDA): Final stop before delivery to recipient’s MUA
  • Recipient’s MUA: Email is retrieved, such as via POP/IMAP protocols, and read (e.g., Outlook)

This message flow can be seen in the diagram below.

Diagram showing email architecture with four main components: Mail User Agent, Message Submission Agent, Mail Transfer Agent, and Mail Delivery Agent. The Mail User Agent sends emails to the Message Submission Agent using SMTP on ports 465 or 587. The Message Submission Agent sends emails to the Mail Transfer Agent using SMTP on port 25. The Mail Transfer Agent delivers emails to the Mail Delivery Agent. Finally, the Mail Delivery Agent allows the Mail User Agent to retrieve emails using IMAP or POP3.

Email messages consist of two main components: the SMTP envelope and the message content. You can think of the SMTP envelope like a postal envelope that helps to route an enclosed message to the correct destination. The envelope is conveyed through a series of SMTP commands.

Some common SMTP commands are described below.

  • HELO/EHLO: Identifying message which initiates the SMTP session
  • MAIL FROM: Email address of the sender
  • RCPT TO: Email address of the recipient
  • DATA: Denotes the beginning of the message content, which ends with a line containing a single ‘.’
  • QUIT: Terminates the connection

The message content itself contains two separate sections - the headers and the message body. The headers provide the MUA with contextual information about the email, such as the author, the recipient’s address, the message subject, and details about how the body has been encoded. The body holds the actual content of the email, and can be formatted or encoded in various ways as specified in the headers. Each line of the message content ends with a carriage return and new line (\r\n) with an empty line used to separate the headers from the message body. The message content section ends with a line containing a single dot character.

Remember: The headers are not the same as the envelope. The envelope is conveyed through SMTP commands, and the headers form part of the message content. To make matters more confusing, both the envelope and the headers convey a “From” address. They’re usually the same email address, but they don’t have to be. For clarity, when I’m talking about the MAIL FROM address in the envelope I’ll call it the “envelope from address”, and I’ll refer to the From: field in the message headers as the “header from address”.

The diagram below shows how these components form a typical mail message.

An annotated diagram of a complete email transmission. The Envelope section contains the HELO, MAIL FROM and RCPT TO commands. The DATA command begins the Message Content section. The Message Content section contains headers, including From, To and Subject. The body is separated from the headers by a blank line. Finally, the Message Content section is ended by a line containing only a single dot, and the SMTP command QUIT is used to end the transmission.

Multipart Messages

To handle modern features like rich formatting and attachments, most emails today use what’s called a multipart message. In this structure, the Content-Type header defines a special “boundary” marker that separates different versions of the content within the body, most commonly a plain text part (text/plain) and an HTML part (text/html).

The techniques in this post don’t require a multipart structure, and so for simplicity we’ll stick to using traditional messages with a single part.

Modern email protections we’re up against

Today’s email systems aren’t just a single server and a client. They’re made up of multiple layers including filtering gateways, authentication services, user policy engines, and the MUA itself. Each layer adds its own set of checks and protections to catch spam, phishing, and other malicious activity before it reaches the user.

We’ll discuss each of these protections one by one.

Generic SMTP protections

To add a layer of sender verification to email, three key standards were introduced over time: first SPF, then DKIM, and finally DMARC to tie it all together. These standards all rely on domain owners publishing special DNS records. When another mail server receives an email, it checks these records to verify the message came from an authorised source.

Sender Policy Framework (SPF)

SPF is like a public “allowed senders” list for a domain. Domain owners publish a special DNS record that lists which email server IP addresses are permitted to send emails on behalf of that domain. When a mail server receives an email, it performs an SPF check by validating the domain in the envelope from address.

The server compares the IP address of the sending machine against the authorised list in the SPF record for the email’s domain name. If the IP address is found in the list, the SPF check passes; otherwise, it fails.

Note

SPF only validates the domain in the envelope from address. SPF alone does not prevent an attacker from placing a different, spoofed address in the header from field.

An SPF record might look like this:

example.com. IN TXT "v=spf1 ip4:192.0.2.5 -all"
  • v=spf1 identifies the record as SPF version 1.
  • ip4:192.0.2.5 authorises a specific server IP address.
  • -all specifies a hard fail, instructing mail servers to reject email from any source not listed.

DomainKeys Identified Mail (DKIM)

DKIM takes a different approach and is a little more complicated than SPF. Rather than using source IP address as an authenticating aspect, it instead uses cryptography to digitally sign emails as they’re emitted by a server from a sending domain name.

First, to set up DKIM, a sending domain name owner will generate a public/private keypair. They’ll configure their mail servers with the key pair (including the private key) and will publish the public key using DNS.

When the mail server emits email on behalf of a sending user, it can use the private key to sign certain aspects of the email in a particular way described by RFC 6373 section 5 and then place this signature into the DKIM-Signature header of the outbound mail. Upon receiving mail with a DKIM-Signature header, the receiving server can retrieve the public key using DNS and use it to verify the signature.

DKIM allows for a domain name to have multiple DKIM keypairs. They are distinguished by something called a “selector”.

An example of a DKIM header is as follows:

DKIM-Signature: v=1; a=rsa-sha256;
        d=example.com; s=selector1;
        h=from:to:cc:subject:date:message-id;
        bh=<hash>;
        b=<signature>
  • v is the version of DKIM in use - currently there is only the one
  • a is the algorithm used to generate the hash and the signature
  • d is the “Signing Domain Identifier” and s is the keypair selector
  • h is the list of headers from the email that contribute to the signature
  • bh is the hash of the contributing headers and the body of the message
  • b is the signature of bh using the algorithm in a and the key identified by s and d

There are other fields that may be present in a DKIM header, but above is the minimum required fields for the header to be valid.

To retrieve the public key from DNS, a receiving mail server would use the selector (in this case selector1) and the Signing Domain Identifier (in this case example.com). An example DNS record for this key could be as follows:

selector1._domainkey.example.com 3600 IN TXT "v=DKIM1; k=rsa; p=<public key>"
  • v=DKIM1 and k=rsa specify the version and key type respectively
  • p contains the actual public key data

Given this public key, the signature from the DKIM header can be validated.

It is worth noting that RFC 6373 DomainKeys Identified Mail (DKIM) Signatures deliberately avoids saying whether the Signing Domain Identifier should match anything in particular regarding the email, such as the envelope from or header from address. Section 3.11 puts it bluntly:

This document does not require the value of the SDID or AUID to match an identifier in any other message header field. This requirement is, instead, an Assessor policy issue.

And so what to do with an email that lacks a DKIM header, contains a valid DKIM header, contains an invalid DKIM header, or contains a DKIM header for a totally unrelated domain name, is left to the receiver’s discretion.

Domain-based Message Authentication, Reporting & Conformance (DMARC)

DMARC ties both SPF and DKIM together and adds an extra layer of control.

First of all, recall that SPF validates that the connecting IP address is allowed to send mail from the domain in the envelope from address. SPF alone doesn’t care about the header from address, which is the email address that an MUA will display to the recipient. DMARC fixes this by putting the focus on the header from address, as explained by RFC 7489 Section 3.1:

DMARC authenticates use of the RFC5322.From domain by requiring that it match (be aligned with) an Authenticated Identifier. The RFC5322.From domain was selected as the central identity of the DMARC mechanism because it is a required message header field and therefore guaranteed to be present in compliant messages, and most Mail User Agents (MUAs) represent the RFC5322.From field as the originator of the message and render some or all of this header field’s content to end users.

DMARC policies are published in DNS and tell receiving mail servers what to do if an email fails SPF and/or DKIM checks (e.g., reject the message, quarantine it, or let it through). DMARC can also generate reports for domain owners about failed authentication attempts, helping them monitor in-the-wild abuse or misconfigurations.

Importantly, for DMARC to pass, you only need either SPF or DKIM to succeed (as long as the passing mechanism aligns with the domain in the header from address). That means if one fails but the other passes, the message will not be rejected by DMARC. There is no way for a domain owner to use DMARC to insist upon SPF and DKIM alignment.

An example DMARC record could look like this:

_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
  • v=DMARC1 identifies the version of DMARC - currently there is only the one
  • p=quarantine specifies the action the receiving server should take for unaligned messages
  • rua= specifies an email address where reports should be sent

Reasoning about SPF, DKIM and DMARC as attackers

These three technologies form the basis of email security and deliverability.

If you are planning on sending email from a domain name you own, they’re not a problem. You can easily set them up - and you should. If you don’t, then receiving email servers (particularly the larger ones) tend to take a less favourable view of the email you send. Whether this is an effort by email platforms to try to increase adoption of basic domain name security hygiene, or whether it’s an attempt to use the presence of good hygiene as an indicator of trustworthiness, you’ll have an easier time if you take a moment to set them up correctly and ensure that the email you send is properly aligned.

If, on the other hand, you are planning on spoofing email from a domain name you don’t own, then they can stand in the way of your efforts.

First, as an attacker, you can easily query DNS for the domain name’s DMARC policy. DMARC exists at a static name within DNS (TXT _dmarc.<domain>). If it exists, you can expect to need your email’s header from address to align with either the domain name’s SPF policy (if any) or with the domain name’s DKIM posture.

Next, SPF is also easy to look up. A domain name’s policy exists as a TXT record for the domain name itself. If it includes an IP address from which you can feasibly emit email then you’re good to go, but in most cases the list will be locked down to IP addresses owned by the domain name owner, or to IP addresses belonging to cloud platforms with account verification controls.

DKIM is a little trickier. Keys are identified by selectors, and so there is no standard way to look up a domain name’s DKIM keys within DNS. You can instead try to elicit mail from the domain name and check the message headers to discover a valid selector, or look the domain up in a public resource such as the DKIM Archive which catalogues domain name DKIM keys over time. However, learning a domain name’s public DKIM key is of little use, unless you’re able to steal or crack the corresponding private key.

A different way to go about things is to plan to send email with a header from address that you control, but with other elements that may confuse the user’s MUA into showing a different address. More on that shortly 😉

First, we need to understand any vendor-specific protections or controls that may be employed by our destination organisation.

Microsoft-specific protections

In addition to the standard SMTP protections (SPF, DKIM, DMARC), Microsoft implements their own proprietary set of protections which are configurable within a receiving organisation.

One important aspect here is that most of these protections only analyse the header from address, overlooking other headers. This will become relevant later.

Use of mail flow rules

Mail flow rules (aka transport rules) let administrators apply custom actions to messages while they’re in transit. These rules offer a rich set of conditions, exceptions and actions to fine-tune email handling.

A common use of these rules is to tag emails which originate from outside the organisation as being “external”. This is performed by adding an administrator-defined message to the message body or email subject.

Screenshot of an email showing an external tag prepended to the message body using mail flow rules.

Note

This yellow warning may look eerily familiar. You could be forgiven for thinking it’s a built-in Exchange thing, or part of the Outlook User Interface when showing email from outside the organisation.

It’s actually arbitrary HTML that an administrator can configure to be added to each in-flight message that meets certain criteria.

I’m guessing that enough organisations use the exact same (or similar enough) warning message style that it’s been burned into our brains as though it’s a built-in thing.

External email tagging

As an alternative to the use of mail flow rules for warning users about external mail, Microsoft Exchange Online provides a feature called External Sender Identification to natively and dynamically flag external emails in the Outlook UI. This means that a user can be appropriately warned about the nature of an email, without the content of the message needing to be manipulated in flight.

This method for tagging emails is preferred as it avoids interfering with messages that might rely on specific formatting or signing mechanisms.

Screenshot of an email showing a dynamic external email warning above the message body.

This feature must be configured in PowerShell with the following command:

Set-ExternalInOutlook -Enabled $true

Anti-phishing policies

Anti-phishing policies encompass a broad range of protections that aim to prevent phishing attempts. These policies can be customised in Microsoft 365’s Security & Compliance Center.

Spoofing detection

Spoofing detection provides two layers of protection.

Firstly, for end users, Outlook shows clear visual indicators on emails that fail various checks as performed by Exchange. This can include a red “Unverified sender” warning message, and/or the replacement of the sender’s profile picture with a question mark icon.

Screenshot of an email showing an unverified sender warning above the message body.

At the same time, Microsoft 365 administrators get access to organisational reports within the Security & Compliance Center. These reports highlight attempted spoofing against users or domains in the organisation, enabling admins to monitor patterns and respond to threats.

Impersonation protection

Impersonation protection allows administrators to define a list of email addresses (such as company executives) or domains (such as business partners) that should be considered sensitive. When set up, emails claiming to be from such a person are subject to additional scrutiny. If an email fails these checks, actions can be applied to that message to send it to the junk mailbox, quarantine it within the admin centre, or delete it.

Mailbox intelligence

Mailbox intelligence uses AI to learn from normal email patterns and habits. It keeps an eye out for emails that don’t seem quite right, such as a particular sender reaching out unexpectedly. If an email is identified as unusual, actions can be applied to that message as mentioned above.

Safety tips

Safety tips are small grey notification boxes at the top of certain emails, giving users a heads-up with messages like “You don’t often get emails from this sender”. These warnings help highlight first-time contacts or possible impersonation attempts.

Screenshot of an email showing a first contact safety tip prepended to the message body.

Phishing thresholds

Lastly, Phishing Thresholds are adjustable settings that let administrators control how aggressively Microsoft 365 looks for phishing emails. This threshold ranges from 1 (standard) to 4 (most aggressive). Increasing the threshold means the system will become stricter when inspecting emails, and will take more serious action at lower levels of suspicion.

Finding the loopholes

Having understood both the generic email security controls (SPF/DKIM/DMARC) and proprietary Microsoft controls, we have a rough idea of what we’re up against. The next step is to start sending some probing emails to understand which controls kick in under which circumstances.

To do this, I set up a “victim” organisation with a Microsoft tenant called TantoTesting. I wanted to build an environment that was intentionally highly secure, to see if I could still break through its email defences. I configured a wide range of protections, including external email tagging, impersonation protection, spoofing detection, safety tips, and set the phishing threshold to its most aggressive level. If spoofing worked against this tenant, I could expect it to work in most situations.

Given my hardened TantoTesting receiving organisation, I created two users. John Doe would act as my unsuspecting recipient, and James Bond would be the user I would try to impersonate. That is to say, as a totally external user, I would try to deliver email to John Doe that appear to have come from James Bond.

To make things interesting and add to the hardening of TantoTesting, I enrolled James Bond within impersonation protection.

A diagram showing the mail flow. James Bond and John Doe are on one side of a dotted line. A person is on the other side of the dotted line wearing a James Bond mask. They are sending an email to John Doe.

It’s important to highlight that John Doe and James Bond are both victims in this case, just in different ways. John Doe, as the recipient, is the direct target of the phishing email and the person whose trust is exploited. Meanwhile, James Bond is the impersonation victim: his identity is being faked in an attempt to deceive John.

I planned to send email from the domain name tantomail.com, but in such a way that it would appear to have come from James Bond. This was a domain name that was under my control, and so I configured SPF and DMARC to give it a good baseline posture for sending email. I ended up sending email directly from a residential IP address (ensuring it aligned with the SPF posture for my domain name) which seemed to satisfy any baseline IP address based checks done by Microsoft.

As I worked through Microsoft’s layered email defences, my goals evolved. Rather than starting with a static checklist, I built it step-by-step, adding new requirements each time I ran into another obstacle.

Throughout the rest of this post, I’ll iterate on this checklist as we go to reflect the journey I took.

It starts off quite simply:

Success Checklist

  • Deliver email to John Doe’s inbox

Baseline

Before jumping into any advanced techniques, it’s important to start with a non-malicious control email to understand how Microsoft’s protections behave under normal circumstances. To establish this baseline, I sent a plain email from my external test domain to John Doe. The goal was to confirm that a standard message, with no spoofing tricks or suspicious content, would be delivered to the inbox and to observe which security features Microsoft applied.

The email landed in John’s inbox with some expected security signals: an external sender tag appeared at the top, Outlook added a safety tip warning about the unfamiliar sender, and the From address was displayed plainly and accurately, containing my own domain name.

Screenshot of the baseline email with external tags, safety tips and a plain email address.

Success Checklist

  • Deliver email to John Doe’s inbox
  • NEW: Avoid the external sender tag
  • NEW: Avoid safety tips and banners

Blocked display names

I tried adding a display name “James Bond” to help improve the look of the email, while retaining my own email address. Outlook immediately flagged the email because James Bond was enrolled within impersonation protection. The email went straight to the junk mailbox, an impersonation safety tip was added in a grey box, and I was still slapped with an external sender tag.

Screenshot of the flagged email with impersonation safety tip.

Success Checklist

  • Deliver email to John Doe’s inbox
  • Avoid the external sender tag
  • Avoid safety tips and banners
  • NEW: Avoid impersonation protection

RFC and external email tagging

Believing that Outlook primarily analyses the header from address to detect impersonation, I decided to dive deeper into the RFC standards to see if there were other SMTP headers that Outlook might overlook, specifically headers related to email origination.

One of these headers stood out. RFC 2822 describes the Sender header as “the mailbox of the agent responsible for the transmission of the message”. It’s essentially used to identify a person that sends an email on behalf of its actual author, such as when assistants send emails on behalf of executives.

Outlook has a quirky way of handling emails containing the Sender header. When this header is present, Outlook displays origination information in a unique format: the Sender address “on behalf of” the From address. For example, if “Michael Jones” is the sender and “John Doe” is the who the email is from, Outlook will show the email originated from “Michael Jones on behalf of John Doe”. Interestingly, Outlook doesn’t validate the contents of the Sender header, allowing an attacker to use any domain or display name they want. The example below demonstrates this by setting the Sender header to James Bond <james.bond@legit.com>

Screenshot of email with sender header containing arbitrary domain and display name.

The apparent absence of Sender header validation made me question what would happen if I provided an internal email address in this header. Doing so resulted in an email which bypassed external email tagging, appearing as if it was sent internally. Hovering over the address supplied in the Sender header even rendered the corporate profile of the user corresponding to that address.

Screenshot of email with sender header containing internal address bypassing external email tagging.

Not Fixed

This technique still works at the time of writing this post

Sadly, we still have the grey safety tip due to the user rarely receiving mail from the email’s From address. Furthermore, the whole “on behalf of thing” with two email addresses looks a bit awkward and may raise suspicion from the recipient.

Success Checklist

Success Checklist

  • Deliver email to John Doe’s inbox
  • Avoid the external sender tag
  • Avoid safety tips and banners
  • Avoid impersonation protection
  • NEW: Avoid “on behalf of” authorship designation

Circumventing safety tips

Despite bypassing external email tagging, Outlook still inserts safety tips into the body of emails. From what I’ve observed, Outlook inserts these safety tips server-side during mail delivery, based on policies set in the admin centre. This means the warning is already baked into the email by the time it hits the user’s inbox.

Analysing the HTML source of an email containing a safety tip shows that the tips are encapsulated in an HTML table which is prepended to the message body. The user content is displayed underneath this table inside an HTML div.

<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body>

    <!-- The safety tip -->
    <table border="0" cellspacing="0" cellpadding="0" width="100%" style="display:table" align="left">
        <tbody style="display: block;">
            <tr>
                <td valign="middle" width="1px" bgcolor="#A6A6A6" cellpadding="7px 2px 7px 2px">
                </td>
                <td valign="middle" width="100%" bgcolor="#EAEAEA" cellpadding="7px 5px 7px 15px" color="#212121">
                    <div>
                        You don't often get email from james.bond@tantomail.com.
                        <a href="https://aka.ms/LearnAboutSenderIdentification">Learn why this is important</a>
                    </div>
                </td>
                <td valign="middle" align="left" width="75px" bgcolor="#EAEAEA" cellpadding="7px 5px 7px 5px" color="#212121">
                </td>
            </tr>
        </tbody>
    </table>

    <!-- The original email contents -->
    <div>
        <p>Hello John,</p>
        <p>Can you please send me the company card details so I can renew our contracts for this year.</p>
        <p>Thanks,</p>
        <p>James</p>
    </div>
</body>

</html>

Note

HTML comments in the above code snippet are my own

When examining the HTML source, I noticed that the tr element (table row) which contained the safety tip did not have any inline styling applied. This gave me an opening. I could inject a simple CSS rule within my message that targets all tr elements, including those holding the safety tips, hiding them from view.

<style>
    tr {display: none; }
</style>

Fixed

This technique no longer works

It’s worth noting that this method hides every table row in the email, so if your email content also uses tables, those could disappear as well.

I reported this trick as part of a broad submission to Microsoft. Whether as a result of my submission, or simply in a case of serendipitous timing, Microsoft quietly patched it in a rather amusing way. Within the tr element containing the safety tip, they added an inline style with revert !important for every single style attribute. This tells the browser, with the highest priority, to ignore any custom styles and to use the default or inherited value. By applying it to every property, Microsoft ensured that any attempt to re-style a safety tip would fail.

<tr
    style="aspect-ratio: revert !important;
           background: revert !important;
           block-size: revert !important;
           ... [43 more declarations]"
> ... [Safety tip here]

This fix meant that direct CSS manipulation was off the table, sending me back to the drawing board. If I couldn’t hide the safety tip after it was inserted, maybe I could prevent Outlook from inserting it in the first place? This got me thinking about end-to-end encryption. Perhaps, if the email content appeared to be encrypted, Outlook wouldn’t be willing to modify it to inject the safety tips.

PGP encryption

There are two main standards for email encryption: PGP (Pretty Good Privacy) and S/MIME. For simplicity and ease of experimentation, I decided to focus on PGP, specifically the older “inline PGP” method. Inline PGP works by placing the encrypted message block directly within the email body as plain text, marked by a standard header and footer:

From: <jane@gmail.com>
To: <john@outlook.com>
Subject: Hello
Content-Type: text/plain

----- BEGIN PGP MESSAGE -----
[ENCRYPTED CONTENT]
----- END PGP MESSAGE -----

Looking at this structure gave me another idea. The Content-Type is still just text/plain. The PGP block itself is just text. Does the content between the PGP header and footer markers actually have to be an encrypted payload for Outlook to recognize it as a “PGP message”? Or would Outlook simply detect the presence of the markers themselves and decide not to tamper with the content within, assuming it’s encrypted?

It turns out, that’s exactly what happens. By including an abbreviated PGP header:

BEGIN PGP MESSAGE

inside the content of an email, Outlook believes the email is encrypted and doesn’t insert safety tips.

Screenshot of email with PGP header bypassing safety tip insertion.

Not Fixed

This technique still works at the time of writing this post

This even worked with HTML emails. This allowed me to hide the PGP header within an HTML comment, making it completely invisible to the user.

Success Checklist

  • Deliver email to John Doe’s inbox
  • Avoid the external sender tag
  • Avoid safety tips and banners
  • Avoid impersonation protection
  • Avoid “on behalf of” authorship designation

From: header funkiness

At this point, I had bypassed external tags and safety tips; however, there was a lingering awkwardness to the emails I was sending. The email origination information still showed my external address (james.bond@tantomail.com) in that “<sender> on behalf of <from>” format.

Screenshot of email showing state of emails with current bypasses applied.

Furthermore, the photo next to the sender name is not that of James Bond. Ideally, we’d clean up the “on behalf of” authorship information and make sure Mr. Bond’s profile picture was used.

Success Checklist

  • Deliver email to John Doe’s inbox
  • Avoid the external sender tag
  • Avoid safety tips and banners
  • Avoid impersonation protection
  • Avoid “on behalf of” authorship designation
  • Show James Bond’s profile photo

I decided to investigate the header from address to better understand how Outlook chooses what origination information is shown to the user.

I came across a presentation from BlackHat USA 2020 (“You have no idea who sent that email: 18 Attacks on Email Sender Authentication”, slides, recording). It outlined the complicated syntax of From headers, and discussed the fact that each that MUA has its own approach when parsing this syntax.

The header from address can contain a mix of display names, comments, routing info, and multiple addresses, all separated by specific punctuation.

             /------------------ comments ------------------\
            /-------\                                /-------\
From: James (a@a.com) Bond <@b.com, @c.com: d@d.com> (e@e.com)
      \---/           \--/  \--- Route --/  \-----/
       \- Display Name -/                   Address

Every email client interprets these components a bit differently, which can lead to some weird and inconsistent results, especially if you’re creative with the syntax. Some clients may even parse them in such a way that it displays a sender email address that wasn’t verified by SPF/DMARC/DKIM or other security controls along the email’s journey.

Consider the following email, being sent through Gmail:

HELO gmail.com
MAIL FROM: <attacker@gmail.com>
RCPT TO: <john@outlook.com>
DATA
From: <spoofed@gmail.com><attacker@gmail.com>
To: <john@outlook.com>
Subject: Hello

Hello, John!
.

Note

The use of two addresses in the header from without a comma separator is outside the specification RFC 2822

In my testing, Gmail will verify that the account given by the envelope from address (attacker@gmail.com) belongs to the user who is logged in over SMTP. It will then check that the last address in the header from field matches the envelope from address. If these conditions are satisfied, the email is sent.

Upon receiving the email, Outlook will conduct SPF, DKIM and DMARC checks on the sender’s domain. From what I observed, Outlook seems to rely on the first address in the header from address (spoofed@gmail.com). This means that, because Gmail cares about the last address (for user authorisation purposes), and because Outlook cares about the first address (for SPF/DKIM/DMARC) purposes, we’re locked in to using the domain gmail.com for both addresses in this Gmail-to-Outlook case.

It doesn’t stop there, though. Outlook will also use the first address in the UI, making it appear as though the email was sent from an alternative Gmail address to that which was actually used.

Screenshot of an email from spoofed address spoofed@gmail.com.

Fixed

This technique no longer works

This doesn’t help us with our James Bond / John Doe story. It’s still a powerful trick in its own right, and it set me on the right track to crack the specific challenge I had set for myself.

The final “spoof”

Having learned that the originator information in the From header is liable to be misinterpreted by MUAs, I returned to the challenge of cleaning up the “<sender> on behalf of <from>” mess in our James Bond email spoofing.

I revisited RFC articles for more information, specifically RFC 822. This RFC described that any standard ASCII character can be placed inside SMTP headers and listed special characters which control certain syntax.

  • Email addresses should be placed within <angle brackets>
  • Multiple addresses should be separated by ,
  • Groups are defined with : and terminated with ;
  • Display names should be placed within "quotes"

This gave me an idea. What would happen if I added an empty address <> or list of empty addresses <,> before the attacker’s address?

From: "Test" <,><james.bond@tantomail.com>`

I can’t place a valid address before the attacker’s address as this would result in SPF, DKIM and DMARC checks failing, but maybe an invalid address would influence what Outlook displays to the client without impacting these checks. This proved correct as sending an email with this syntax resulted in Outlook only showing the display name (“Test”), while hiding the attacker’s address (james.bond@tantomail.com) from view.

Screenshot of an email using empty addresses to hide the attacker’s address.

At the same time I also began experimenting with ASCII control characters. These are non-printable characters designed to control hardware devices, and when placed in email headers are either rendered as an empty rectangle (â–¯) or are hidden. I placed these characters inside the display name to see how they would appear when viewed in Outlook, as shown below with the unit separator character \x1f.

From: "Te\x1fst" <james.bond@tantomail.com>

When the email arrived, this control character was hidden in both Outlook web and desktop applications, undetectable to the recipient.

Screenshot of an email with an invisible control character inserted in the display name.

I assumed that if the display name consisted solely of such a hidden character, then the display name would be omitted, just like how the email address was omitted if the first email address was a list of empty addresses (<,>).

Now, what would happen if I combined these tricks, and added a Sender header back in. With the originator information in the From header being potentially entirely undisplayable, what would Outlook choose to show?

To test this theory I constructed an email with the headers shown below.

From: \x1f <,><james.bond@tantomail.com>
Sender: James Bond <james.bond@tantotesting.onmicrosoft.com>

With Outlook not wanting to show any of the information inside the From header, I theorised that Outlook could only show the information inside the unverified Sender header.

The end result? The email arrived in the inbox looking as if it had come directly from James Bond’s internal address. The attacker’s domain was hidden, there were no external tags or safety tips, and even the correct profile picture appeared. All the usual visual clues were stripped away. To any recipient, this message would look completely legitimate.

Screenshot of an email with all spoofing techniques applied.

As this form of spoofing only visually changes what the recipient sees, it also bypassed several third-party email security solutions that I tested.

Success Checklist

  • Deliver email to John Doe’s inbox
  • Avoid the external sender tag
  • Avoid safety tips and banners
  • Avoid impersonation protection
  • Avoid “on behalf of” authorship designation
  • Show James Bond’s profile photo

Fixed

This technique no longer works

Bonus mischief

Along the way, I stumbled upon a few bonus techniques worth mentioning. These little extras can help make phishing campaigns even more convincing or, at the very least, more interesting for red teamers.

Fake recipients

Only addresses specified in the RCPT TO SMTP command will actually receive the email. By adding addresses to the To header, but not including them as recipients, you can make it appear as though the message was sent to multiple people, even if some were destined to never get the message. This can add a sense of urgency or social pressure, or just make the email seem more normal. In the example below, Jane Smith has been added as a fake recipient.

Screenshot of an email with fake recipient.

Reply-To redirection

By setting a different address in the Reply-To header of an email, you can control where any replies are sent. For example, an email might look like it’s from James Bond, but if the recipient clicks “Reply” their response will go to the address you specified in the Reply-To field. This technique can be useful to see which recipients respond to phishing emails, and whether they notice the unusual reply address before sending.

Spoofed meeting invites

Calendar invites are just as easy to manipulate. By editing the headers in an ICS file, you can make it look as though the meeting is organised by someone else, or add fake attendees. You can even suppress RSVP notifications so your impersonation target isn’t alerted about meetings they didn’t organise. This can be especially effective in today’s workplaces, where online meetings are a regular part of daily routines.

Screenshot of a spoofed meeting invite.

Anonymous sender

If you both strip out the Sender header, and cause the originator information in the From header to become entirely unprintable, Outlook is left with nothing to display. This creates a mysterious senderless email, perfect for pranks, or just to see how your target reacts to an email from nowhere.

Screenshot of an email with an anonymous sender.

Final thoughts

After wrapping up this research, I disclosed my findings to Microsoft. Their response? “This case does not meet MSRC’s current bar for immediate servicing”. Microsoft ended up fixing some of the techniques in the weeks following my presentation at BSides Canberra in 2024. I’ve done my best to note which techniques still work, and which ones do not, as of the time of publishing this post.

My journey showed to me ways in which email’s legacy design, and inconsistent parsing between clients, still leaves room for creative attacks against modern email systems and clients.

I have some fresh email techniques in the works that I’ll be revealing soon, so watch this space!