Category Archives: Microsoft Exchange

Everything related to Exchange

Finding Exchange Database hidden mailboxes. ​

Finding Exchange Database hidden mailboxes.

Story:

Maybe you have been in this situation before, trying to delete an Exchange database after moving all of its mailboxes, arbitration or archives to another server or database but it didn’t work and said that there is still something in the database? 

Now I am in a similar situation however I checked nothing in the database as you can see in the below screenshot. 

I have noticed that these issues could happen when an Exchange server gets broken or forcefully deleted from AD without properlty uninstalling it. some traces of system mailboxes might remain there with database attributes pointing to the database. 

Solution:

Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Snapin
Function Get-HiddenMailbox
{
    [CmdletBinding()]
    Param(
    [Parameter(Mandatory=$True)][string]$Path,
    [Parameter(Mandatory=$True)][string]$Database
    )
<#Check for any remaining mailboxes in a database that you can’t delete.

 

[PS] C:\Program Files\Microsoft\Exchange Server\V15\scripts>Remove-MailboxDatabase a-sb-com-udb1-v1
This mailbox database contains one or more mailboxes, mailbox plans, archive mailboxes, public folder mailboxes or
arbitration mailboxes, Audit mailboxes. To get a list of all mailboxes in this database, run the command Get-Mailbox
-Database <Database ID>. To get a list of all mailbox plans in this database, run the command Get-MailboxPlan. To get
a list of archive mailboxes in this database, run the command Get-Mailbox -Database <Database ID> -Archive. To get a
list of all public folder mailboxes in this database, run the command Get-Mailbox -Database <Database ID>
-PublicFolder. To get a list of all arbitration mailboxes in this database, run the command Get-Mailbox -Database
<Database ID> -Arbitration. To get a list of all Audit mailboxes in this database, run the command Get-Mailbox
-Database <Database ID> -AuditLog. To disable a non-arbitration mailbox so that you can delete the mailbox database,
run the command Disable-Mailbox <Mailbox ID>. To disable an archive mailbox so you can delete the mailbox database,
run the command Disable-Mailbox <Mailbox ID> -Archive. To disable a public folder mailbox so that you can delete the
mailbox database, run the command Disable-Mailbox <Mailbox ID> -PublicFolder. To disable a Audit mailbox so that you
can delete the mailbox database, run the command Get-Mailbox -AuditLog | Disable-Mailbox. Arbitration mailboxes should
be moved to another server; to do this, run the command New-MoveRequest <parameters>. If this is the last server in
the organization, run the command Disable-Mailbox <Mailbox ID> -Arbitration -DisableLastArbitrationMailboxAllowed to
disable the arbitration mailbox. Mailbox plans should be moved to another server; to do this, run the command
Set-MailboxPlan <MailboxPlan ID> -Database <Database ID>.
    + CategoryInfo          : InvalidOperation: (a-sb-com-udb1-v1:DatabaseIdParameter) [Remove-MailboxDatabase], Assoc
   iatedUserMailboxExistException
    + FullyQualifiedErrorId : [Server=SBG-MX03,RequestId=480ce97d-8492-41a9-82fa-93ed30efe652,TimeStamp=6/28/2022 9:04
   :09 AM] [FailureCategory=Cmdlet-AssociatedUserMailboxExistException] 45D30D02,Microsoft.Exchange.Management.System
  ConfigurationTasks.RemoveMailboxDatabase
    + PSComputerName        : server.domain.local
#>

 

#Fist get DB’s HomeMDB value

 

#Write-host ‘Enter your Database Name’ -ForegroundColor Red -BackgroundColor Black

 

$DN = (Get-MailboxDatabase $Database).distinguishedName
$Date = (Get-date).ToString(“MM-dd-yyyy”)

 

$Mailboxes = Get-ADObject -filter {(HomeMDB -eq $DN)}

 

$QueryResult = $Mailboxes.count
$CurrentCount = 0

 

foreach ($Mailbox in $Mailboxes){

 

     try{
         $ObjectProps = [Ordered]@{ ‘DisplayName’ = $Null; ‘UserPrincipalName’ = $Null; ‘Database’ = $Null; ‘Mailbox’ = $Null; ‘Arbitration’ = $Null; ‘Archive’ = $Null; ‘Audit’ = $Null; ‘Monitoring’ = $Null; ‘ErrorResponse’ = $Null}
 
         $MBX = $Mailbox.name
         $CurrentCount ++

 

         Write-Progress -Activity “Checking Hidden Mailboxes in the database $DB $CurrentCount of $QueryResult -Status “Fetching $MBX -PercentComplete (($CurrentCount / $QueryResult) * 100)
 
         $Result = New-Object -TypeName PSObject -Property $ObjectProps

 

         $MailboxResult = Get-mailbox -Identity $MBX -ErrorAction SilentlyContinue
         if ($MailboxResult){Write-Host “User $MBX. is a Mailbox” -ForegroundColor Green  }
 
            $ArbResult = get-mailbox -Identity $MBX -Arbitration -ErrorAction SilentlyContinue
            if($ArbResult){Write-host “User $MBX. is an Arbitration Mailbox” -ForegroundColor White }

 

                 $ArchiveResult = get-mailbox -Identity $MBX -Archive -ErrorAction SilentlyContinue
                    if($ArchiveResult){Write-host “User $MBX. is a Archive” -ForegroundColor Red}
 
                                $AuditResult = get-mailbox -Identity $MBX -AuditLog -ErrorAction SilentlyContinue
                                   if($AuditResult){Write-host “User $MBX. is a Audit Mailbox” -ForegroundColor DarkRed}
 
                                        $Monitoring =  get-mailbox -Identity $MBX -Monitoring -ErrorAction SilentlyContinue
                                            if ($Monitoring){Write-host “User $MBX. is a monitoring Mailbox” -ForegroundColor Yellow }
 

 

 
            $Result.DisplayName = $MBX
            $Result.UserPrincipalName = (Get-ADUser -Identity $Mailbox.DistinguishedName).UserprincipalName
            $Result.Database = $DB
            $Result.Mailbox = $MailboxResult
            $Result.Arbitration = $ArbResult
            $Result.Archive = $ArchiveResult
            $Result.Audit = $AuditResult
            $Result.Monitoring = $Monitoring
            $Result.ErrorResponse = ‘#N/A’
            $NewPath = $path.Split(‘.’)[0] + ‘_’ + $date + ‘.csv’

 

            $Result | export-csv -path $NewPath -Delimiter ‘;’ -NoTypeInformation -NoClobber -Append -Encoding utf8
 
 
            }
 
                Catch{
 
                Write-Warning $_.Exception.Message}

 

                $Result | export-csv -path $NewPath -Delimiter ‘;’ -NoTypeInformation -NoClobber -Append -Encoding utf8
 
       }
}

Prerequisites:

– You will have to run this script from Exchange Server.

– An account that can connect to Active Directory with at least read permission and Exchange admin read role. 

The script will utilize Active Directory and Exchange to get the Database’s distinguished name and scan any AD User Object that has this DB’s DN and post it to you as an output. 

Example:

Get-HiddenMailbox -Path ‘C:\example.csv’ -database ‘Affected Database’

As you can see in the below screenshot, I got mostly health mailboxes which should not really be a problme in case you’re deleting database, however I got one system mailbox that is still there and pointing to this Database however, I already have scanned the database for any arbitration mailboxes but Exchange CMDlet showed none. 

Now that I know which user it is, the solution for me to be able to remove/delete this database which I no longer need is to delete this AD user object since its no longer in use by Exchange. 

You won’t be able to get this mailbox through get-mailbox cmdlet because its not an active mailbox. however you will find it in AD. 

So I deleted the mailbox mentioned below and next I am going to try and delete the mailbox database in question. 

Result

Here’s the result after deleting the user in Question.

Checking and Providing Full and SendAs delegate access on O365 Exchange Online

Delegate Permissions

This is a code that I have wrote recently to check if an account have Full and SendAs access on target mailboxes in CSV and give the option to choose whether to provide this access or not.

Checking First:

You’ll need to provide two things to get this code working, First the Source account that will need access to the mailboxes. in this case referred to as “ServiceAccount”.

CSV List of Mailbxoes:

You’ll need to provide list of Mailboxes of the users you’d like to provide access to, the List must be user’s Identity either UPN or SMTP would be fine.

The Service account’s Identity must be the UPN attribute.

If you would like to improve this code please do comment or get in touch directly

Thanks

#Connect to Exchange
#Connect & Login to ExchangeOnline (MFA)

try
{
    Get-Clutter -Identity user@domain.com -ErrorAction Stop > $null
}
catch 
{
Connect-ExchangeOnline
}

    $Users = import-csv 'C:\CSV\MailboxListIsHere.csv'
    $ServiceAccount = 'Your Account that will access other Mailboxes' #// Please change the SVC account before running the code
    

        foreach ($User in $users)
        {
            $Mailbox = $User.Identity
            
            #Checking Full Access
            $Full = Get-MailboxPermission -Identity $Mailbox -User $ServiceAccount
            If ($Full.AccessRights -eq "FullAccess")
            {
                Write-Host -f Green $($ServiceAccount) "Already has Full access to $Mailbox."}
            
                    Else
                    {
                        $Answer1 = Read-Host "Do you want to assign $($ServiceAccount) Full access to $Mailbox (Yes or No)"
                        If ($Answer1 -eq "Yes")
                            {
                                Try{
                                    Add-MailboxPermission -Identity $Mailbox -User $ServiceAccount -AccessRights FullAccess
                                    Write-Host -f DarkGreen $($ServiceAccount) "Send-as access has been added to $Mailbox"
                                    }
                           
                            Catch{ ($Full.AccessRights -eq "FullAccess")}
                            
                        }
                        
                    }
                
                $SendAs = Get-RecipientPermission -Identity $Mailbox -Trustee $ServiceAccount -AccessRights SendAs
                if($SendAs.AccessRights -eq "SendAs") {
                    Write-Host -f Green $($ServiceAccount) "Already has SendAs access to $Mailbox."
                    }
                    Else
                    {
                        $Answer2 = Read-Host "Do you want to assign $($ServiceAccount) Send-as access to $Mailbox (Yes or No)"
                        If ($Answer2 -eq "Yes")
                            {
                                Try{
                                    Add-RecipientPermission -Identity $Mailbox -AccessRights SendAs -Trustee $ServiceAccount
                                    Write-Host -f Green $($ServiceAccount) "has Send-as access on $Mailbox"
                                }
                            Catch{($SendAs.AccessRights -eq "Sendas")}}
                            else{Exit}
                        }
                    }
        }
            
        

Retrieving attachments from Exchange mailbox using python

Story:

I got a request from a client who constantly gets CVs and have to download them for the hiring managers to review them and wanted to get some way an automated mechanism of downloading all those emails.

Googling lead me to the exchangelib project which is a great python source for such a purpose. I built my local lab of the following servers to test it

  1. AD 2016 moh10ly.local
  2. Exchange 2016 = exch01.moh10ly.local
  3. AAD = Another 2016 server to test from

I built my local Certification authority and made sure that all servers has the CA installed to avoid any issues on python.

If you are going to use this on your production environment you can basically install Python anywhere even on your own computer and it should work if EWS is exposed and Autodiscover is configured propely and have a valid and trusted 3rd party Certificate.

However, If you would like to schedule this to work on a daily basis and let it download attachments from mailbox then you’ll need a server or at least a computer to rely on that it would be on when the scheduled task works.

Prerequisites :

Windows Server 2016:

  • Download and install latest version of Python 3.10
  • From CMD run the following cmd
    • Pip install exchangelib
    • Pip install exchangelib[kerberos]
    • Pip install exchangelib[sspi]
  • Download and install MIT Kerberos MSI from https://web.mit.edu/KERBEROS/dist 64bit version
  • If you’re doing this on a local Lab without a trusted 3rd certificate you’ll need to make sure to export your certificatation Authority Certificate in CER format, copy the cert and add it to the end of Python root PEM.

Testing Scenario

  • I created two mailboxes on my local Exchange server lab
  • I have sent myself an email to info@moh10ly.com with 3 attachments in it as you can see.
  • Setup a server to use to download all attachments from the mailbox.

Prepare your Python Script

  • Import Packages in order to use them.

from exchangelib import DELEGATE, IMPERSONATION, Account, Credentials, EWSDateTime, EWSTimeZone, Configuration, NTLM, GSSAPI, CalendarItem, Message, Mailbox, Attendee, Q, ExtendedProperty, FileAttachment, ItemAttachment, HTMLBody, Build, Version, FolderCollection
  • Prepare Credentials of the user you would like to retrieve the attachments from.
credentials = Credentials(username='moh10ly\info', password='Bc12345$')
  • Enter your Exchange server configuration. Since autodiscover didn’t work for me as I don’t have a public certifiate so I went ahead and placed the server configuration.
ews_url = 'https://mail.moh10ly.com/EWS/exchange.asmx'
ews_auth_type = 'NTLM'
primary_smtp_address = 'info@moh10ly.com'
config = Configuration(service_endpoint=ews_url, credentials=credentials, auth_type=ews_auth_type)
  • Place the account type and configuration
account = Account(
primary_smtp_address=primary_smtp_address,
config=config, autodiscover=False,
access_type=DELEGATE)
  • Configure the local path of where you want to save attachments to on the server where this code is going to be launched from. in my code example I have created a folder called “Temp” on the C root drive and that’s what I will use.
  • You can pickup a different local path by changing the /temp path in the line “local_path = os.path.join(‘/temp‘, attachment.name)”
import os.path
from exchangelib import Account, FileAttachment, ItemAttachment, Message

some_folder = account.inbox 
for item in some_folder.all():
    for attachment in item.attachments:
        if isinstance(attachment, FileAttachment):
            local_path = os.path.join('/temp', attachment.name)
            with open(local_path, 'wb') as f:
                f.write(attachment.content)

This by now should be working fine and you should see that it is saving all your mailbox attachments to the folder that you have configured in the path section of the code.

Complete code to run

Working config


from exchangelib import DELEGATE, IMPERSONATION, Account, Credentials, EWSDateTime, EWSTimeZone, Configuration, NTLM, GSSAPI, CalendarItem, Message, Mailbox, Attendee, Q, ExtendedProperty, FileAttachment, ItemAttachment, HTMLBody, Build, Version, FolderCollection


credentials = Credentials(username='moh10ly\info', password='Bc12345$')

ews_url = 'https://mail.moh10ly.com/EWS/exchange.asmx'
ews_auth_type = 'NTLM'
primary_smtp_address = 'info@moh10ly.com'
config = Configuration(service_endpoint=ews_url, credentials=credentials, auth_type=ews_auth_type)


account = Account(
primary_smtp_address=primary_smtp_address,
config=config, autodiscover=False,
access_type=DELEGATE)

import os.path
from exchangelib import Account, FileAttachment, ItemAttachment, Message

some_folder = account.inbox 
for item in some_folder.all():
    for attachment in item.attachments:
        if isinstance(attachment, FileAttachment):
            local_path = os.path.join('/temp', attachment.name)
            with open(local_path, 'wb') as f:
                f.write(attachment.content)


-----------------

#To download all attachments in the inbox:

for item in account.inbox.all():
    for attachment in item.attachments:
        if isinstance(attachment, FileAttachment):
            local_path = os.path.join('/sky', attachment.name)
            with open(local_path, 'wb') as f, attachment.fp as fp:
                buffer = fp.read(1024)
                while buffer:
                    f.write(buffer)
                    buffer = fp.read(1024)
            print('Saved attachment to', local_path)

Hope this have helped you

References:

https://towardsdatascience.com/download-email-attachment-from-microsoft-exchange-web-services-automatically-9e20770f90ea

Check under attachments:

https://ecederstrand.github.io/exchangelib/

https://pypi.org/project/exchangelib/

https://www.activestate.com/resources/quick-reads/how-to-install-and-use-exchangelib-python/

Troubleshoot cert issue

https://stackoverflow.com/questions/51925384/unable-to-get-local-issuer-certificate-when-using-requests-in-python

With graph

https://techcommunity.microsoft.com/t5/identity-authentication/what-oauth-permissions-needed-for-exchangelib/m-p/2858179

Securing and Testing your Exchange Server with Pfsense HAProxy

– Using the CVE-2021-26855 Payload

After the recent vulnerabilities that hit Exchange Servers On-premises I found sometime to install KaliLinux and try to check what kind of information would I get from the patched servers.

I downloaded the payloads and tried to run it against couple of clients that I have patched the servers for luckily no authentication was made.

image

– Using Nikto scanner

By using Nikto command from Kali Linux I could see what  Information could Exchange expose using

The command line is nikto –h mail.domain.com and the result of the scan would be exposing the Server’s name, local IP address, OWA Version,  ASP Net platform and version.

image

Since I have my Exchange Server published via HAProxy 1.8 on Pfsense then I had to tweak HAProxy to strengthen the ciphers, make sure that HSTS is in place and deny the headers that expose the server’s sensitive information.

The result is pretty good as it also has affected the server’s score on ssllabs.com

Prior to the tweaking  my owa scan result on SSL Labs would get an A

image

– Pfsense’s HAProxy Settings before

Before upgrading Pfsense to the latest version HAProxy was on 1.6 and the ssl/tls settings were also different as they were setup through the Advanced SSL options on the frontend however, now this is no longer supported and you’ll have to remove that and set it up on the “Global Advanced pass thru” in the General setting page.

ssl-default-bind-options ssl-min-ver TLSv1.2

tune.ssl.default-dh-param 2048

ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK

image

Right after you save this, you will still need to change another settings on the Frontend to protect your server’s information from being exposed.

In the HAProxy settings Go to Frontend > Scroll down all the way to “Advanced pass thru” and paste the following:

image

# Remove headers that expose security-sensitive information.

rspadd X-Frame-Options:\ SAMEORIGIN
rspidel X-FeServer:.*$
rspidel ^Server:.*$
rspidel ^X-Powered-By:.*$
rspidel ^X-AspNet-Version:.*$
rspidel X-WsSecurity-Enabled:.*$
rspidel X-WsSecurity-For:.*$
rspidel X-OAuth-Enabled:.*$
rspadd X-Xss-Protection:\ 1;\ mode=block
rspadd Strict-Transport-Security:\ max-age=31536000;includeSubDomains;preload
rspadd Referrer-Policy:\ no-referrer-when-downgrade
rspidel Request-Id:.*$
rspidel X-RequestId:.*$
rspadd X-Content-Type-Options:\ nosniff


In the below result, I have got almost everything protected well except for the OWA version which can be a bit problematic. In the next article I am going to try and mitigate this so the server can be protected in the expected manner.

image

image

– The Result

Now the server is showing a totally different result and the Nikto scan is not revealing anything anymore.

SSLabs

image

https://securityheaders.com/

The reason why I got B on security headers is due to the fact that Content-Security-Policy header will malfunction the ECP and OWA Login pages. Permission Policy is new feature and I couldn’t find anything about it on HAProxy.

image

I hope this helps

Refences:

https://securityheaders.com/

https://www.ssllabs.com/

https://www.haproxy.com/documentation/aloha/12-0/traffic-management/lb-layer7/http-rewrite/

https://www.net7.be/blog/article/xss_csrf_http_security.html

Exchange Server backdoor investigation tools

The Story

After the disastrous exploit that was found in Microsoft Exchange Servers lots of corporations started immediately patching their servers with the latest Cumulative update and Security patches. The question is would those patches be enough if the server is already hacked or have a backdoor installed already?

image

What are those 0-day exploits ?

The vulnerabilities recently being exploited were CVE-2021-26855, CVE-2021-26857, CVE-2021-26858, and CVE-2021-27065 which are part of alleged “State-sponsored Chinese group” according to Microsoft.

Let’s get into details of those exploits one by one:

CVE-2021-26855 is a server-side request forgery (SSRF) vulnerability in Exchange which allowed the attacker to send arbitrary HTTP requests and authenticate as the Exchange server.

CVE-2021-26857 is an insecure deserialization vulnerability in the Unified Messaging service. Insecure deserialization is where untrusted user-controllable data is deserialized by a program. Exploiting this vulnerability gave HAFNIUM the ability to run code as SYSTEM on the Exchange server. This requires administrator permission or another vulnerability to exploit.

CVE-2021-26858 is a post-authentication arbitrary file write vulnerability in Exchange. If HAFNIUM could authenticate with the Exchange server then they could use this vulnerability to write a file to any path on the server. They could authenticate by exploiting the CVE-2021-26855 SSRF vulnerability or by compromising a legitimate admin’s credentials.

CVE-2021-27065 is a post-authentication arbitrary file write vulnerability in Exchange. If HAFNIUM could authenticate with the Exchange server then they could use this vulnerability to write a file to any path on the server. They could authenticate by exploiting the CVE-2021-26855 SSRF vulnerability or by compromising a legitimate admin’s credentials.

How to proceed ?

Microsoft released couple of tools that could diagnose your servers and check if you already have been infected with a backdoor or any of these nasty malware and also remove those infected files or clean them and ask you for a restart if it’s required.

Tools:

  1. MSERT (Microsoft Safety Scanner) detects web shells, Download here .
  2. Health Checker (Scans your server for any vulnerabilities and whether you have updated Server CU and installed patches). Download here
  3. Exchange WebShell Detection (A simple PowerShell that is fast and checks if your IIS or Exchange directory has been exploited). Download here
  4. Scan your exchange server for proxy logon:
    https://github.com/microsoft/CSS-Exchange/tree/main/Security
  5. Microsoft very recently created a mitigation tool for Exchange on-premises that would rewrite url for the infected servers and recover the files that were changed. You can download the tools from this github link.

    https://github.com/microsoft/CSS-Exchange/tree/main/Security

    Copy the Test-ProxyLogon code into Notepad
    Save As “Test-ProxyLogon.ps1” with the quotes in your C:\Temp folder
    Run in Exchange Management Shell: .\Test-ProxyLogon.ps1 -OutPath C:\Temp

Scan Result

Scan result should show you the following if your servers has been exploited already.

This will remove the infections and asks for a restart.

clip_image001

References:

https://www.microsoft.com/security/blog/2021/03/02/hafnium-targeting-exchange-servers/

https://www.bleepingcomputer.com/news/security/microsoft-exchange-updates-can-install-without-fixing-vulnerabilities/

https://github.com/dpaulson45/HealthChecker?mkt_tok=eyJpIjoiTURRMk5HRTFaV1V6TkRrMCIsInQiOiJcL3ZOTkRUVzdXdkJmTm5ibUIzTExKTDVxXC9ObFAxTmZLanFRZ0xpcDkxMW5raVE0dlRwV2FhVFFmWlVUVFZaZUdFM1NlcEFNTEZ6dTh5aWlqcVBpV3J2R2IxbGJxMmNUZ1ppYjJyZklnMjZFZngrM2tBUnNsM1JKcHJsSU1ib3BTIn0%3D#download

Exchange 2016: Find remaining Folders of delete or non existing databases

Exchange Corner

Story

Let’s assume that you work for a company that has Exchange 2016 and has big amount of databases (50-100 DB).

You constantly delete databases to clear white space or for whatever reason but don’t usually keep on deleting folders or lost track of which database is deleted in your DB Folder.

Real Life Scenario

In the following PowerShell script I am going to demonstrate how to check which of the folders in my D drive (Database drive) has an existing Database and which do not have.

Databases Folder path

OutPut:

Script

The below script gets all folders in the drive path D:\Databases to check if they exist or not.


# Get deleted database that still has remaining non deleted folders
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
$databases = Get-ChildItem D:\Databases\*  -Directory | select Name

foreach ($database in $databases)
{
        $DB = $database.Name
        if ((Get-MailboxDatabase -Identity $db -ErrorAction Ignore ))
            {
            write-host "Database $($db) exists on Exchange Server" -ForegroundColor Green
            }
                else
                {
                Write-Host "Database $($db) doesn't exist on Exchange Server " -ForegroundColor Red
                }
}

I did not add the part to delete the folder through the script as it is still a risky thing to automate and would rather do the deletion manually after double confirming it’s totally gone.

For more about Exchange Server related articles please visit Exchange section here

Hope this helps.

Brightmail does not deliver email to Distribution group members

The Story

Note: This article assumes you have Brightmail Gateway

When you try to send an email to a particular Exchange Distribution group Group@domain.com the result is either users don’t exist or you might get the following error if you test with Microsoft Test connectivity online tool.

Error:

The server returned status code 554 – Transaction failed. The server response was: 5.7.1 Delivery not authorized

Other related errors

‘554 5.7.1: You are not allowed to connect’

clip_image001

Cause:

Because the group has been cached in the Symantec gateway with its old members, The result could be an error that users don’t exist or delivery is not authorized.

Solution:

To solve this problem, You need to go to Brightmail gateway Administration > Directory Integration and click on your AD Directory > Advanced and hit on Clear Cache.

This would cleared the cached group and take the most recently updated group and its members.

This should resolve the problem.

clip_image002

How to clear the DDS cache in Messaging Gateway

https://knowledge.broadcom.com/external/article?legacyId=tech132131

Skype for Business IM integration with Exchange 2016 OWA–Part 2

This article is a completion of Part 1, Click here to go to Part 1

Configuration Steps – Part 2

7. On Exchange: Enable OWA VD Instant Messaging
8. On Exchange: Enable Messaging on OWA Policy
9. On Exchange: Create Enterprise Application for Skype Pool.
10. On Exchange: Create new SettingOverride for Skype for Business.
11- Generate a new Certificate for Exchange IM
12. Assign the newly imported certificate to IIS Exchange Back End site
13. On Exchange: Restart the WebAppPool
14. Log out and sign back in to OWA to Check
15. Troubleshooting methods

    7- On Exchange Server: Enable OWA VD Instant Messaging

    Part of enabling IM integration between Exchange and SfB is to enable OWA Virtual Directory to allow this. The below cmdlet does the job for you on all your Exchange Servers

    From Exchange, Launch Exchange Management and run the following cmdlet

    Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -InstantMessagingEnabled $true -InstantMessagingType Ocs

    clip_image001[6]_thumb

    8- On Exchange: Enable Messaging on OWA Policy

    Run the following to enable Messaging for Owa Policy

    Get-OwaMailboxPolicy | Set-OwaMailboxPolicy -InstantMessagingEnabled $true -InstantMessagingType Ocs

    clip_image001[6]_thumb[1]

    9- On Exchange: Create Enterprise Application for Skype Pool.

      From Exchange Management shell Run the following cmdlet

      Cd $exscripts

      .\Configure-EnterprisePartnerApplication.ps1 -AuthMetadataUrl “https://sbg-pool01.domain.com/metadata/json/1” -ApplicationType Lync

      The AuthMetadataUrl is going to be your local Skype for Business Pool URL. This URL should work in your Exchange server without any Certificate error. Meaning that the certificate assigned to your Skype for Business pool should already be imported to Exchange Servers to trust this URL.

      image_thumb[14]

        If your previous configuration is correct then you should see the “The Configuration has Succeeded” Message.

          10- On Exchange: Create new SettingOverride for Skype for Business.

          Notes:

          • To configure the same settings on all Exchange 2016 and Exchange 2019 servers in the Active Directory forest, don’t use the Server parameter.

          New-SettingOverride -Name “<UniqueOverrideName>” -Component OwaServer -Section IMSettings -Parameters @(“IMServerName=<Skype server/pool  name>”,”IMCertificateThumbprint=<Certificate Thumbprint>”) -Reason “<DescriptiveReason>” [-Server <ServerName>]

          The Thumbprint you use here will define if whether IM will work or not as this what secures the communication between Exchange and Skype. If you use the wrong certificate your Integration will fail and users wont be able to login to IM through OWA.

          11- Generate a new Certificate for Exchange IM

          IMPORTANT NOTE:

          In order for IM in OWA to work the certificate you will generate must have its common name set as mail.domain.com to match the configuration.

          Using Digicert tool on Exchange Server I will generate the CSR of the new certificate

          Click on Create CSR

          image_thumb[15]

          Choose SSL certificate type and make sure you choose Mail.domain.com as CN

          In the SANs type all of the involved servers (Skype for Business Frontends, Mailbox servers in FQDN and in Hostnames as in the screenshot below). and click on Generate

          image_thumb[16]

          • Go to your CA Server’s CertSRV URL and copy the CSR code there to generate the new certificate.
          • Import the new certificate to the current server, then export it in PFX format and import it to all the Exchange Servers you’re planning to use.

          image_thumb[18]

          • After importing the certificate I will verify that I can see the private key

          image_thumb[19]

          Click on the Details and copy the Thumbprint or from MMC right click the certificate > Properties give it a friendly name e.g. (IM) and then from Exchange Management shell you can copy the Thumbprint directly.

          Get-ExchangeCertificate | select thumbprint,friendlyName

          image_thumb[20]

          Now use the previous script to create the setting Override for OwaServer.

          Things you can change are in bold “Name, IM Servername Value, and the Thumbprint value”.

          New-SettingOverride -Name “IM Override” -Component OwaServer -Section IMSettings -Parameters @(“IMServerName=SBG-Pool01.domain.com“,”IMCertificateThumbprint= 28E4B1BA0F2FCB1535AF199F02A64EFC78367F2D“) -Reason “Configure IM”

          image_thumb[21]

          If you enter the server parameter to use a single server you can change that by using. Note that you must not use FQDN but rather only the server’s hostname.

          Get-SettingOverride | Set-SettingOverride -Server sbg-mx01,sbg-mx02

          image_thumb[22]

          This should generate an event ID 112 on Exchange servers involved in the deployment.

          clip_image001[9]_thumb

            12. Assign the newly imported certificate to IIS Exchange Back End site

            Once the certificate is in the server store, You will be able to easily find in from IIS and bind it to the Exchange Back End site.

            This is the most crucial step to get IM to work in OWA. Don’t worry about breaking up Exchange Sites or Powershell. If you have added Exchange Servers Hostnames and FQDNs in this certificate then you should be good.

            • Now Launch IIS
            • Click on Exchange Back End
            • Select Binding
            • Click on the 444 port and edit
            • Select the newly generated certificate that has the mail.domain.com as CN. (This certificate must also have all Exchange Servers hostnames and FQDNs set as SANs)

            image_thumb[23]

            image_thumb[24]

            Make sure you change the backend cert to the new on all the involved Exchange Servers.

            13. On Exchange: Restart the WebAppPool

            Restart-WebAppPool MSExchangeOWAAppPool

            image_thumb[25]

              14. Log out and sign back in to OWA to Check

              Log out of OWA and back in and check if you are able to Login to IM . It should normally sign you in automatically but in case of an error then you should see it.

              image_thumb[29]

              In case of an error you should see the following.

              image_thumb[27]

              If it works then you should see the presence

              image_thumb[28]

              15. Troubleshooting Methods

              If you follow the above steps correctly then it should work especially when applying the right certificate for your Exchange Back End IIS part however if you face an error then you should do the following steps to troubleshoot the error

              • Set the Eventlog for Instant Messaging on Exchange from Low to High

              Set-EventLogLevel -Identity “sbg-mx01\MSExchange OWA\InstantMessage” -Level High

              image_thumb[30]

              • Look in the following path for errors

              C:\Program Files\Microsoft\Exchange Server\V15\Logging\OWA\InstantMessaging

              • Check the Healthset of the OWA Instant Messaging.

              Get-ServerHealth -HealthSet OWA.Protocol.Dep -Server sbg-mx01 | Format-Table Name, AlertValue –Auto

              image_thumb[31]

              Get-MonitoringItemIdentity -Server sbg-mx01 -Identity OWA.Protocol.Dep | Format-Table Identity,ItemType,Name -Auto

                image_thumb[32]

                Ref

                https://docs.microsoft.com/en-us/exchange/plan-and-deploy/post-installation-tasks/configure-im-integration-with-owa?view=exchserver-2019

                https://docs.microsoft.com/en-us/exchange/high-availability/managed-availability/health-sets?view=exchserver-2019

                Skype for Business IM integration with Exchange 2016 OWA–Part 1

                The Story

                A good and detailed documentation is everything we need to implement any kind of project especially if it’s an integration between two different servers that perform different roles.

                And with PKI involved the complications multiply thus a good article write up is what we need.

                Previously I have tried a test lab with Skype for Business 2015/2019 IM Integration with Exchange 2016/2019 and the result was a complete failure and endless search for what’s missing to get IM to work from OWA?

                image

                ERROR

                Upon completion of the steps mentioned in Microsoft’s Official documentation and after restarting Exchange IIS or OWAAppPool you will see this when you try to login to OWA with your user

                There’s a problem with instant messaging. Please try again later.

                image

                MS Official Documentation

                In their Official documentation Microsoft says that the certificate in question must be trusted by all the servers involved meaning Skype for Business Frontend and Mailbox Servers.

                Meanwhile this is true, it still would not get the IM to login/work although it might drop the initialize event ID 112 in the event log.

                clip_image001

                Here is what MS says about the certificate.

                Exchange and Skype for Business integration requires server certificates that are trusted by all of the servers involved. The procedures in this topic assume that you already have the required certificates. For more information, see Plan to integrate Skype for Business Server 2015 and Exchange. The required IM certificate thumbprint refers to the Exchange Server certificate assigned to the IIS service.

                REF URL: https://docs.microsoft.com/en-us/exchange/plan-and-deploy/post-installation-tasks/configure-im-integration-with-owa?view=exchserver-2019#what-do-you-need-to-know-before-you-begin

                image

                Step by Step Deployment

                To do things the way that should get this to work, I will detail steps one by one so we can be sure to get the positive results we are all waiting for when dealing with Exchange and Skype for Business.

                Exchange IM URL 1: mail.domain.com

                Skype for Business Pool FQDN: SBG-Pool01.domain.com

                Autodiscover URL : Autodiscover.Domain.com

                Prerequisites

                1. For Default and Web Service Internal, Your Skype for Business Frontend Server/Pool must use a certificate that is generated from an internal CA which you can use later to generate Exchange’s IM Certificate.
                2. UCMA must be installed (Doesn’t matter if version 4 or 5) both are supposed to work with Exchange 2016.
                3. Local Certification Authority must already be deployed in the domain.

                Configuration Steps – Part 1

                1. On SfB: Set CsAuthConfiguration Autodiscover URL for Skype server to find Exchange Autodiscover
                2. On SfB: Get-CsSite to see what is the current site ID.
                3. On Exchange: Check AutodiscoverServiceInternalURI
                4. On SfB: Create new Partner
                5. On SfB: Create new Trusted Application Pool
                6. On SfB: Create new Trusted Application ID

                Configuration Steps – Part 2

                7. On Exchange: Enable OWA VD Instant Messaging
                8. On Exchange: Enable Messaging on OWA Policy
                9. On Exchange: Create Enterprise Application for Skype Pool.
                10. On Exchange: Create new SettingOverride for Skype for Business.
                11- Generate a new Certificate for Exchange IM
                12. Assign the newly imported certificate to IIS Exchange Back End site
                13. On Exchange: Restart the WebAppPool
                14. Log out and sign back in to OWA to Check
                15. Troubleshooting methods

                Prerequisites

                1- Update or Create Server Default and Web Service Internal Certificate for SfB Pool servers

                The certificate installed on the Skype for Business Pool Frontend servers must be generated from a local Certification Authority which can be trusted by Exchange Server services.

                The Certificate generated for Skype for Business pool as in the below screenshot is generated from my CA and includes the names of the servers:

                • Skype for Business Pool
                • Skype for Business Frontend FQDNs
                • Exchange Servers
                • Autodiscover FQDN
                • Lyncdiscover.domains.com
                • Lyncdiscoverinternal.domains.com
                • sip.domains.com
                • meet.domains.com
                • dialin.domain.com
                • External.domain.com

                image

                image

                2- UCMA must be installed

                On both Exchange and Skype for Business servers I already have UCMA 4.0 version installed, but if you don’t have it or have an older version then you can’t continue without it.

                image

                3- Make sure you have a Local Certification Authority deployed in your domain.

                Configuration Steps – Part 1

                1- On SfB: Set CsAuthConfiguration Autodiscover URL for Skype server to find Exchange Autodiscover

                For Skype for Business Server to find Exchange Autodiscover Service point and to be able to authenticate servers we’ll be using the below cmdlet

                This enables both servers to authenticate and share information when needed and without user’s interference.

                Set-CsOauthConfiguration -ExchangeAutodiscoverUrl https://autodiscover.domain.com/autodiscover/autodiscover.svc

                image

                image

                Ref:

                https://docs.microsoft.com/en-us/powershell/module/skype/set-csoauthconfiguration?view=skype-ps

                2- On SfB: Get-CsSite to see what is the current site ID.

                Getting a site ID will be useful for later use to setup the Trusted Application Pool.

                On Skype for Business Management shell. Type the following

                Get-CsSite

                So the Site ID is 1. I will keep this for later use

                image

                3- On Exchange: Check AutodiscoverServiceInternalURI

                Specify the AutodiscoverServiceInternalURI for internal Autodiscover service. Make sure it points to your public URL and certificate not the internal one otherwise your users will get a certificate error through Outlook and might cause IM chat not to work.

                The Cmdlet would be

                Get-ClientAccessService | Set-ClientAccessService –AutoDiscoverServiceInternalUri https://autodiscover.domain.com/autodiscover/autodiscover.xml

                image

                4- On SfB: Create new Partner Application

                On Skype for Business Server, Launch Management Shell and use this cmdlet to add Exchange as a trusted Application to the SfB topology.

                New-CsPartnerApplication -Identity Exchange -ApplicationTrustLevel Full -MetadataUrl “https://autodiscover.domain.com/autodiscover/metadata/json/1

                image

                5- On SfB: Create new Trusted Application Pool

                New-CsTrustedApplicationPool -Identity mail.domain.com -Registrar sbg-pool01.domain.com -Site 1 -RequiresReplication $false

                image

                6- On SfB: Create new Trusted Application ID

                From SfB Management Shell run the following cmdlet .

                New-CsTrustedApplication -ApplicationId OutlookWebAccess -TrustedApplicationPoolFqdn mail.domain.com -Port 5199

                image

                Finally

                clip_image001[4]

                Click on the link below for Part 2

                Skype for Business IM integration with Exchange 2016 OWA–Part 2

                an Exchange mailbox was mistakenly migrated over another user’s object used by another user

                The Story

                If you ever used Prepare moverequest command to migrate a user and forgot to use ADMT to rewrite user’s properties with the old attributes. You might have used ADMT again to rewrite the properties.

                If you use ADMT you will need to exclude all Exchange Attributes from the source since its already copied using Prepare-move request script however, in some cases some people do make mistakes and you might have came through the same mistake my colleague  have done during one of these extremely complicated Cross forest Migrations where you’d prepare a CSV files through PowerShell and names wouldn’t match Sam accounts.

                Don’t Panic

                If however, you forgot again to exclude the Exchange attributes while using ADMT then you most likely wont see the user in the Target forest which will cause to panic thinking the user is gone .. But no the user is not gone don’t panic.

                When you look for the user’s mailbox on the target forest after the move request is completed you’ll get an error reporting the user can’t be found

                image

                Solution

                To fix the problem you’ll need to change to attributes only for this migrated user. (In the target forest after user mailbox move is completed).

                The attributes are

                msExchRecipientDisplayType    1073741824
                msExchRecipientTypeDetails    128

                The wrong Attributes are as following.

                image

                You will need to fix them to look like the following

                image

                Once you apply the change you’ll need to wait for a minute or few depending on your AD replication speed.
                The problem will be then solved

                image