From e2aeb927de377f34a3a5749a063de409dc6f5e22 Mon Sep 17 00:00:00 2001 From: Daniel Bacon Date: Mon, 15 Mar 2021 21:50:47 -0700 Subject: [PATCH 1/5] fixing EOMT threats detected vs not messaging --- Security/src/EOMT.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Security/src/EOMT.ps1 b/Security/src/EOMT.ps1 index f68bee5b05..a3ea76d4ab 100644 --- a/Security/src/EOMT.ps1 +++ b/Security/src/EOMT.ps1 @@ -537,13 +537,15 @@ function Run-MSERT { $Message += "We highly recommend re-running this script with -RunFullScan. " } $Message += "For additional guidance, see `"$SummaryFile`"." + write-host $Message $RegMessage = "Microsoft Safety Scanner is complete: THREATS DETECTED" Set-LogActivity -Stage $Stage -RegMessage $RegMessage -Message $Message + } else { + $Message = "Microsoft Safety Scanner is complete on $env:computername No known threats detected." + write-host $Message + $RegMessage = "Microsoft Safety Scanner is complete" + Set-LogActivity -Stage $Stage -RegMessage $RegMessage -Message $Message } - - $Message = "Microsoft Safety Scanner is complete on $env:computername No known threats detected." - $RegMessage = "Microsoft Safety Scanner is complete" - Set-LogActivity -Stage $Stage -RegMessage $RegMessage -Message $Message } function Get-ServerVulnStatus { From 216a61bfd390cbda8f0a9f04a32128ca0d3dbcdc Mon Sep 17 00:00:00 2001 From: Daniel Bacon Date: Mon, 15 Mar 2021 21:55:55 -0700 Subject: [PATCH 2/5] removing confusing lang in summary --- Security/src/EOMT.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Security/src/EOMT.ps1 b/Security/src/EOMT.ps1 index a3ea76d4ab..b99278c970 100644 --- a/Security/src/EOMT.ps1 +++ b/Security/src/EOMT.ps1 @@ -657,7 +657,7 @@ function Write-Summary { $header = @" Microsoft Safety Scanner and CVE-2021-26855 mitigation summary Message: Microsoft attempted to mitigate and protect your Exchange server from CVE-2021-26855 and clear malicious files. -For more information on these vulnerabilities please visit https://aka.ms/Exchangevulns. This attempt was successful. +For more information on these vulnerabilities please visit https://aka.ms/Exchangevulns. Please review locations and files as soon as possible and take the recommended action. "@ } else { From b1724f1ab48cb17f658938ee80730b90fefff2de Mon Sep 17 00:00:00 2001 From: Daniel Bacon Date: Tue, 16 Mar 2021 06:46:21 -0700 Subject: [PATCH 3/5] fixed formatting added privacy statement --- Security/src/EOMT.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Security/src/EOMT.ps1 b/Security/src/EOMT.ps1 index b99278c970..61c173a9ef 100644 --- a/Security/src/EOMT.ps1 +++ b/Security/src/EOMT.ps1 @@ -537,12 +537,12 @@ function Run-MSERT { $Message += "We highly recommend re-running this script with -RunFullScan. " } $Message += "For additional guidance, see `"$SummaryFile`"." - write-host $Message + Write-Host $Message $RegMessage = "Microsoft Safety Scanner is complete: THREATS DETECTED" Set-LogActivity -Stage $Stage -RegMessage $RegMessage -Message $Message } else { $Message = "Microsoft Safety Scanner is complete on $env:computername No known threats detected." - write-host $Message + Write-Host $Message $RegMessage = "Microsoft Safety Scanner is complete" Set-LogActivity -Stage $Stage -RegMessage $RegMessage -Message $Message } From c366832f93b78a2480fcc1449454a29e4a9e78c6 Mon Sep 17 00:00:00 2001 From: Daniel Bacon Date: Tue, 16 Mar 2021 06:46:33 -0700 Subject: [PATCH 4/5] fixed formatting added privacy statement --- Security/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Security/README.md b/Security/README.md index 8f250b975d..079218693c 100644 --- a/Security/README.md +++ b/Security/README.md @@ -20,6 +20,8 @@ This is the most effective way to help quickly protect and mitigate your Exchang This a better approach for Exchange deployments with Internet access and for those who want an attempt at automated remediation. We have not observed any impact to Exchange Server functionality via these mitigation methods nor do these mitigation methods make any direct changes that disable features of Exchange. +Use of the Exchange On-premises Mitigation Tool and the Microsoft Saftey Scanner are subject to the terms of the Microsoft Privacy Statement: https://aka.ms/privacy + ### Requirements to run the Exchange On-premises Mitigation Tool * External Internet Connection from your Exchange server (required to download the Microsoft Safety Scanner and the IIS URL Rewrite Module). From 1f5113753355fbe2b56fcc69fae813fed1022752 Mon Sep 17 00:00:00 2001 From: Daniel Bacon Date: Tue, 16 Mar 2021 08:00:50 -0700 Subject: [PATCH 5/5] updating ExchangeMitigations.ps1 remove EMS dep --- Security/src/ExchangeMitigations.ps1 | 174 +++++++++------------------ 1 file changed, 56 insertions(+), 118 deletions(-) diff --git a/Security/src/ExchangeMitigations.ps1 b/Security/src/ExchangeMitigations.ps1 index 83b0209468..d2ef6bd1af 100644 --- a/Security/src/ExchangeMitigations.ps1 +++ b/Security/src/ExchangeMitigations.ps1 @@ -115,7 +115,7 @@ param( function GetMsiProductVersion { param ( - [System.IO.FileInfo]$filename + [string]$filename ) try { @@ -123,132 +123,69 @@ function GetMsiProductVersion { $database = $windowsInstaller.GetType().InvokeMember( "OpenDatabase", "InvokeMethod", $Null, - $windowsInstaller, @($filename.FullName, 0) + $windowsInstaller, @($filename, 0) ) $q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'" + $View = $database.GetType().InvokeMember( "OpenView", "InvokeMethod", $Null, $database, ($q) ) - $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null) - - $record = $View.GetType().InvokeMember( - "Fetch", "InvokeMethod", $Null, $View, $Null - ) + try { + $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null) | Out-Null - $productVersion = $record.GetType().InvokeMember( - "StringData", "GetProperty", $Null, $record, 1 - ) + $record = $View.GetType().InvokeMember( + "Fetch", "InvokeMethod", $Null, $View, $Null + ) - $View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null) + $productVersion = $record.GetType().InvokeMember( + "StringData", "GetProperty", $Null, $record, 1 + ) - return $productVersion + return $productVersion + } finally { + if ($View) { + $View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null) | Out-Null + } + } } catch { throw "Failed to get MSI file version the error was: {0}." -f $_ } } -function Get-InstalledSoftware { - <# - .SYNOPSIS - Retrieves a list of all software installed on a Windows computer. - .EXAMPLE - PS> Get-InstalledSoftware - - This example retrieves all software installed on the local computer. - .PARAMETER ComputerName - If querying a remote computer, use the computer name here. - - .PARAMETER Name - The software title you'd like to limit the query to. - - .PARAMETER Guid - The software GUID you'e like to limit the query to - #> - [CmdletBinding()] +function Get-InstalledSoftwareVersion { param ( - - [Parameter()] [ValidateNotNullOrEmpty()] - [string]$ComputerName = $env:COMPUTERNAME, + [string[]]$Name + ) - [Parameter()] - [ValidateNotNullOrEmpty()] - [string]$Name, + try { + $UninstallKeys = @( + "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall", + "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" + ) - [Parameter()] - [guid]$Guid - ) - process { - try { - $scriptBlock = { - $args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value } - - $UninstallKeys = @( - "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall", - "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" - ) - New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null - $UninstallKeys += Get-ChildItem HKU: | Where-Object { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' } | ForEach-Object { - "HKU:\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall" - } - if (-not $UninstallKeys) { - Write-Warning -Message 'No software registry keys found' - } else { - foreach ($UninstallKey in $UninstallKeys) { - $friendlyNames = @{ - 'DisplayName' = 'Name' - 'DisplayVersion' = 'Version' - } - Write-Verbose -Message "Checking uninstall key [$($UninstallKey)]" - if ($Name) { - $WhereBlock = { $_.GetValue('DisplayName') -like "$Name*" } - } elseif ($GUID) { - $WhereBlock = { $_.PsChildName -eq $Guid.Guid } - } else { - $WhereBlock = { $_.GetValue('DisplayName') } - } - $SwKeys = Get-ChildItem -Path $UninstallKey -ErrorAction SilentlyContinue | Where-Object $WhereBlock - if (-not $SwKeys) { - Write-Verbose -Message "No software keys in uninstall key $UninstallKey" - } else { - foreach ($SwKey in $SwKeys) { - $output = @{ } - foreach ($ValName in $SwKey.GetValueNames()) { - if ($ValName -ne 'Version') { - $output.InstallLocation = '' - if ($ValName -eq 'InstallLocation' -and - ($SwKey.GetValue($ValName)) -and - (@('C:', 'C:\Windows', 'C:\Windows\System32', 'C:\Windows\SysWOW64') -notcontains $SwKey.GetValue($ValName).TrimEnd('\'))) { - $output.InstallLocation = $SwKey.GetValue($ValName).TrimEnd('\') - } - [string]$ValData = $SwKey.GetValue($ValName) - if ($friendlyNames[$ValName]) { - $output[$friendlyNames[$ValName]] = $ValData.Trim() ## Some registry values have trailing spaces. - } else { - $output[$ValName] = $ValData.Trim() ## Some registry values trailing spaces - } - } - } - $output.GUID = '' - if ($SwKey.PSChildName -match '\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b') { - $output.GUID = $SwKey.PSChildName - } - New-Object -TypeName PSObject -Prop $output - } - } + New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null + + $UninstallKeys += Get-ChildItem HKU: | Where-Object { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' } | ForEach-Object { + "HKU:\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall" + } + + foreach ($UninstallKey in $UninstallKeys) { + $SwKeys = Get-ChildItem -Path $UninstallKey -ErrorAction SilentlyContinue + foreach ($n in $Name) { + $SwKeys = $SwKeys | Where-Object { $_.GetValue('DisplayName') -like "$n" } + } + if ($SwKeys) { + foreach ($SwKey in $SwKeys) { + if ($SwKey.GetValueNames().Contains("DisplayVersion")) { + return $SwKey.GetValue("DisplayVersion") } } } - - if ($ComputerName -eq $env:COMPUTERNAME) { - & $scriptBlock $PSBoundParameters - } else { - Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters - } - } catch { - Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } + } catch { + Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } } Function BackendCookieMitigation { @@ -278,7 +215,7 @@ Function BackendCookieMitigation { Write-Verbose "[INFO] Checking for IIS URL Rewrite Module 2 on $env:computername" #If IIS 10 check for URL rewrite 2.1 else URL rewrite 2.0 - $RewriteModule = Get-InstalledSoftware -Name *IIS* | Where-Object { $_.Name -like "*URL*" -and $_.Name -like "*2*" } + $RewriteModule = Get-InstalledSoftwareVersion -Name "*IIS*", "*URL*", "*2*" $IISVersion = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\InetStp\ | Select-Object versionstring $RewriteModuleInstallLog = ($PSScriptRoot + '\' + 'RewriteModuleInstallLog.log') @@ -387,8 +324,8 @@ Function UnifiedMessagingMitigation { ) # UM doesn't apply to Exchange Server 2019 - $exchangeVersion = (Get-ExchangeServer).AdminDisplayVersion - if ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 2) { + $exchangeVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup\') + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { return } @@ -452,8 +389,8 @@ Function ECPAppPoolMitigation { Get-WebAppPoolState -Name $AppPoolName } if ($RollbackMitigation) { - $exchangeVersion = (Get-ExchangeServer).AdminDisplayVersion - if ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 2) { + $exchangeVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup\') + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { if (-not((Get-WebAppPoolState -Name "MSExchangeOABAppPool").value -eq "Stopped")) { StartAndCheckHM } @@ -504,8 +441,9 @@ Function OABAppPoolMitigation { Get-WebAppPoolState -Name $AppPoolName } if ($RollbackMitigation) { - $exchangeVersion = (Get-ExchangeServer).AdminDisplayVersion - if ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 2) { + + $exchangeVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup\') + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { if (-not((Get-WebAppPoolState -Name "MSExchangeECPAppPool").value -eq "Stopped")) { StartAndCheckHM } @@ -562,8 +500,8 @@ Function StopAndCheckHM { Set-Service MSExchangeHM -StartupType Disabled } - $exchangeVersion = (Get-ExchangeServer).AdminDisplayVersion - if (-not ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 0)) { + $exchangeVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup\') + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { $MSExchangeHMR = Get-Service MSExchangeHMRecovery if ($MSExchangeHMR.Status -ne "Stopped") { @@ -585,7 +523,7 @@ Function StopAndCheckHM { } Get-Service MSExchangeHM - if (-not ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 0)) { + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { Get-Service MSExchangeHMRecovery } } @@ -599,8 +537,8 @@ Function StartAndCheckHM { Start-Service MSExchangeHM } - $exchangeVersion = (Get-ExchangeServer).AdminDisplayVersion - if (-not ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 0)) { + $exchangeVersion = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\ExchangeServer\v15\Setup\') + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { $MSExchangeHMR = Get-Service MSExchangeHMRecovery If (((gwmi -Class win32_service | Where-Object { $_.name -eq "MSExchangeHMRecovery" }).StartMode -ne "Auto" )) { @@ -623,7 +561,7 @@ Function StartAndCheckHM { Get-Service MSExchangeHM - if (-not ($exchangeVersion.Major -eq 15 -and $exchangeVersion.Minor -eq 0)) { + if ($exchangeVersion.OwaVersion -notlike "15.0.*") { Get-Service MSExchangeHMRecovery } }