Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 8-8-23 #1795

Merged
merged 5 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .build/cspell-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ hsts
httperr
ietf
imap
inetsrv
Infoworker
Inproc
INSUFF
Expand Down Expand Up @@ -90,6 +91,7 @@ msdcs
MSDTC
MSERT
msert
msipc
msrc
Multiplexor
nato
Expand Down
7 changes: 7 additions & 0 deletions .build/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
".vscode",
"/cspell-words.txt"
],
"patterns": [
{
"name": "return-newline-tab-tab",
"pattern": "\\`r\\`n\\`t\\`t"
}
],
"ignoreRegExpList": ["return-newline-tab-tab"],
"caseSensitive": true,
"overrides": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

. $PSScriptRoot\..\Add-AnalyzedResultInformation.ps1
function Invoke-AnalyzerSecurityCve-2023-21709 {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ref]$AnalyzeResults,

[Parameter(Mandatory = $true)]
[object]$SecurityObject,

[Parameter(Mandatory = $true)]
[object]$DisplayGroupingKey
)

Write-Verbose "Calling: $($MyInvocation.MyCommand)"

<#
Description: Check for CVE-2023-21709 vulnerability
Affected Exchange versions: 2016, 2019
Fix: Remove TokenCacheModule from IIS
Workaround: N/A
#>

if ($SecurityObject.IsEdgeServer -eq $false) {
Write-Verbose "Testing CVE: CVE-2023-21709"

if ($SecurityObject.ExchangeInformation.IISSettings.IISModulesInformation.ModuleList.Name -contains "TokenCacheModule") {
Write-Verbose "TokenCacheModule detected - system is vulnerable to CVE-2023-21709 vulnerability"
$params = @{
AnalyzedInformation = $AnalyzeResults
DisplayGroupingKey = $DisplayGroupingKey
Name = "Security Vulnerability"
Details = ("{0}`r`n`t`tSee: https://portal.msrc.microsoft.com/security-guidance/advisory/{0} for more information." -f "CVE-2023-21709")
DisplayWriteType = "Red"
DisplayTestingValue = "CVE-2023-21709"
AddHtmlDetailRow = $false
}
Add-AnalyzedResultInformation @params
} else {
Write-Verbose "TokenCacheModule wasn't detected and as a result, system is not vulnerable to CVE-2023-21709 vulnerability"
}
} else {
Write-Verbose "Edge Server Role is not affected by this vulnerability as it has no IIS installed"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
. $PSScriptRoot\Invoke-AnalyzerSecurityCve-2021-1730.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityCve-2021-34470.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityCve-2022-21978.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityCve-2023-21709.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityCve-MarchSuSpecial.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityExtendedProtectionConfigState.ps1
. $PSScriptRoot\Invoke-AnalyzerSecurityIISModules.ps1
Expand Down Expand Up @@ -127,6 +128,7 @@ function Invoke-AnalyzerSecurityCveCheck {
"Feb23SU" = (@(NewCveEntry @("CVE-2023-21529", "CVE-2023-21706", "CVE-2023-21707") $ex131619) + (NewCveEntry "CVE-2023-21710" @($ex2016, $ex2019)))
"Mar23SU" = (@(NewCveEntry ("CVE-2023-21707") $ex131619))
"Jun23SU" = (NewCveEntry @("CVE-2023-28310", "CVE-2023-32031") @($ex2016, $ex2019))
"Aug23SU" = (NewCveEntry @("CVE-2023-38181", "CVE-2023-38182", "CVE-2023-38185", "CVE-2023-35368", "CVE-2023-35388") @($ex2016, $ex2019))
}

# Need to organize the list so oldest CVEs come out first.
Expand Down Expand Up @@ -200,6 +202,7 @@ function Invoke-AnalyzerSecurityCveCheck {
Invoke-AnalyzerSecurityCve-2021-1730 -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
Invoke-AnalyzerSecurityCve-2021-34470 -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
Invoke-AnalyzerSecurityCve-2022-21978 -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
Invoke-AnalyzerSecurityCve-2023-21709 -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
Invoke-AnalyzerSecurityCve-MarchSuSpecial -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
# Make sure that these stay as the last one to keep the output more readable
Invoke-AnalyzerSecurityExtendedProtectionConfigState -AnalyzeResults $AnalyzeResults -SecurityObject $securityObject -DisplayGroupingKey $DisplayGroupingKey
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function Invoke-AnalyzerSecuritySettings {

Write-Verbose "Calling: $($MyInvocation.MyCommand)"
$osInformation = $HealthServerObject.OSInformation
$aes256CbcInformation = $HealthServerObject.ExchangeInformation.AES256CBCInformation
$keySecuritySettings = (Get-DisplayResultsGroupingKey -Name "Security Settings" -DisplayOrder $Order)
$baseParams = @{
AnalyzedInformation = $AnalyzeResults
Expand Down Expand Up @@ -331,6 +332,30 @@ function Invoke-AnalyzerSecuritySettings {
}
Add-AnalyzedResultInformation @params

# AES256-CBC encryption support check
$params = $baseParams + @{
Name = "AES256-CBC Protected Content Support"
Details = $true
DisplayWriteType = "Green"
}

if (($aes256CbcInformation.AES256CBCSupportedBuild) -and
($aes256CbcInformation.ValidAESConfiguration -eq $false)) {
$params.Details = ("True" +
"`r`n`t`tThis build supports AES256-CBC protected content, but the configuration is not complete. Exchange Server is not able to decrypt" +
"`r`n`t`tprotected messages which could impact eDiscovery and Journaling tasks. If you use Rights Management Service (RMS) on-premises," +
"`r`n`t`tplease follow the instructions as outlined in the documentation: https://aka.ms/ExchangeCBCKB")
$params.DisplayWriteType = "Yellow"
} elseif ($aes256CbcInformation.AES256CBCSupportedBuild -eq $false) {
$params.Details = ("False" +
"`r`n`t`tThis could lead to scenarios where Exchange Server is no longer able to decrypt protected messages," +
"`r`n`t`tfor example, when sending rights management protected messages using AES256-CBC encryption algorithm," +
"`r`n`t`tor when performing eDiscovery and Journaling tasks." +
"`r`n`t`tMore Information: https://aka.ms/Purview/CBCDetails")
$params.DisplayWriteType = "Red"
}
Add-AnalyzedResultInformation @params

$additionalDisplayValue = [string]::Empty
$smb1Settings = $osInformation.Smb1ServerSettings

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

. $PSScriptRoot\..\..\Helpers\CompareExchangeBuildLevel.ps1
. $PSScriptRoot\..\..\..\..\Shared\Invoke-ScriptBlockHandler.ps1
. $PSScriptRoot\..\..\..\..\Shared\ErrorMonitorFunctions.ps1
function Get-ExchangeAES256CBCDetails {
param(
[Parameter(Mandatory = $false)]
[String]$Server = $env:COMPUTERNAME,

[Parameter(Mandatory = $true)]
[System.Object]$VersionInformation
)

<#
AES256-CBC encryption support check
https://techcommunity.microsoft.com/t5/security-compliance-and-identity/encryption-algorithm-changes-in-microsoft-purview-information/ba-p/3831909
#>

begin {
Write-Verbose "Calling: $($MyInvocation.MyCommand)"
$aes256CBCSupported = $false
$msipcRegistryAclAsExpected = $false
$regPathToCheck = "HKLM:\SOFTWARE\Microsoft\MSIPC\Server"
# Translates to: "NetworkService", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow"
# See: https://learn.microsoft.com/dotnet/api/system.security.accesscontrol.registryaccessrule.-ctor?view=net-7.0#system-security-accesscontrol-registryaccessrule-ctor(system-security-principal-identityreference-system-security-accesscontrol-registryrights-system-security-accesscontrol-inheritanceflags-system-security-accesscontrol-propagationflags-system-security-accesscontrol-accesscontroltype)
$networkServiceAcl = New-Object System.Security.AccessControl.RegistryAccessRule(
[System.Security.Principal.SecurityIdentifier]::new("S-1-5-20"), 983103, 3, 0, 0
)
} process {
# First, check if the build running on the server supports AES256-CBC
if (Test-ExchangeBuildGreaterOrEqualThanSecurityPatch -CurrentExchangeBuild $VersionInformation -SU "Aug23SU") {

Write-Verbose "AES256-CBC encryption for information protection is supported by this Exchange Server build"
$aes256CBCSupported = $true

# As build supports AES256-CBC, next step is to check that the registry key exists and permissions are set as expected
$params = @{
ComputerName = $Server
ScriptBlock = { Test-Path -Path $regPathToCheck }
CatchActionFunction = ${Function:Invoke-CatchActions}
}

if ((Invoke-ScriptBlockHandler @params) -eq $false) {
Write-Verbose "Unable to query Acl of registry key $regPathToCheck assuming that the key doesn't exist"
} else {
$params.ScriptBlock = { Get-Acl -Path $regPathToCheck }
$acl = Invoke-ScriptBlockHandler @params

# ToDo: As we have multiple places in HC where we query acls, we should consider creating a function
# that can be used to do the acl call, similar to what we do in Get-ExchangeRegistryValues.ps1.
Write-Verbose "Registry key exists and Acl was successfully queried - validating Acl now"
try {
$aclMatch = $acl.Access.Where({
($_.RegistryRights -eq $networkServiceAcl.RegistryRights) -and
($_.AccessControlType -eq $networkServiceAcl.AccessControlType) -and
($_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]) -eq $networkServiceAcl.IdentityReference) -and
($_.InheritanceFlags -eq $networkServiceAcl.InheritanceFlags) -and
($_.PropagationFlags -eq $networkServiceAcl.PropagationFlags)
})

if (@($aclMatch).Count -ge 1) {
Write-Verbose "Acl for NetworkService is as expected"
$msipcRegistryAclAsExpected = $true
} else {
Write-Verbose "Acl for NetworkService was not found or is not as expected"
}
} catch {
Write-Verbose "Unable to verify Acl on registry key $regPathToCheck"
Invoke-CatchActions
}
}
} else {
Write-Verbose "AES256-CBC encryption for information protection is not supported by this Exchange Server build"
}
} end {
return [PSCustomObject]@{
AES256CBCSupportedBuild = $aes256CBCSupported
RegistryKeyConfiguredAsExpected = $msipcRegistryAclAsExpected
ValidAESConfiguration = (($aes256CBCSupported) -and ($msipcRegistryAclAsExpected))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
. $PSScriptRoot\..\..\..\..\Shared\Get-ExchangeSettingOverride.ps1
. $PSScriptRoot\IISInformation\Get-ExchangeAppPoolsInformation.ps1
. $PSScriptRoot\IISInformation\Get-ExchangeServerIISSettings.ps1
. $PSScriptRoot\Get-ExchangeAES256CBCDetails.ps1
. $PSScriptRoot\Get-ExchangeApplicationConfigurationFileValidation.ps1
. $PSScriptRoot\Get-ExchangeConnectors.ps1
. $PSScriptRoot\Get-ExchangeDependentServices.ps1
Expand Down Expand Up @@ -147,6 +148,13 @@ function Get-ExchangeInformation {
}
}
$eemsEndpointResults = Invoke-ScriptBlockHandler @eemsEndpointParams

Write-Verbose "Checking AES256-CBC information protection readiness and configuration"
$aes256CbcParams = @{
Server = $Server
VersionInformation = $versionInformation
}
$aes256CbcDetails = Get-ExchangeAES256CBCDetails @aes256CbcParams
} end {

Write-Verbose "Exiting: Get-ExchangeInformation"
Expand All @@ -169,6 +177,7 @@ function Get-ExchangeInformation {
IISSettings = $iisSettings
SettingOverrides = $settingOverrides
FIPFSUpdateIssue = $FIPFSUpdateIssue
AES256CBCInformation = $aes256CbcDetails
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,15 @@ Describe "Testing Health Checker by Mock Data Imports - Exchange 2013" {
TestObjectMatch "SMB1 Installed" "True" -WriteType "Red"
TestObjectMatch "SMB1 Blocked" "False" -WriteType "Red"

$Script:ActiveGrouping.Count | Should -Be 82
$Script:ActiveGrouping.Count | Should -Be 83
}

It "Display Results - Security Vulnerability" {
SetActiveDisplayGrouping "Security Vulnerability"

$cveTests = $Script:ActiveGrouping.TestingValue | Where-Object { ($_.GetType().Name -eq "String") -and ($_.StartsWith("CVE")) }
$cveTests.Contains("CVE-2020-1147") | Should -Be $true
$cveTests.Count | Should -Be 53
$cveTests.Count | Should -Be 54
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,19 @@ Describe "Testing Health Checker by Mock Data Imports - Exchange 2016" {
TestObjectMatch "Pattern service" "Unreachable`r`n`t`tMore information: https://aka.ms/HelpConnectivityEEMS" -WriteType "Yellow"
TestObjectMatch "Telemetry enabled" "False"

$Script:ActiveGrouping.Count | Should -Be 95
$Script:ActiveGrouping.Count | Should -Be 96
}

It "Display Results - Security Vulnerability" {
SetActiveDisplayGrouping "Security Vulnerability"

$cveTests = GetObject "Security Vulnerability"
$cveTests.Contains("CVE-2020-1147") | Should -Be $true
$cveTests.Count | Should -Be 33
$cveTests.Count | Should -Be 39
$downloadDomains = GetObject "CVE-2021-1730"
$downloadDomains.DownloadDomainsEnabled | Should -Be "false"

$Script:ActiveGrouping.Count | Should -Be 40
$Script:ActiveGrouping.Count | Should -Be 46
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,15 @@ Describe "Testing Health Checker by Mock Data Imports" {
TestObjectMatch "Strict Mode disabled" "False" -WriteType "Green"
TestObjectMatch "BaseTypeCheckForDeserialization disabled" "False" -WriteType "Green"

$Script:ActiveGrouping.Count | Should -Be 78
$Script:ActiveGrouping.Count | Should -Be 79
}

It "Display Results - Security Vulnerability" {
SetActiveDisplayGrouping "Security Vulnerability"

$cveTests = GetObject "Security Vulnerability"
$cveTests.Contains("CVE-2020-1147") | Should -Be $true
$cveTests.Count | Should -Be 33
$cveTests.Count | Should -Be 39
$downloadDomains = GetObject "CVE-2021-1730"
$downloadDomains.DownloadDomainsEnabled | Should -Be "False"
TestObjectMatch "Extended Protection Vulnerable" "True" -WriteType "Red"
Expand Down
Loading