Office 365 Mail Forwarding Rules (and other Mail Rules too)
If you haven't heard, SANS suffered a "Data Incident" this summer, the disclosure was released on August 11. Details can be found in several locations:
This is well written up in several places:
https://www.sans.org/dataincident2020
IOC's discussed here:
https://www.sans.org/blog/sans-data-incident-2020-indicators-of-compromise/
Webcast is available in two places:
https://www.sans.org/webcasts/116375
https://www.youtube.com/watch?v=KZ3gcFe4_rE
This breach didn't affect me adversely, if my information was affected the disclosed information all falls into the category of information I advertise - - it's all on my website or in LinkedIn. But this did get me to thinking about other corporate networks where more sensitive customer information is routinely emailed around. An email forwarding rule in Office 365 could be a "forever data breach" in a situation link that - whether the rule was planted by an attacker or (mis)configured by an end-user, the results could be catastrophic. Whether it results in a breach of customer data, disclosure of intellectual property, or just a down-tick in a PCI audit - an email rule in the wrong place and at the wrong time can have a severe business impact.
So that being said, how can we look for these things if you have hundreds, thousands or tens-of-thousands of mailboxes to consider? In an Office 365 shop, and especially if I wrote the code, the answer is most likely going to be PowerShell!
Before we start, you'll need the msonline module:
install-module msonline |
A basic "get connected" script might look like this:
Import-Module MSOnline |
Getting the list of mailboxes (so you have something to loop through) is as simple as "get-mailbox"
$mailboxnames = get-mailbox | select name |
To get rules on a mailbox, "get-inboxrule" does the job:
Get-InboxRule -Mailbox "rob@coherentsecurity.com" |
Often we're looking for "RedirectTo" or "ForwardTo" rules, but at this point your script may start to differ from mine, you might be looking for different types of rules. All the parameters that make up each rule are in fields, so it's easy to search and match on exactly what you are looking for. Normally I pull all configured rules, but I include the "redirectto" and "forwardto" fields so I can separate those out easily, usually in Excel.
If you are looking for other rule types, there are quite a few flags to help you sort / extract what you are looking for - this will give you the list of possibilities (the output of this command is edited to show only fields you might want to search/match on in your hunt for malicious rules):
Get-InboxRule -Mailbox "rob@coherentsecurity.com" | get-member Name MemberType Definition |
However, once you have a match on whatever it is that you are looking for, the "Description" field is what you likely want in your report - that spells out in plain language what the rule is.
My regular script usually looks something like this:
# prep variables $RuleList = @() $timestamp = get-date -format "yyyy-MM-dd-HH-mm"
#See if the MSOnline Module is installed or not if (Get-Module -ListAvailable -Name MSOnline) { # no action, module is installed } else { # note "install-module" requires local admin rights install-module MSOnline }
# import module and connect Import-Module MSOnline # collect credentials for an organization's O365 Administrator account $O365Cred = Get-Credential # Connect up to your org's instance $O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $O365Cred -Authentication Basic -AllowRedirection Import-PSSession $O365Session Connect-MsolService –Credential $O365Cred
# collect all mailboxes in the enterprise $mailboxes = get-mailbox
# Loop Through all mailboxes, check for rules # note that will all the mailbox metadata, you can hunt for lots of other things too ....
foreach ($mb in $mailboxes) { # main email for the mailboxes $email = $mb.PrimarySmtpAddress # is this a valid user-user? if($mb.WindowsLiveID.length -ne 0) { $rules = get-inboxrule -mailbox $email if (($rules | measure-object).count) { foreach( $r in $rules) { $tempval = [pscustomobject]@{ UserName = $email RuleName = $r.name RuleEnabled = $r.Enabled CopytoFolder = $r.CopyToFolder MovetoFolder = $r.MoveToFolder RedirectTo = $r.RedirectTo ForwardTo = $r.ForwardTo TextDescription = $r.Description } $RuleList += $tempval } } } } # display results on screen, also save to a CSV with time/datestamp $RuleList | out-Gridview $filename = ".\MailRules-" + $timestamp + ".csv" $RuleList | export-CSV $filename
|
The output (for just my mailbox, with one test rule) is shown below. In a more traditional organization it'll of course be much larger, with both more users and more rules.
This script applies to server rules only. If your user has checked the "run on this machine only" tick box when building the rule, or has created a rule that will only run inside of outlook (for instance, has selected "play a sound" or something else that will only run locally), then those rules are stored in Outlook and will not show up when you sweep your O365 instance for server-side rules.
Also, keep in mind that not all mail rules are malicious - often they can automate time-eating manual processes for a nice productivity boost. It'd be my opinion though that you at least want to evaluate the rules in your organization, especially forwarding rules, and especially if those rules forward to email addresses outside of your domain.
If you decide to kick the tires on this script (or if you decide to improve on it), by all means use our comment section to let us know what you found!
====== Update ======
Our reader Peter notes that for systems that use MFA for administrators (which is what we should ALL be doing), the 'ConnectMSolService" command should be used instead of "Get-Credential". This will give you a modern login form rather than just userid/password entry.
So this:
Import-Module MSOnline $O365Cred = Get-Credential $O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $O365Cred -Authentication Basic -AllowRedirection Import-PSSession $O365Session Connect-MsolService –Credential $O365Cred |
Becomes something like this:
Import-Module MSOnline Connect-MSolService |
References:
https://docs.microsoft.com/en-us/microsoft-365/enterprise/connect-to-microsoft-365-powershell?view=o365-worldwide
(as described, note that you need .Net 3.5 installed for this to work)
===============
Rob VandenBrink
rob <at> coherentsecurity.com
Comments