Forum Discussion

blushta's avatar
Mar 25, 2025

HTTP Response Headers Hardening for Exchange 2019 on Windows Server 2022

Category: Security Hardening

Issue:
Currently, Exchange 2019 running on Windows Server 2022 does not have strict HTTP response headers configured, leaving it potentially vulnerable to security threats such as MIME type sniffing, clickjacking, and cross-site scripting (XSS) attacks.

Objective:
Harden the security of Exchange 2019 web services by enabling the following HTTP response headers:

X-Content-Type-Options: Prevents MIME type sniffing by forcing browsers to respect declared content types.

X-Frame-Options: Prevents embedding of Exchange web pages in iframes to mitigate clickjacking attacks.

X-XSS-Protection or Content-Security-Policy (CSP): Protects against reflected XSS attacks (X-XSS-Protection is deprecated, CSP is preferred).

I have found this article; can anyone tell me if it applies to Exchange 2019 as well?

HTTP Security Headers - Icewolf Blog

Thank you

3 Replies

  • ScarlettDavis's avatar
    ScarlettDavis
    Bronze Contributor

    1. Key security header configuration
     Response headers that must be added:
    powershell
    # Set via IIS Manager or PowerShell
    Set-WebConfigurationProperty -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\Default Web Site” -Name “X-Content -Type-Options” -Value ”nosniff”
    Set-WebConfigurationProperty -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\Default Web Site” -Name “X-Frame- Options” -Value ”SAMEORIGIN”
    Set-WebConfigurationProperty -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\Default Web Site” -Name “Strict- Transport-Security” -Value ”max-age=31536000; includeSubDomains”
    2. Tuning of specific Exchange components
     OWA/ECP hardening:
    powershell
    # Add CSP header for OWA virtual directory
    Set-WebConfigurationProperty -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\Default Web Site\owa” -Name ” Content-Security-Policy” -Value ‘default-src ’self‘ https:; script-src ’self‘ ’unsafe-inline‘ ’unsafe-eval‘ https:; style-src ’self‘ ’unsafe- inline' https:”
    3. Server-level hardening
    Disable unnecessary information exposure:
    powershell.
    # Remove Server header
    Set-WebConfigurationProperty -Filter “/system.webServer/rewrite/outboundRules” -PSPath “IIS:\” -Name “enabled” -Value $true
    Add-WebConfigurationProperty -Filter “/system.webServer/rewrite/outboundRules” -PSPath “IIS:\” -Name “rule” -Value @{name='Remove Server Header'; patternSyntax='Wildcard'; matchServerVariable='RESPONSE_Server'; action='AbortRequest'}
    4. Automated Deployment Scripts
     Complete hardening script:
    powershell
    $headers = @{
        “X-Content-Type-Options” = ”nosniff”
        “X-Frame-Options” = ”SAMEORIGIN”
        “Strict-Transport-Security” = ”max-age=31536000; includeSubDomains”
        “Referrer-Policy” = ”strict-origin-when-cross-origin”
    }
    foreach ($site in (Get-Website)) {
        foreach ($header in $headers.GetEnumerator()) {
            Set-WebConfigurationProperty -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\$($site.Name)” -Name $header.Key -Value $header.Value
        }
    }
    5. Validation and Testing
     Check the tool:
    Use curl validation:
    bash
    curl -I https://your-exchange-server.com/owa
    Online scanning:
    SecurityHeaders.com
    Mozilla Observatory
    6. Rollback Programs
     Emergency recovery:
    powershell
    # Remove all custom headers
    Clear-WebConfiguration -Filter “/system.webServer/httpProtocol/customHeaders” -PSPath “IIS:\Sites\Default Web Site”
    Best Practice:
    Verify in a test environment first
    Backup IIS configuration before modification (%windir%\system32\inetsrv\config\applicationHost.config)

    • blushta's avatar
      blushta
      MCT

      Dear Davis,

      Thank you for the PowerShell script; however, it seems that that script has a syntax error, which is taking time to correct. I have created these response headers manually.

      Thank you

      b.l

      • MisterWolf18's avatar
        MisterWolf18
        Copper Contributor

        I don't believe the above commands are going to work because Exchange doesn't have a customheaders section added to the web.config by default. I'd be sure to make a backup of your web.config 1st, and then manually add the customheaders section or try adding each individual value via PS using the Add-WebConfiguration property (Set-WebConfigurationProperty requires the property to exist, it won't create it) and specifying a collection to add the custom headers into. 

         

        I'm testing adding headers by hand and trying to use:

        Add-WebConfigurationProperty -PSPath “IIS:\Sites\Default Web Site” -Filter "system.webServer/httpProtocol/customHeaders" -Name "collection" -Value @{name="X-Frame-Options";value="SAMEORIGIN"}

         

        Here's a script from the PS Gallery that is checking for the existence of headers and using Set-WebConfigurationProperty if found or Add-WebConfigurationProperty if not found. Just a matter of repeating the same Add-WebVConfigurationProperty cmdlet and changing the -Value @{name="header",value="value"} to include the header and corresponding value you want to add. Should just be able to run those cmdlets 4 or 5 times to set what you want, no script needed.

        https://www.powershellgallery.com/packages/Outsystems.SetupTools/1.6.30.0/Content/Functions%5CSet-OSPlatformSecuritySettings.ps1#:~:text=Else%20%7B-,Add%2DWebConfigurationProperty%20%2DPSPath%20%22IIS:%5CSites%5CDefault%20Web,Output%20%22Security%20settings%20successfully%20applied%22