Block Malicious Inbound Chat with External Access Allow List

In my article about the GIFShell proof-of-concept attack to compromise Teams data, I said that an easy way to stop unwanted chat messages arriving from unknown tenants that might be the entry point for attackers was to create an allow list for external access. If an allow list exists, Teams will only accept inbound chat messages from domains in the allow list.

Typically, tenants manage external access through the Users section of the Teams admin center. It’s easy to add or remove domains from the allow list there. However, that assumes you know which domains to add or remove. And that’s the question that arose from the article – how do you figure out which domains should be on the allow list?

My instinct is to use the set of guest accounts already present in the tenant as a guide. After all, if you’ve allowed someone from another tenant to become a guest account in your tenant, it’s reasonable to assume that you’re also willing to accept inbound chat messages from that domain. If you don’t, the guests can participate in channel conversations and chats that started before a restriction is imposed, but they cannot start new chats from their tenant to people in your tenant.

Steps to Update the Teams External Access Configuration

If we accept that guest accounts are a good basis for controlling external access, we can use PowerShell to:

  • Find all guests in the tenant.
  • Extract the domain from the email address for each guest account.
  • Build a list of domains from those extracted from the guest accounts.
  • Fetch the current external access configuration for Teams.
  • Find the domains not already included in the external access configuration.
  • Update the external access configuration with the missing domains.

Every tenant will handle the details of how this processing is done in their own way, but the basic commands remain the same. Here’s the code I created to do the job. You can download the latest version of the script from GitHub.

Connect-MgGraph -NoWelcome -Scopes User.Read.All
[array]$Guests = Get-MgUser -All -Filter "usertype eq 'Guest'"
Write-Host ("{0} guest accounts found" -f $Guests.Count)
$GuestList = [System.Collections.Generic.List[Object]]::new()

ForEach ($Guest in $Guests) {
    $Domain = $Guest.Mail.Split("@")[1]
    $ReportLine = [PSCustomObject][Ordered]@{  
      Guest    = $Guest.Mail
      Domain   = $Domain
      Name     = $Guest.DisplayName }
    $GuestList.Add($ReportLine)
}
Write-Host ""
Write-Host "Guest accounts found for the following domains"
Write-Host "----------------------------------------------"
$GuestList | Group-Object Domain | Sort-Object Name | Select-Object Name, Count
$Domains = $GuestList | Sort-Object Domain -Unique | Select-Object -ExpandProperty Domain

Write-Host "Connecting to Microsoft Teams to check current external access configuration"
Connect-MicrosoftTeams

# Get current set of domains configured for Teams extrenal access
$DomainConfiguration  = Get-CsTenantFederationConfiguration  | Select-Object -ExpandProperty AllowedDomains
# Check the set of domains that aren't in the current configuration
[array]$DomainsToAdd = $Domains | Where-Object {$_ -notin $DomainConfiguration.AllowedDomain.Domain}

$Prompt = "Do you want to add the following domains to the list allowed for Teams external access? " + $DomainsToAdd -join ", "
$Choice = Read-Host $Prompt

If (($Choice.ToUpper()) -eq "Y") {
 $i = 0
 ForEach ($Domain in $DomainsToAdd) {
  $i++
  Write-Host ("Adding {0} to the allowed domains list... ({1}/{2})" -f $Domain, $i, $DomainsToAdd.Count)
  Set-CsTenantFederationConfiguration -AllowedDomainsAsAList @{Add=$Domain} -ErrorAction SilentlyContinue
 }
$DomainConfiguration  = Get-CsTenantFederationConfiguration  | Select-Object -ExpandProperty AllowedDomains
Write-Host ("External access for Teams now includes {0} domains" -f $DomainConfiguration.AllowedDomain.Domain.count)
}

The external access domain white list can accommodate approximately 4,000 entries.

PowerShell Modules Required

The code is straightforward and uses the Get-MgUser cmdlet from the Microsoft Graph PowerShell SDK to find the set of guest accounts and cmdlets from the Microsoft Teams PowerShell module to fetch and update the external access configuration. Both modules are under active development and Microsoft issues new versions every month or so. It’s best to use the latest version to ensure that you don’t run into problems fixed in the current release.

Apart from that, the only cmdlets used are basic PowerShell cmdlets like Group-Object, Sort-Object, and Select-Object. In other words, no black magic or complicated code.

The Downside of Block Lists

The downside of any block list is that they stop communication. Even after allowing every domain that a guest account comes from, it’s possible that users will be frustrated when they’re unable to communicate with other contacts. Perhaps you need a method to allow users to request the addition of a new domain (after checking) to the Teams external access configuration. I’ll leave that debate to you.

Meet Tony Redmond and other Microsoft MVPs at The Experts Conference 2022, December 6-7.

100% Free and Virtual. You don’t want to miss the Microsoft training event of the year!

About the Author

Tony Redmond

Tony Redmond has written thousands of articles about Microsoft technology since 1996. He is the lead author for the Office 365 for IT Pros eBook, the only book covering Office 365 that is updated monthly to keep pace with change in the cloud. Apart from contributing to Practical365.com, Tony also writes at Office365itpros.com to support the development of the eBook. He has been a Microsoft MVP since 2004.

Comments

  1. Avatar photo
    Clément BONNIN

    Hello Tony,

    Thanks so much for your script ! It helps a lot !
    Unfortunaltely, I had to modify it a little to make it work.
    As I’m working on multiple tenants, it’s better for me to add disconnects before MgGraph and MicrosoftTeams

    But the main issue seems to be with “Set-CsTenantFederationConfiguration -AllowedDomainsAsAList”.
    If I well understand, AllowedDomainsAsAList was only working with the old SkypeForBusiness PS module.

    With some help :
    https://learn.microsoft.com/en-us/answers/questions/1160191/whitelist-a-domain-for-teams-online-in-a-federated

    I replaced it with “Set-CsTenantFederationConfiguration -AllowedDomains” and some other lines.

    Thanks again,

    Regards.

    Clément BONNIN

    1. Avatar photo
      Tony Redmond

      Using the MicrosoftTeams PowerShell module V5.5, this still works:

      $Domain = “orange.fr”
      Set-CsTenantFederationConfiguration -AllowedDomainsAsAList @{Add=$Domain}

      The documentation https://learn.microsoft.com/en-us/powershell/module/skype/set-cstenantfederationconfiguration?view=skype-ps also confirms that the cmdlet still works as used in the script.

      The point is that the script calculates domains from guest user accounts and updates the external configuration with those domains (one at a time). I could build a list object and commit them all together… maybe I’ll do that one day.

Leave a Reply