Using Office 365 to Protect Your Email

exchange-2014No doubt everyone reading this is familiar with spoofed email. Where an attacker crafts a message to appear as though it comes from a legitimate sender, in the hopes the recipient will reveal personal information or part with their hard earned cash.

With the rise in so called ‘spear phishing’, being able to effectively block spoofed email is no longer just desireable, it is critical.

Also bear in mind that whilst technologies like Sender ID and DKIM exist, they require both parties of an email to be using them for them to be effective.

You may think any domain you have moved to Office 365 recently is automatically protected by Exchange Online Protection however, like previous versions of Exchange, SenderID checking is disabled by default, as are advanced spam filtering and malware protection.

The defaults are reasonable, however you can and probably should, update them to better protect your environment.

For this post I will be posing as an attacker and as a victim using two of my own domains.

  • I registered a domain, setup Sender ID for outgoing emails.
  • Configured a PC with Outlook to use the IMAP account settings provided. Using the victims email address and my attackers account details.
  • My victim is setup as the accounts department for a fictitious domain I also own.
  • Starting with default Office 365 Security Settings
    The usual spear phish you may have seen involves a little bit of inside knowledge of the company. This can be found anywhere online with a little searching but good sources are LinkedIn or other social media. Even publically available companies house records, anything!

In this scenario the attacker knows The Boss’s details, and the Mrs Accounts Lady’s email address.


As you can see, this email has waltzed straight into our victims mailbox, and appears to come from The Boss.

We hit reply, and don’t notice the email is going to the attacker. not The Boss.


So how did this email get through?

We have not set an SPF record listing sources of legitimate mail.

We can add in an SPF record, which Microsoft provide detailed instructions for, and in some cases can connect to your DNS provider to configure for you.

"v=spf1 -all"

In actual fact Microsoft lists an SPF as a requirement for successful setup of the service, however not having one, does not prevent you from using the service.

So now our attacker replies, but the message still comes in.

taking piss

Despite the headers of the message now showing the SPF Check has failed.

Received: from
 (2a01:111:f400:7e01::207) by
 (2603:10a6:203:3d::28) with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.991.14 via
 Frontend Transport; Thu, 23 Mar 2017 16:19:17 +0000
Authentication-Results: spf=fail (sender IP is;; dkim=none (message not signed)
 header.d=none;; dmarc=none action=none;
Received-SPF: Fail ( domain of does not
 designate as permitted sender)


Our victim needs to enable checking SenderID on incoming messages.

Using Exchange Online PowerShell, we can do that quite easily.

We create two items, a policy and a rule.

New-HostedContentFilterPolicy -Name "Company Anti Spam Policy" -MarkAsSpamSpfRecordHardFail On
New-HostedContentFilterRule -Name "Company Anti Spam Rule" -HostedContentFilterPolicy "Company Anti Spam Policy" -enabled $true -RecipientDomainIs

Our attackers emails are now sent straight to junk mail. Partial Success.


Using a Transport Rule we can take action on these emails before they reach the spam filter.

We know that a message that fails SenderID will be set with a header like this, “Authentication-Results: spf=fail” so we can create a rule that looks for that header value.

New-TransportRule "Company Anti Spam Transport Rule" -RecipientDomainIs -FromAddressMatchesPatterns "" -HeaderMatchesMessageHeader "Authentication-Results" -HeaderMatchesPatterns "spf=fail" -RejectMessageReasonText "Sender ID Fail"

This transport rule now applies to any mail that fails SPF, for your own domain name, and rejects the message.

You might decide you don’t want to reject it, you want to quarantine, or maybe just silently delete it.

That would depend on your organisations preferences for false negatives/positives, there are some legitimate reasons mail could fail authentication, my fictitious organisation has a zero tolerance approach to this, you of course may be more liberal.

The problem here is that SPF is vulnerable to an exploit whereby the SenderID mechanism only checks the 5321.MailFrom header, it skips the 5322.From header, as explained expertly in this blog post..

Using a script or similar technique an attacker can still get his email delivered, and still appear to be from The Boss.

Authentication-Results: spf=pass (sender IP is
Received-SPF: Pass ( domain of designates as permitted sender

Office 365 has done some work here in it’s default settings to try to combat this by warning the recipient that an email may be fraudulent, however the message would still be delivered to the recipient. We can take our own steps to combat this vulnerability.


Using a technology known as DMARC we can enable ‘strict SPF checking‘ whereby both the 5321 and 5322 headers must be from the same domain.

A DMARC record is similar to an SPF record, in that it is a TXT record in DNS but, it specifies actions for what to do if the SPF check fails, in addition it supports DKIM, reporting and a few other things.

There are wizards online that can assist you creating a DMARC record, and I published my own mini introduction to DMARC a while back.

Using the resources highlighted I can create a new DMARC record for my victim domain. The below record says any email failing SPF should be quarantined.

v=DMARC1; p=quarantine;;; fo=1; aspf=s;
Authentication-Results: spf=pass (sender IP is;; dkim=none (message not signed)
 header.d=none;; dmarc=fail action=quarantine;
Received-SPF: Pass ( domain of designates as permitted sender

Reading this link explains that whilst Office 365 implements DMARC checks, by default it treats ‘quarantine’ and ‘reject’ in the same way. That is, to mark the email as Junk, not move the it to the Hosted Quarantine, or Reject it as you might  expect.

To fix that we can implement two more Transport Rules.

We can use the same Header Value as our previous rule, but this time look for DMARC options using a Regular Expression, or REGEX.

(dmarc=fail action=\Sreject)
(dmarc=fail action=quarantine)
New-TransportRule "Company Anti Spam - DMARC Reject" -FromScope NotInOrganization -RecipientDomainIs -HeaderMatchesMessageHeader "Authentication-Results" -HeaderMatchesPatterns "(dmarc=fail action=\Sreject)" -DeleteMessage -StopRuleProcessing $true
New-TransportRule "Company Anti Spam - DMARC Quarantine" -FromScope NotInOrganization -RecipientDomainIs -HeaderMatchesMessageHeader "Authentication-Results" -HeaderMatchesPatterns "(dmarc=fail action=quarantine)" -Quarantine $true  -StopRuleProcessing $true

This is another good resource on DMARC and Office 365 and explains some instances where the ‘reject’ value may be modified to ‘o.reject’ or ‘oreject’ and if you have implemented the PCT feature of DMARC where the action is applied only to a percentage of your email.

Our reject rule would override the override from Office 365 and reject a message, but our quarantine rule would respect a PCT for an action of quarantine.

As you can see from these tests when we switch the DMARC value between Reject and Quarantine, our rules are taking the correct action to protect us.


This will not only protect your organisation from Spoofing against your own domain name, but also protect you from other domains that may be spoofed.

In some situations legitimate email may be sent from locations that are not authenticated. These are usually sighted as mailing lists or external partners.

I have some clients who run daily newsletters, the emails for those report to come from the clients domain, but actually are sent from an external service. SPF records can be updated to support multiple senders (with some limitations) and more frequently now sending services like SendGrid or Dotmailer will allow, or even recommend the use of DKIM. By adding DMARC on top of SPF and DKIM we can be sure that recipients know how to correctly handle mail that comes from unauthenticated sources.

However attackers are now wise to these authentication techniques, so more often they don’t spoof real domain names anymore. They create similar domains that at a quick glance look the same, or at least related.

For example a recent example of one I encountered was for sage[-]pay[.]org[.]uk which was a real, legitimate domain with SenderID correctly configured.

The email came straight into my clients mailbox. Luckily they sent it on to me rather than opening the OneDrive link that came with it.


Another client was targeted where an attacker registered a domain with a single character substituted (a 0 instead of an o), they too had gone to some trouble to attempt their attack by setting up SenderID, but they also sent this email to a third party. So the attacker spoofed my client, to spear phish a third party. You have to admire the creativity.

What can we do abut that? Well one approach is to purchase and control every domain name iteration you think an attacker might try to use. Apart from being wildly inefficient, it would also get expensive. We can however try something else.

From his research our attacker knows who Mr Boss is, and that spoofed email wont come in, he really wants that $500,000 transfer so he registers a similar domain name, and the ruse continues.

spoof 2

Luckily we can use a REGEX to try and catch this attempt as well.

This is a great resource for testing out your REGEXs before putting them into use.

The idea being to create a regex that will be broad enough to skip legitimate email and targeted to just variations on the domain names you own and the characters that might be replaced.

For my domain, both the 3 and the 8 could be switched to a B or the 3 and the 8 could change position.

This REGEX excludes our actual domain name, using something called a ‘Negative Look ahead’ then looks for a string of characters that starts with a y and contains a B, a 3 or an 8. in the next two characters, with a wildcard at the end.


Unfortunately Office 365 Transport Rules do not allow the use of wildcard characters.

So, borrowing some creative thinking from everyone’s favourite Pop Star Infosec Expert, we can use a ‘not white space’ selector in the expression.

$regex = "(?![38Bb]{2}\S{0,})"
New-TransportRule "Company Anti Spam Regex" -FromScope NotInOrganization -RecipientDomainIs -HeaderMatchesMessageHeader "From" -HeaderMatchesPatterns $regex -SenderAddressLocation HeaderOrEnvelope -DeleteMessage $true -StopRuleProcessing $true

We can now prevent many variations of our victim domain name from sending us emails, this rule will silently drop any message where the sender address matches. Again depending on your environment you may choose to quarantine them or reject with an explanation.

I also mentioned sage[-]pay[.]org[.]uk, this one is more tricky to catch.

Essentially the email was not a fake. As far as email goes, this message is fully authenticated, with no reason to reject or quarantine. It just contains fraudulent information.

The solution, I believed also lied in using a REGEX. Being quite new to REGEX, I wasn’t sure how to create one that would reliably gather multiple search terms, whilst only matching if more than one term was present and then taking into account the nuances with how Exchange handles REGEX in Transport Rules.

After two days of playing around I decided to take a different approach.

Looking at the phrasing of the email, it is easy to pick one or two keywords, like payment or remittance, but given they are general business terms I also wanted to be able to only apply an action if an email also contained a shortened URL.


I decided the best approach might be a multi rule sequence with the idea being. in our first rule, we can check for some keywords, if any are present we can set a custom header value. In our next rule we can search for the presence of a shortened URL and the custom header value. If both the header and a shortened URL are present in the email our rule can then take action.

$regex1 = "[pP]ayment|[iI]nvoice|[rR]emittance"
$regex2 = "|"
$header = "X-Exchange-Organization-KW"
New-TransportRule "Company Anti Spam - Keyword 1" -FromScope NotInOrganization -RecipientDomainIs -SubjectOrBodyMatchesPatterns $regex1 -SetHeaderName $header -SetHeaderValue "1"
New-TransportRule "Company Anti Spam - Keyword 2" -FromScope NotInOrganization -RecipientDomainIs -SubjectOrBodyMatchesPatterns $regex2  -HeaderMatchesMessageHeader $header -HeaderMatchesPattern "2" -SetSCL 9

Using this method I was able to successfully identify this example and move it to junk mail.

However I realised that the company I work for uses links in our email signature for tracking clicks to social media, so emailing a client to ask about an invoice or a payment having employed this rule set on the clients tenant would result in our own email being marked as junk.

Which would not make me very popular in the accounts department.

So I spent some more time thinking about it, and decided that I would tweak the REGEX to apply only to images pulled from links on 1drv or


New-TransportRule "Company Anti Spam - Keyword 2" -FromScope NotInOrganization -RecipientDomainIs -SubjectOrBodyMatchesPatterns $regex2 -SetHeaderName $header -SetHeaderValue "2"
New-TransportRule "Company Anti Spam - Keyword 3" -FromScope NotInOrganization -RecipientDomainIs -RecipientAddressMatchesPatterns $regex3 -HeaderMatchesMessageHeader $header -HeaderMatchesPattern "2" -SetSCL 9

This exercise demonstrates the difficulty and perhaps futility in trying to pre-emptively catch Phishing emails through a few simple transport rules, obviously if it were that easy we would have eradicated spam and phishing already.

Having said that, I think that being able to look for keywords in emails and acting on them is definitely a worthwhile pursuit, even if it is simply to monitor the emails coming into your organisation.

I mentioned SwiftOnSecurity earlier, and she has very kindly shared her list of REGEXs she has put together to catch a number of popular phrases employed in phishing, she has hinted on tweets she uses them only to catch Phishing with incident reports, so it can be reported, rather than to actively block them.

An incident report s an action that you can take when a message matches criteria you set in a rule. Office 365 then sends information about that email to a designated account.

The information you receive in the report can be as detailed as you want, and it can even include the original email.


Incident Report

With that in mind I would recommend her page which links you quickly to many services where you can report phishing emails and websites, and it really does work!

In addition to this rule, we can add a rule that blocks any domain we catch sending Phishing emails.

New-TransportRule "Company Anti Spam - Block Domains" -FromScope NotInOrganization -SenderDomainIs "" -DeleteMessage $true

Then later if we want to add additional domains to block:

$domains = (Get-TransportRule "Company Anti Spam - Block Domains").SenderDomainIs
Set-TransportRule "Company Anti Spam - Block Domains" -SenderDomainIs $domains

So far we have looked at SenderID, DMARC and Phishing. How about everyone’s favourite, the attachment?

Blocking attachments with executable content is a very effective way to block a large number of attacks, and is as easy as running this command.

New-TransportRule "Company Anti Spam - Executable Content" -FromScope NotInOrganization -RecipientDomainIs -AttachmentHasExecutableContent $true -RejectMessageEnhancedStatusCode 5.7.1 -RejectMessageReasonText "Executeable Content"

In addition to that we can look at the Office 365 Malware Filter. There is a default rule, however the attachment filter is disabled in that.

We can create a new policy that enables the attachment filter with two commands.

New-MalwareFilterPolicy -Name "Company Anti Malware Policy" -Action DeleteMessage -EnableFileFilter $true
New-MalwareFilterRule -Name "Company Anti Malware Rule" -RecipientDomainIs -MalwareFilterPolicy "Company Anti Malware Policy"

The default filetype filter includes these extensions.


If you want to add some additional file extensions, you can do that like this:

$files = (Get-MalwareFilterPolicy "Company Malware Filter Policy").FileTypes
Set-MalwareFilterPolicy "Company Malware Filter Policy" -FileTypes $files

In that example we have added the WSH file extension to our attachment filter list.

If you want to add multiple file types at once:

$files += ("wsh","wsf","zip","xlsm")

Lastly I wanted to talk about DKIM.

DKIM is another technology that people generally have been slow to adopt (myself included), I felt SPF was good enough and when you also consider that Exchange 2010 (and SBS 2011) were unable to use it natively we were in no rush to adopt it.

I now believe that approach is flawed, and I think we as MSPs, Consultants, or Engineers should do everything we can do to allow our sent messages to be authenticated.

DKIM, is actually relatively straight forward to setup, although the advice and best practices I have seen suggest you revisit it periodically and update your keys.

First we create two DNS CNAME Records for our domain.

This step applies to Office 365 Environments only, other providers will have different setup instructions, for example GMAIL uses TXT records to publish the DKIM Key.;

Then using the Exchange Shell we can Enable DKIM for our Domain.

New-DKIMSigningConfig -DomainName -enabled $true

Now when we send a message from that domain it will be signed.

I mentioned above about rotating your keys, which is a method of maintaining integrity in your signed messages.

Microsoft is now managing that for you as explained in this blog post, whereas with other providers you would need to manually update DNS with your new keys.

Once we have our DKIM enabled, we can revisit our DMARC record and update the DKIM section from relaxed, to strict.

v=DMARC1; p=reject;;; fo=0; adkim=s; aspf=s; pct=100; rf=afrf; ri=86400; sp=none


Hopefully I have highlighted some things you can do to increase security and deliverability of your clients emails. Id love to hear what else you are doing!

About Robert Pearman
Robert Pearman is a UK based Small Business Server enthusiast. He has been working within the SMB IT Industry for what feels like forever. Robert likes Piña colada and taking walks in the rain, on occasion he also enjoys writing about Small Business Technology like Windows Server Essentials or more recently writing PowerShell Scripts. If you're in trouble, and you can find him, maybe you can ask him a question.

3 Responses to Using Office 365 to Protect Your Email

  1. amybabinchak says:

    I have had some issue getting the DKIM keys to be seen properly by Microsoft. I’ve copied and pasted them as txt records. It fail. Not sure where to turn I gave up on it a few months back. Interested in any suggestion for what might have gone wrong.

Leave a reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: