Pages

Showing posts with label Exchange 2013. Show all posts
Showing posts with label Exchange 2013. Show all posts

Monday, November 2, 2020

Configuring X-Content-Type-Options and Permissions-Policy for Citrix ADC / NetScaler to score A on Security Headers for Exchange OWA

I’ve recently been involved with a few projects involving security vulnerabilities from penetration scans and one of the clients were asked to secure their Exchange OWA portal load balanced behind a Citrix ADC so that 2 of the 6 headers that are identified to be missing from the Security Headers (https://securityheaders.com/) scan are addressed:

  • X-Content-Type-Options
  • Permissions-Policy
image

Please refer to my previous blog post for instructions on how to implement the other headers identified to be present in the scan above:

Securing a Citrix ADC (formally known as NetScaler VPX) to score an A rating on Security Headers - March 2020
http://terenceluk.blogspot.com/2020/02/securing-citrix-adc-formally-known-as.html

X-Content-Type-Options

The X-Content-Type-Options header is fairly easy to implement as it is described in Citrix’s knowledge base article:

How to create rewrite policy for content security headers , XSS protection, HSTS, X-Content-Type-Options & Content-Security-Policy.
https://support.citrix.com/article/CTX233095

The following are the CLI commands:

add rewrite action rw_act_insert_Xcontent_header_Policy insert_http_header X-Content-Type-Options "\"nosniff\""

add rewrite policy rw_pol_insert_XContent_Policy TRUE rw_act_insert_Xcontent_header_Policy

bind lb vserver mail.college.bm_external -policyName rw_pol_insert_XContent_Policy -type RESPONSE -priority 120 -gotoPriorityExpression NEXT

image

The following is the Rewrite Action in the Citrix ADC / NetScaler GUI:

image

The following is the Rewrite Policy in the Citrix ADC / NetScaler GUI:

image

With the Rewrite Action and Policy in place, and having the policy bound to the virtual server, the scan should now return the header as being present:

image

Permissions-Policy

The Permissions-Policy, which replaces the Feature Policy, isn’t as straight forward as Citrix does not have a KB for the implementation of this header. However, Scott Helme provides a very detailed explanation for this header:

Goodbye Feature Policy and hello Permissions Policy!
https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy/

The following are the CLI commands to create the Rewrite Action, Policy and bind it to the virtual server:

add rewrite action rw_act_insert_Permissions_Policy insert_http_header Permissions-Policy "\"vibrate=(self), sync-xhr=(self \'https://<owa.domain.com>\')\""

add rewrite policy rw_pol_insert_Permissions_Policy "HTTP.RES.HEADER(\"Permissions-Policy\").EXISTS.NOT" rw_act_insert_Permissions_Policy

bind lb vserver mail.contoso.com_external -policyName rw_pol_insert_Permissions_Policy -type RESPONSE 110 -gotoPriorityExpression NEXT

image

The following is the Rewrite Action in the Citrix ADC / NetScaler GUI:

image

The following is the Rewrite Policy in the Citrix ADC / NetScaler GUI:

image

With the Rewrite Action and Policy in place, and having the policy bound to the virtual server, the scan should now return the header as being present:

image

**Note that the reason why the score in the screenshot above is A rather than A+ is because the Content-Security-Policy header configured contains the ‘unsafe-inline’ in the script-src directive. I have yet to successfully omit ‘unsafe-inline’ for sites such as a Citrix Gateway or Exchange OWA without causing the login page to fail to load.

image

Wednesday, October 21, 2020

Browsing a Citrix ADC / NetScaler published Exchange OWA displays the warning message: Your connection is not fully secure Your connection is not fully secure NET::ERR_SSL_OBSOLETE_VERSION

Problem

You’ve received reports that browsing a Citrix ADC / NetScaler published Exchange OWA displays the following warning message in Chrome and Edge Chromium:

Google Chrome

Your connection is not fully secure

This site uses an outdated security configuration, which may expose your information (for example, passwords, messages, or credit cards) when it is sent to this site.

NET::ERR_SSL_OBSOLETE_VERSION

image

image

Edge Chromium

Your connection isn't secure

This site uses an outdated security configuration that might expose your personal information when it's sent to this site (for example, passwords, messages, or credit cards).

NET::ERR_SSL_OBSOLETE_VERSION

image

It is possible to proceed in both browsers but a Not secure message will be displayed in the address bar:

image

Solution

One of the reasons why this warning message would be displayed is because Google Chrome 72 and later versions have deprecated support for legacy TLS versions, which include TLS 1.0 and 1.1. If the Load Balancing Virtual Server for the Exchange OWA configured on Citrix ADC / NetScaler has only TLS 1.0 and TLS 1.1 enabled as shown in the screenshot below then the warning message above will be displayed:

image

To correct the issue, simply enable TLSv12 in addition to TLSv1, TLSv11:

image

Or just enable TLSv12 if there are no legacy devices with browsers accessing the website (those should be upgraded if they exist):

image

Once updated, the site should load and the Security tab of Google Chrome’s Developer Tools should display a message indicating the site is using TLS 1.2:

image

Thursday, April 23, 2020

Configuring AD FS claims-based authentication with Exchange Server 2019 Outlook on the web fails to display and redirect /owa and /ecp logon portals

Problem

You’ve completed deploying the configuration required that allow clients to use AD FS (on Windows Server 2019) claims-based authentication to connect to Exchange Server 2019 Outlook on the web (formerly known as Outlook Web App) and the Exchange admin center (EAC) as outlined in the following documentation:

Use AD FS claims-based authentication with Outlook on the web
https://docs.microsoft.com/en-us/exchange/clients/outlook-on-the-web/ad-fs-claims-based-auth?view=exchserver-2019

… but notice that attempting to navigate to /owa throws two different errors depending on the browser you use:

Google Chrome:

The page isn’t working

mail.contoso.com redirected you too many times.

ERR_TOO_MANY_REDIRECTS

image

Internet Explorer:

Server Error in '/owa' Application.


Encryption certificate is absent

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: Microsoft.Exchange.Security.Authentication.AdfsConfigurationException: Encryption certificate is absent
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[AdfsConfigurationException: Encryption certificate is absent]
   Microsoft.Exchange.Security.Authentication.Utility.GetCertificates() +130
   Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms() +12
   Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e) +143
   Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration() +177
   Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context) +17
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +580
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +165
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +267
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +341

[HttpException (0x80004005): Encryption certificate is absent]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +523
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +107
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +688

image

Attempting to navigate to /ecp throws the following error:

Server Error in '/ecp' Application.


Runtime Error

Description: An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
Details: To enable the details of this specific error message to be viewable on remote machines, please create a <customErrors> tag within a "web.config" configuration file located in the root directory of the current web application. This <customErrors> tag should then have its "mode" attribute set to "Off".

<!-- Web.Config Configuration File -->

<configuration>

<system.web>

<customErrors mode="Off"/>

</system.web>

</configuration>

Notes: The current error page you are seeing can be replaced by a custom error page by modifying the "defaultRedirect" attribute of the application's <customErrors> configuration tag to point to a custom error page URL.

<!-- Web.Config Configuration File -->

<configuration>

<system.web>

<customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/>

</system.web>

</configuration>

image

Reviewing the event logs shows the following error consistently logged on the Exchange server:

image

Log Name: Application

Source: ASP.NET 4.0.30319.0

Event ID: 1309

Level: Warning

Event code: 3005

Event message: An unhandled exception has occurred.

Event time: 4/23/2020 2:41:17 PM

Event time (UTC): 4/23/2020 5:41:17 PM

Event ID: 034a726997a145338d6d7f878e25b637

Event sequence: 2

Event occurrence: 1

Event detail code: 0

Application information:

Application domain: /LM/W3SVC/1/ROOT/owa-20-132321372689777583

Trust level: Full

Application Virtual Path: /owa

Application Path: E:\Microsoft\Exchange Server\V15\FrontEnd\HttpProxy\owa\

Machine name: OSMIUM

Process information:

Process ID: 14576

Process name: w3wp.exe

Account name: NT AUTHORITY\SYSTEM

Exception information:

Exception type: AdfsConfigurationException

Exception message: Encryption certificate is absent

at Microsoft.Exchange.Security.Authentication.Utility.GetCertificates()

at Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms()

at Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e)

at Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration()

at Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context)

at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)

at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)

at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context)

at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

Request information:

Request URL: https://mail.contoso.bm:443/owa/

Request path: /owa/

User host address: 172.16.10.105

User:

Is authenticated: False

Authentication Type:

Thread account name: NT AUTHORITY\SYSTEM

Thread information:

Thread ID: 18

Thread account name: NT AUTHORITY\SYSTEM

Is impersonating: False

Stack trace: at Microsoft.Exchange.Security.Authentication.Utility.GetCertificates()

at Microsoft.Exchange.Security.Authentication.AdfsSessionSecurityTokenHandler.CreateTransforms()

at Microsoft.Exchange.Security.Authentication.AdfsFederationAuthModule.FederatedAuthentication_ServiceConfigurationCreated(Object sender, ServiceConfigurationCreatedEventArgs e)

at Microsoft.IdentityModel.Web.FederatedAuthentication.get_ServiceConfiguration()

at Microsoft.IdentityModel.Web.HttpModuleBase.Init(HttpApplication context)

at System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers)

at System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)

at System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(sIntPtr appContext, HttpContext context)

at System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext)

Custom event details:

image

Solution

This issue took quite a bit of my time to troubleshoot as I thought I had made a mistake for the configuration outlined in the document. What I later determined from the event constantly logged shown above was that the self-signed Microsoft Exchange Server Auth Certificate on the Exchange 2019 servers have expired and it was causing the authentication redirect to the AD FS server to fail. To quickly determine whether this is the case for an environment, simply launch the event viewer on one of the Exchange servers, navigate to the Application logs and filter based on Event ID 24:

You should see an event similar to the following:

image

Log Name: Application

Source: MSExchange Web Services

Event ID: 24

Level: Error

The Exchange certificate [Subject]

CN=Microsoft Exchange Server Auth Certificate

[Issuer]

CN=Microsoft Exchange Server Auth Certificate

[Serial Number]

2BF79A269A16ACB047DE62C555EAF2B7

[Not Before]

3/18/2015 2:36:19 PM

[Not After]

2/20/2020 1:36:19 PM

[Thumbprint]

E60327C0FFB444247A6CD5E2BAD6AD58083BD6F1

expired on 2/20/2020 1:36:19 PM.

image

The certificate in this environment expired on February 20, 2020 and while this Exchange Server 2019 wasn’t installed 5 years ago (this is the default lifetime of the self-signed certificate), the first Exchange Server 2013 or 2016 was probably installed sometime in 2015. This certificate is installed on every Exchange server in the organization and shared as it is not unique to the identity of any of the servers.

To renew this certificate, begin by executing the following cmdlet to display the certificates on the Exchange server and confirm that the Microsoft Exchange Server Auth Certificate listed has indeed expired:

Get-ChildItem cert:\localmachine\my | ft Thumbprint,Notafter,Subject

image

Use the Get-AuthConfig cmdlet to confirm that the expired certificate is being used:

Note the matching thumbprint.

image

Use the following cmdlet to retrieve the thumbprint of the expired certificate:

Get-AuthConfig | fl Currentcer*

Copy the Thumbprint down as you will need this later.

image

Note that if the certificate has expired then you can simply renew it directly from the EAC console but I had issues accessing the EAC so I decided to use PowerShell to perform the renewal as outlined in the documentation here:

Renew an Exchange Server certificate
https://docs.microsoft.com/en-us/exchange/architecture/client-access/renew-certificates?view=exchserver-2019

Execute the following cmdlet to list all of the certificates the Exchange server is using and confirm that the previously copied thumbprint matches the one listed as Subject: CN=Microsoft Exchange Server Auth Certificate :

Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,NotBefore,NotAfter

image

Execute the following cmdlet to retrieve the expired certificate as an object then renew it with the New-ExchangeCertificate cmdlet:

Get-ExchangeCertificate -Thumbprint <paste the thumbprint previous copied> | New-ExchangeCertificate -Force -PrivateKeyExportable $true

Here is an example of the cmdlet ran with the thumbprint copied previously:

Get-ExchangeCertificate -Thumbprint E60327C0FFB444247A6CD5E2BAD6AD58083BD6F1 | New-ExchangeCertificate -Force -PrivateKeyExportable $true

image

Copy the thumbprint to notepad and clearly label this is the renewed certificate.

Executing the previous cmdlet:

Get-ExchangeCertificate | where {$_.IsSelfSigned -eq $true} | Format-List FriendlyName,Subject,CertificateDomains,Thumbprint,NotBefore,NotAfter

… will now show the expired and renewed certificate:

image

If you’re like me where you’re unable to access EAC, you can view the new certificate in the IIS console as well:

image

Execute the Get-AuthConfig cmdlet and make a note of the that the CurrentCertificateThumbprint is populated while the PreviousCertificateThumbprint and NextCertificateThumbprint are empty:

image

Proceed to replace the expired certificate by executing the following cmdlets:

$thumb = "< The New Certificate Thumbprint>"

$date = get-date

Set-AuthConfig -NewCertificateThumbprint $thumb -NewCertificateEffectiveDate $date

Here is an example of the cmdlet to execute with the information above:

$thumb = “BDE4266ED877E95F38D303878A048C0EA0183C7B”

$date = get-date

Set-AuthConfig -NewCertificateThumbprint $thumb -NewCertificateEffectiveDate $date

image

image

Execute the Get-AuthConfig cmdlet and notice how that the CurrentCertificateThumbprint hasn’t changed but the NextCertificateThumbprint field is now populated with the new certificate’s thumbprint:

image

Proceed to publish the new certificate and clearing the old expired certificate from the configuration by executing the following cmdlets:

Set-AuthConfig -PublishCertificate

Set-AuthConfig -ClearPreviousCertificate

Execute the Get-AuthConfig cmdlet and notice how that the CurrentCertificateThumbprint has been updated with the new certificate’s thumbprint and the NextCertificateThumbprint field is cleared:

image

Proceed and confirm that these events are no longer logged:

image

image

… then test to confirm that the /owa and /ecp are now being redirected to AD FS.

Wednesday, April 24, 2019

Running Remote Connectivity Analyzer against Exchange 2013/2016/2019 fails with: “MAPI over HTTP connectivity failed.”

Problem

You use the Remote Connectivity Analyzer to test external connectivity for an Exchange 2013/2016/2019 environment but notice that it fails with the following error:

Testing MAPI over HTTP connectivity to server mail.contoso.com
      MAPI over HTTP connectivity failed.
      
Additional Details
      Elapsed Time: 11 ms.

     
Test Steps
      
Attempting to resolve the host name contexc02.contoso.com in DNS.
      The host name couldn't be resolved.
        Tell me more about this issue and how to resolve it

     
Additional Details
      Host contexc02.contoso.com couldn't be resolved in DNS InfoDomainNonexistent.
Elapsed Time: 11 ms.


What’s strange about the error is that the server FQDN referenced in the message has the FQDN of the internal server name and domain name.

Solution

As much as the error suggests this caused by MAPI over HTTP, you may notice that executing the cmdlet:

Get-MapiVirtualDirectory | FL ServerName, *url*, *auth*

… would reveal that the configuration for the external MAPI Virtual Directory is already configured with the appropriate URL.

Executing the cmdlet:

Get-OrganizationConfig | fl identity,*mapi*

… will also indicate that MAPI over HTTP is enabled.

What typically causes this issue is if Outlook Anywhere has not been configured.  You can review the settings on each of the servers either by executing the following cmdlet:

Get-OutlookAnywhere | FL Identity,*Host*,*requireSSL*

… or navigating to the server properties’ Outlook Anywhere section, which would likely have the internal server’s FQDN as that is the default:

Either adjust the configuration in the EAC for each server appropriately or use the following cmdlet to configure the settings:

Set-OutlookAnywhere -Identity:"<serverName>\Rpc (Default Web Site)" -DefaultAuthenticationMethod NTLM -InternalHostname <internalFQDNURL> -InternalClientsRequireSsl $true -ExternalHostname <externalFQDNURL> -ExternalClientsRequireSsl $true -SSLOffloading $false

The Remote Connectivity Analyzer should return successful results once this has been corrected.

Sunday, April 21, 2019

Attempting to execute Exchange PowerShell cmdlets on objects in another domain fails with: “The operation couldn't be performed because object 'alias@domain.com' couldn't be found on 'DC01.domain.com'.”

One of the common questions I have been asked over the years is why the following error is thrown when an Exchange PowerShell cmdlet is executed on an object in another domain where the Exchange Organization is not installed with.  The following is an example of the scenario:

  1. The environment has 1 forest and multiple domains
  2. The root domain name is contoso.com
  3. Another domain named tradewinds.com is in the same forest but a separate tree
  4. Exchange is installed into the contoso.com domain

You log onto one of the Exchange servers in the contoso.com domain and attempt to execute a cmdlet for an object in the tradewinds.com domain but receive the following error:

Get-MailboxPermission -Identity inbox@tradewinds.com
The operation couldn't be performed because object 'inbox@tradewinds.com' couldn't be found on
'contDC01.contoso.com'.
     + CategoryInfo          : InvalidData: (:) [Get-MailboxPermission], ManagementObjectNotFoundException
     + FullyQualifiedErrorId : [Server=contBMEXMA01,RequestId=c60334ef-7152-42ec-98f0-f838d0a90283,TimeStamp=4/5/2019 12
    :36:27 PM] [FailureCategory=Cmdlet-ManagementObjectNotFoundException] E1D4908D,Microsoft.Exchange.Management.Recip
   ientTasks.GetMailboxPermission
     + PSComputerName        : contbmexma01.contoso.com

The reason why this error is thrown is because any cmdlets executed in the default context will only look up objects in the domain where Exchange is installed.  In order to search for objects outside of the current domain, you will either need to:

  1. Log onto an Exchange server that is joined to that domain (if there is one)
  2. Use the DomainController switch to specify a domain controller in that domain
  3. Execute the follow cmdlet to expand the scope to include the entire forest (not that this can cause searches to be slow if the environment is large):

Set-AdServerSettings -ViewEntireForest $true

Friday, April 12, 2019

Attempting to enable a user for Unified Messaging in Exchange Server 2016 fails with: "Extension xxxx is already assigned to another user on the dial plan UMDialPlan or on an equivalent dial plan."

Problem

You attempt to enable a user for Unified Messaging in Exchange Server 2016 but receive the following error:

Extension xxxx is already assigned to another user on the dial plan UMDialPlan or on an equivalent dial plan.

You know that this extension was previously assigned to another user so you search for the previous user and can confirm that Unified Messaging for the user is disabled:

Reviewing the properties of the account’s email address properties confirm there are now EUM addresses:

Executing the following cmdlets does not display this extension assigned to anyone in the dial plan:

Get-UMMailbox | where { $_.Extensions -eq "9533" }

Get-UMMailbox | Format-Table -Wrap -AutoSize > C:\UMExt.txt

You proceed to review the msExchShadowProxyAddresses attribute in the previous user’s AD user account’s properties’ Attribute Editor:

You can see that an eum address with the extension and proceed to remove it.

However, this does not correct the issue as the same error message is thrown.

Solution

I can’t take full credit for the solution but figured it would be worth blogging since it took over an hour for me to locate a cmdlet that was able to find the find the offending user.  This cmdlet can be found on this forum post:

https://social.technet.microsoft.com/Forums/en-US/55dc00d5-2301-49d0-9a02-482d237c339b/exchange-server-2013-enableummailbox-error-extension-2909-is-already-assigned-to-another-user-on?forum=exchangesvrunifiedmessaging

The cmdlet was:

Get-ADobject -filter * -Properties name,msRTCSIP-Line,telephoneNumber,proxyAddresses | Select-Object name,msRTCSIP-Line,telephoneNumber,@{Name="proxyAddresses";Expression={[string]::join(";",( $_ | Select-Object -ExpandProperty proxyaddresses ))}} | Where-Object { $_.proxyAddresses -like "*9533*" } | Format-table -Wrap -AutoSize

This user was also had Unified Messaging disabled:

However, the eum attribute was visible in the properties of the email address settings:

Removing the attributes corrected the issue.