Exchange

Is your Hybrid Exchange Server SAFE or unknowingly EXPOSED?

Hello and happy 2022! 🥳 I hope the year has started off as well as it possibly can for you (aside from the holiday ending a bit too early of course!)… 🍺😭 …right back to work!

Now, is your Exchange environment safe!!?? Really? Is it?

I love this utility called ‘SMTP Diag Tool’. It’s great for seeing whether you can connect directly to port 25 of an Exchange server. In most cases, if you can, you can send unauthenticated email to accepted domains within the organisation, because that’s how email used to work right?

SMTP Diag Tool

Before we had a mail filtering service in front of Exchange, email was sent directly between servers (in fact if Exchange was configured to use SpamHaus and SpamCop lookups, it did a pretty good job itself!). But I digress…

In many cases lately I have found I can connect directly to, and send unchecked email to Exchange servers, most often using ‘mail’ or ‘webmail’ hostnames. This method bypasses MX records, mail filtering services and also tells you probably have port 443 wide open as well. Clients are shocked – bypassing my mail filter – really? Yep! Here are the scenarios:

  1. You have a mail filtering service, but nobody set up the firewall or Exchange rules to restrict inbound email to the services sending IP Addresses (applies to on-premises and 365).
  2. You have a Hybrid Exchange configuration, some or all mailboxes are in the cloud but you still have port 25 and 443 open to your on-premises server.
  3. And a less serious case but a definite gap to plug – you are cloud only or hybrid, but have not configured rules to stop other tenants from emailing you directly (this would need to be a targeted attack, but I’m sure the attackers will automate the creation of that attack in future if not already).

To fix this there are several options; the more configured the better!

  1. The best step to take is restricting incoming traffic at the firewall. If you can’t use ‘Internet databases’ as firewall objects, throw away your firewall and get a suitable FortiGate model.
  2. Use the ‘Microsoft-Azure’ and ‘Microsoft-Outlook’ objects to restrict incoming (and outbound if you can) 25 traffic to Microsoft’s servers (if you are hybrid and using Defender mail filtering) OR by restricting to your mail filtering service’s IP range for port 25 (if you are on-premises, or routing through it).
  3. Use the Exchange Hybrid Agent! Re-run the wizard and choose the Agent option (you may need to install it manually first if running 2010). This allows you to close port 443 inbound entirely, by performing free / busy lookups and mailbox moves through an Azure App Proxy.
  4. For port 443, you can also use an Azure Application Proxy to act as a gateway to your environment if you are not Hybrid and it must be contactable from the internet (IMO Everyone should be using this for internet facing services – then you can close all inbound ports on your firewall and let Microsoft do the work!! (security team = ✅)
  5. If you do have inbound 443, use IIS with the URL Rewrite module to block access to any virtual directories that are not required (you’re not still using ActiveSync I hope!!?).
  6. You can also modify the Default Receive Connector in Exchange only to accept from a filtering service, or 365, but this is harder to maintain and shouldn’t be needed if the firewall is configured correctly.
  7. For the cloud-only and Hybrid scenarios, make sure you have implemented the Exchange rules to ensure only mail using your MX record will be delivered, ensuring it traverses the Mail Filtering protection of Exchange Online: Advanced Office 365 Routing: Locking Down Exchange On-Premises when MX points to Office 365 – Microsoft Tech Community.

I also recommend performing the following tasks to ensure maximum security for your environment, first focusing on Hybrid Exchange seeing as that is the most common scenario.

  • AD Connect – if it’s been around for a while, make sure it is now on a 2016/2019 server with TLS 1.2 enabled. You must have these OS to install the latest version. Also make sure it is configured for Hybrid Exchange while you are there.
  • Hopefully you are on Exchange 2016 (since that is free for Hybrid and 2019 is not), if not plan and get it done ASAP. Don’t use 2 vCPU and 8GB memory for your Exchange Hybrid server, what are we, skinflints? 4 vCPU and 16GB are recommended and should be easily achievable in any environment. If not then I cry for you… 😭😭
  • Use Azure Automation with Server Update Management to automatically patch your on-premises servers, even if you don’t have Azure yet this is worth enabling it for… WSUS – Yuuuuk! 🤮🤮

Until next time – chur chur from Simon!

Remove proxy address for specific domain from Exchange Distribution groups

This script can be run after connecting to Exchange Online or on-premises environment. Replace “porkchops.com” with the suffix you want to remove 👍

Thanks to me mate Sailesh who loooves his porkchops!! 🤣🤣

# Remove proxy address for "porkchops.com" from Exchange Distribution groups

$domainname = "porkchops.com"

$groups = Get-DistributionGroup -Resultsize unlimited | where {$_.EmailAddresses -like "*$domainname*"} 

foreach ($group in $groups) {  

    $groupidentity = $group.identity
    $addresstoremove = $group.Alias+"@$domainname"

    Set-DistributionGroup $groupidentity -EmailAddresses @{remove=$addresstoremove}
}

# End

Exchange Online – set default Retention Policy if null

# EDIT # I have updated this script due to an issue where multiple mailboxes are matched due to similar names, this line below with $mailboxes variable piped to the Set command uses Display Name for Identity which may not be unique. Script is updated to loop through the mailboxes using UPN for the Set command. Cheers! 🍺

$mailboxes | Set-Mailbox -RetentionPolicy $defaultpolicy.Name

I’ve come across several clients lately who are migrating to or have migrated to Exchange Online, and find some users have no retention policy set. This script can be scheduled in an Azure runbook to find enabled users with no policy and set it to the default policy. Replace ‘svc-runbookcred’ with your runbook credential name. Easily modified to connect to on premise Exchange; if you need any help just add a comment below! 🙂

# use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# specify runbook credential name
$runbookcredential = 'svc-runbookcred'

# get credential for eol connection
Try { 
    $CredAzure = Get-AutomationPSCredential -Name $runbookcredential
}
        Catch {
            Write-Error "Failed to get credential!"
            Exit
        }   
Write-Output "Get automation credential - Success"

# connect eol
Try {
    Connect-ExchangeOnline -Credential $CredAzure
}
        Catch {    
            Write-Error "Failed to connect to MSOnline!"
            Exit
        }
Write-Output "Connect to EOL - Success"

# get default policy from org settings
Try {
    $defaultpolicy = Get-RetentionPolicy | Where-Object { $_.IsDefault -eq $true }
}
        Catch {    
            Write-Error "Failed to get default policy!"
            Exit
        }
Write-Output "Get default policy - Success"

# find enabled mailboxes with no policy set
Try {
    $mailboxes = Get-Mailbox -ResultSize Unlimited -Filter { ( RecipientTypeDetails -eq 'UserMailbox' ) -and ( ExchangeUserAccountControl -ne 'AccountDisabled') } | Where-Object { $_.RetentionPolicy -eq $null }
}
        Catch {    
            Write-Error "Failed to get mailboxes!"
            Exit
        }
Write-Output "Get mailboxes - Success"

# set to default policy
Try {
    foreach ($mailbox in $mailboxes) {
        Set-Mailbox -Identity $mailbox.UserPrincipalName -RetentionPolicy $defaultpolicy.Name
    }
}
        Catch {    
            Write-Error "Failed to set policy!"
            Exit
        }
Write-Output "Set default policy - Success"

# end

Azure Runbook – enable Exchange Online Litigation Hold

This script will connect to Exchange Online and enable litigation hold for all enabled users. Errors due to not having the appropriate license are ignored. Litigation hold can be enabled for users licensed with Business Premium, EOL Plan 2 or the Mailbox Archive add-on. Replace ‘svc-runbookcred’ with your runbook credential name. You can schedule to run nightly to pick up new users as they are added. If you like the script, made it cooler or need some help, please add a comment below! 🙂

# use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# specify runbook credential name
$runbookcredential = 'svc-runbookcred'

# get credential for eol connection
Try { 
    $CredAzure = Get-AutomationPSCredential -Name $runbookcredential

}
        Catch {
            Write-Error "Failed to get credential!"
            Exit
        }   
Write-Output "Get automation credential - Success"

# connect eol
Try {
    Connect-ExchangeOnline -Credential $CredAzure
}
        Catch {    
            Write-Error "Failed to connect to MSOnline!"
            Exit
        }
Write-Output "Connect to EOL - Success"

# get user mailboxes
Try {
    $mailboxes = Get-Mailbox -ResultSize Unlimited -Filter { ( RecipientTypeDetails -eq 'UserMailbox' ) -and ( ExchangeUserAccountControl -ne 'AccountDisabled') } | Where-Object {$_.LitigationHoldEnabled -ne $true}
}
        Catch {    
            Write-Error "Failed to get user mailboxes!"
            Exit
        }
Write-Output "Get user mailboxes - Success"

# enable litigation hold
Try {
    $mailboxes | Set-Mailbox -LitigationHoldEnabled $true -ErrorAction Ignore
}
        Catch {    
            Write-Error "Failed to enable litigation hold!"
            Exit
        }
Write-Output "Enable litigation hold - Success"