From ff06672de291d9158f09881969866e908f31e356 Mon Sep 17 00:00:00 2001 From: Akash Sharma <77853107+SharmaAkash1@users.noreply.github.com> Date: Thu, 18 Mar 2021 21:26:26 +0530 Subject: [PATCH 1/3] Adding changes to reduce false positives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The changes made in the script are as follows: 1. For Cve26858 we only show the error if the path in the error message “Download failed and temporary file needs to be removed” is invalid (does not start with C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\OAB) 2. For set-virtual directory we throw an error only if the url is invalid 3. For the get-suspicious files we only show those if one of the 4 vulnerabilities (Cve26855 Or Cve26857 or Cve26858 or Cve27065 ) is found. This was done because even customers who did not have any vulnerabilities were alerted due to the presence of some zip files that they had created in their system. These false positives lead to a lot of confusion and the uneasiness for the customers. 4. We also show an additional error message regarding web shells if we find logs of successful reset-virtualdirectory hits (having a bad anchor mailbox object) in the httpsproxy folder. --- Security/src/Test-ProxyLogon.ps1 | 141 ++++++++++++++++++++++++------- 1 file changed, 110 insertions(+), 31 deletions(-) diff --git a/Security/src/Test-ProxyLogon.ps1 b/Security/src/Test-ProxyLogon.ps1 index 4a7aa28953..4a0bde0013 100644 --- a/Security/src/Test-ProxyLogon.ps1 +++ b/Security/src/Test-ProxyLogon.ps1 @@ -1,4 +1,4 @@ -# Checks for signs of exploit from CVE-2021-26855, 26858, 26857, and 27065. +# Checks for signs of exploit from CVE-2021-26855, 26858, 26857, and 27065. # # Examples # @@ -109,7 +109,7 @@ begin { "HttpStatus" ) - $files = (Get-ChildItem -Recurse -Path $HttpProxyPath -Filter '*.log').FullName + $files = [System.Array](Get-ChildItem -Recurse -Path $HttpProxyPath -Filter '*.log').FullName $allResults = @{ Hits = [System.Collections.ArrayList]@() @@ -169,8 +169,30 @@ begin { Write-Host " Exchange 2013 or later not found. Skipping CVE-2021-26858 test." return } + + $allResults = @{ + downloadPaths = [System.Collections.ArrayList]@() + filePaths = [System.Collections.ArrayList]@() + } - Get-ChildItem -Recurse -Path "$exchangePath\Logging\OABGeneratorLog" | Select-String "Download failed and temporary file" -List | Select-Object -ExpandProperty Path + $files = [System.Array](Get-ChildItem -Recurse -Path "$exchangePath\Logging\OABGeneratorLog" | Select-String "Download failed and temporary file" -List | Select-Object -ExpandProperty Path) + + for( $i=0; $i -lt $files.Count; $i++) + { + $maliciousPathFound = $false + $loginstance = Select-String -Path $files[$i] -Pattern "Download failed and temporary file" + foreach ($logLine in $loginstance) { + $path = ([String]$logLine | Select-String -Pattern 'Download failed and temporary file (.*?) needs to be removed').Matches.Groups[1].value + if($path -ne $null -and (-not ($path.StartsWith("'$exchangePath" + "ClientAccess\OAB","CurrentCultureIgnoreCase")))){ + [Void]$allResults.downloadPaths.Add( [String]$path ) + $maliciousPathFound = $true + } + } + if($maliciousPathFound){ + $allResults.FilePaths.Add([String]$files[$i]) + } + } + return $allResults } function Get-Cve27065 { @@ -178,12 +200,37 @@ begin { param () $exchangePath = Get-ExchangeInstallPath - if ($null -eq $exchangePath) { - Write-Host " Exchange 2013 or later not found. Skipping CVE-2021-27065 test." - return + + $outProps = @( + "DateTime", "RequestId", "ClientIPAddress", "UrlHost", + "UrlStem", "RoutingHint", "UserAgent", "AnchorMailbox", + "HttpStatus" + ) + + $files =[System.Array](Get-ChildItem -Recurse -Path "$exchangePath\Logging\HttpProxy\Ecp" -Filter '*.log').FullName + $allResults = @{ + resetVDirHits = [System.Collections.ArrayList]@() + resetVDirFiles = [System.Collections.ArrayList]@() + setVDirMaliciousUrlLogs = [System.Collections.ArrayList]@() } + For ( $i = 0; $i -lt $files.Count; ++$i ) { - Get-ChildItem -Recurse -Path "$exchangePath\Logging\ECP\Server\*.log" -ErrorAction SilentlyContinue | Select-String "Set-.+VirtualDirectory" -List | Select-Object -ExpandProperty Path + if ((Get-ChildItem $files[$i] -ErrorAction SilentlyContinue | Select-String -Pattern "ServerInfo~").Count -gt 0) { + + $FoundMaliciousResetVDir = $false + Import-Csv -Path $files[$i] -ErrorAction SilentlyContinue | Where-Object { $_.AnchorMailbox -Like 'ServerInfo~*/*Reset*VirtualDirectory#' -and $_.HttpStatus -eq 200} | + Select-Object -Property $outProps | + ForEach-Object { + [Void]$allResults.resetVDirHits.Add( $_ ) + $FoundMaliciousResetVDir = $true + } + if($FoundMaliciousResetVDir){ + [Void]$allResults.resetVDirFiles.Add( $files[$i] ) + } + } + } + $allResults.setVDirMaliciousUrlLogs = Get-ChildItem -Recurse -Path "$exchangePath\Logging\ECP\Server\*.log" -ErrorAction SilentlyContinue | Select-String "Set-.+VirtualDirectory.+?(?=Url).+<\w+.*>(.*?)<\/\w+>.+?(?=VirtualDirectory)" -List | Select-Object -ExpandProperty Path + return $allResults } function Get-SuspiciousFile { @@ -260,14 +307,15 @@ begin { ComputerName = $env:COMPUTERNAME Cve26855 = Get-Cve26855 Cve26857 = @(Get-Cve26857) - Cve26858 = @(Get-Cve26858) - Cve27065 = @(Get-Cve27065) - Suspicious = @(Get-SuspiciousFile) + Cve26858 = Get-Cve26858 + Cve27065 = Get-Cve27065 LogAgeDays = Get-LogAge IssuesFound = $false + Suspicious = $null } - if ($results.Cve26855.Hits.Count -or $results.Cve26857.Count -or $results.Cve26858.Count -or $results.Cve27065.Count -or $results.Suspicious.Count) { + if($results.Cve26855.Hits.Count -or $results.Cve26857.Count -or $results.Cve26858.downloadPaths.Count -or $results.Cve27065.resetVDirHits.Count -or $results.Cve27065.setVDirMaliciousUrlLogs.Count){ + $results.Suspicious = @(Get-SuspiciousFile) $results.IssuesFound = $true } @@ -416,36 +464,40 @@ begin { } Write-Host "" } - if ($report.Cve26858.Count -gt 0) { + if ($report.Cve26858.downloadPaths.Count -gt 0) { Write-Host " [CVE-2021-26858] Suspicious activity found in OAB generator logs!" -ForegroundColor Red - Write-Host " Please review the following files for 'Download failed and temporary file' entries:" - foreach ($entry in $report.Cve26858) { - Write-Host " $entry" - if ($CollectFiles -and $isLocalMachine) { - Write-Host " Copying Files:" - if (-not (Test-Path -Path "$($LogFileOutPath)\CVE26858")) { - Write-Host " Creating CVE26858 Collection Directory`n`r" - New-Item "$($LogFileOutPath)\CVE26858" -ItemType Directory -Force | Out-Null - } + Write-Host " Webshells possibly downloaded in file system. Explore below locations:" -ForegroundColor Red + if (-not $DisplayOnly) { + $newFileDownloadPaths = Join-Path -Path $OutPath -ChildPath "$($report.ComputerName)-Cve-2021-26858-DownloadPaths.log" + $newFileForFilePaths = Join-Path -Path $OutPath -ChildPath "$($report.ComputerName)-Cve-2021-26858.log" + $report.Cve26858.downloadPaths | Set-Content -Path $newFileDownloadPaths + $report.Cve26858.filePaths | Set-Content -Path $newFileForFilePaths + Write-Host " Report exported to: $newFileForFilePaths" + Write-Host " Report exported to: $newFileDownloadPaths" + } else { + $report.Cve26858.downloadPaths | Out-Host + } + if ($CollectFiles -and $isLocalMachine) { + Write-Host " Copying Files:" + if (-not (Test-Path -Path "$($LogFileOutPath)\CVE26858")) { + Write-Host " Creating CVE26858 Collection Directory" + New-Item "$($LogFileOutPath)\CVE26858" -ItemType Directory -Force | Out-Null + } + foreach ($entry in $report.Cve26858.filePaths) { if (Test-Path -Path $entry) { Write-Host " Copying $($entry) to $($LogFileOutPath)\CVE26858" -ForegroundColor Green Copy-Item -Path $entry -Destination "$($LogFileOutPath)\CVE26858" } else { - Write-Host " Warning: Unable to copy file $($entry.Path). File does not exist.`n`r " -ForegroundColor Red + Write-Host " Warning: Unable to copy file $($entry). File does not exist." -ForegroundColor Red } } } - if (-not $DisplayOnly) { - $newFile = Join-Path -Path $OutPath -ChildPath "$($report.ComputerName)-Cve-2021-26858.log" - $report.Cve26858 | Set-Content -Path $newFile - Write-Host " Report exported to: $newFile" - } Write-Host "" } - if ($report.Cve27065.Count -gt 0) { + if ($report.Cve27065.setVDirMaliciousUrlLogs.Count -gt 0) { Write-Host " [CVE-2021-27065] Suspicious activity found in ECP logs!" -ForegroundColor Red - Write-Host " Please review the following files for 'Set-*VirtualDirectory' entries:" - foreach ($entry in $report.Cve27065) { + Write-Host " Please review the following files for 'Set-*VirtualDirectory' entries (potentially malicious urls used):" + foreach ($entry in $report.Cve27065.setVDirMaliciousUrlLogs) { Write-Host " $entry" if ($CollectFiles -and $isLocalMachine) { Write-Host " Copying Files:" @@ -463,11 +515,38 @@ begin { } if (-not $DisplayOnly) { $newFile = Join-Path -Path $OutPath -ChildPath "$($report.ComputerName)-Cve-2021-27065.log" - $report.Cve27065 | Set-Content -Path $newFile + $report.Cve27065.setVDirMaliciousUrlLogs | Set-Content -Path $newFile Write-Host " Report exported to: $newFile" } Write-Host "" } + if ($report.Cve27065.resetVDirHits.Count -gt 0) { + Write-Host " [CVE-2021-27065] Webshell possibly downloaded in file system" -ForegroundColor Red + Write-Host " Please scan your file system for any malicious webshells. Reset-VirtualDirectory entries:" + if (-not $DisplayOnly) { + $newFile = Join-Path -Path $OutPath -ChildPath "$($report.ComputerName)-Cve-2021-27065-ResetVDir.csv" + $report.Cve27065.resetVDirHits | Export-Csv -Path $newFile + Write-Host " Report exported to: $newFile" + } else { + $report.Cve27065.resetVDirHits | Format-Table DateTime, AnchorMailbox -AutoSize | Out-Host + } + if ($CollectFiles -and $isLocalMachine) { + Write-Host " Copying Files:" + if (-not (Test-Path -Path "$($LogFileOutPath)\Cve27065")) { + Write-Host " Creating Cve27065 Collection Directory" + New-Item "$($LogFileOutPath)\Cve27065" -ItemType Directory -Force | Out-Null + } + foreach ($entry in $report.Cve27065.resetVDirFiles) { + if (Test-Path -Path $entry) { + Write-Host " Copying $($entry) to $($LogFileOutPath)\Cve27065" -ForegroundColor Green + Copy-Item -Path $entry -Destination "$($LogFileOutPath)\Cve27065" + } else { + Write-Host " Warning: Unable to copy file $($entry). File does not exist." -ForegroundColor Red + } + } + } + Write-Host "" + } if ($report.Suspicious.Count -gt 0) { Write-Host " Other suspicious files found: $(@($report.Suspicious).Count)" if (-not $DisplayOnly) { From c85f083682bf9de4776f8cd15901ca7a527f4fed Mon Sep 17 00:00:00 2001 From: SharmaAkash1 Date: Thu, 18 Mar 2021 22:57:02 +0530 Subject: [PATCH 2/3] Formatting fixes to tets-proxyLogon --- Security/src/Test-ProxyLogon.ps1 | 43 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Security/src/Test-ProxyLogon.ps1 b/Security/src/Test-ProxyLogon.ps1 index 4a0bde0013..5be61dde8e 100644 --- a/Security/src/Test-ProxyLogon.ps1 +++ b/Security/src/Test-ProxyLogon.ps1 @@ -1,4 +1,4 @@ -# Checks for signs of exploit from CVE-2021-26855, 26858, 26857, and 27065. +# Checks for signs of exploit from CVE-2021-26855, 26858, 26857, and 27065. # # Examples # @@ -169,29 +169,28 @@ begin { Write-Host " Exchange 2013 or later not found. Skipping CVE-2021-26858 test." return } - + $allResults = @{ downloadPaths = [System.Collections.ArrayList]@() - filePaths = [System.Collections.ArrayList]@() + filePaths = [System.Collections.ArrayList]@() } $files = [System.Array](Get-ChildItem -Recurse -Path "$exchangePath\Logging\OABGeneratorLog" | Select-String "Download failed and temporary file" -List | Select-Object -ExpandProperty Path) - for( $i=0; $i -lt $files.Count; $i++) - { + for ( $i = 0; $i -lt $files.Count; $i++) { $maliciousPathFound = $false $loginstance = Select-String -Path $files[$i] -Pattern "Download failed and temporary file" foreach ($logLine in $loginstance) { $path = ([String]$logLine | Select-String -Pattern 'Download failed and temporary file (.*?) needs to be removed').Matches.Groups[1].value - if($path -ne $null -and (-not ($path.StartsWith("'$exchangePath" + "ClientAccess\OAB","CurrentCultureIgnoreCase")))){ + if ($null -ne $path -and (-not ($path.StartsWith("'$exchangePath" + "ClientAccess\OAB", "CurrentCultureIgnoreCase")))) { [Void]$allResults.downloadPaths.Add( [String]$path ) $maliciousPathFound = $true } } - if($maliciousPathFound){ + if ($maliciousPathFound) { $allResults.FilePaths.Add([String]$files[$i]) } - } + } return $allResults } @@ -207,29 +206,29 @@ begin { "HttpStatus" ) - $files =[System.Array](Get-ChildItem -Recurse -Path "$exchangePath\Logging\HttpProxy\Ecp" -Filter '*.log').FullName + $files = [System.Array](Get-ChildItem -Recurse -Path "$exchangePath\Logging\HttpProxy\Ecp" -Filter '*.log').FullName $allResults = @{ - resetVDirHits = [System.Collections.ArrayList]@() - resetVDirFiles = [System.Collections.ArrayList]@() + resetVDirHits = [System.Collections.ArrayList]@() + resetVDirFiles = [System.Collections.ArrayList]@() setVDirMaliciousUrlLogs = [System.Collections.ArrayList]@() } For ( $i = 0; $i -lt $files.Count; ++$i ) { if ((Get-ChildItem $files[$i] -ErrorAction SilentlyContinue | Select-String -Pattern "ServerInfo~").Count -gt 0) { - + $FoundMaliciousResetVDir = $false - Import-Csv -Path $files[$i] -ErrorAction SilentlyContinue | Where-Object { $_.AnchorMailbox -Like 'ServerInfo~*/*Reset*VirtualDirectory#' -and $_.HttpStatus -eq 200} | - Select-Object -Property $outProps | - ForEach-Object { - [Void]$allResults.resetVDirHits.Add( $_ ) - $FoundMaliciousResetVDir = $true + Import-Csv -Path $files[$i] -ErrorAction SilentlyContinue | Where-Object { $_.AnchorMailbox -Like 'ServerInfo~*/*Reset*VirtualDirectory#' -and $_.HttpStatus -eq 200 } | + Select-Object -Property $outProps | + ForEach-Object { + [Void]$allResults.resetVDirHits.Add( $_ ) + $FoundMaliciousResetVDir = $true + } + if ($FoundMaliciousResetVDir) { + [Void]$allResults.resetVDirFiles.Add( $files[$i] ) } - if($FoundMaliciousResetVDir){ - [Void]$allResults.resetVDirFiles.Add( $files[$i] ) - } } } - $allResults.setVDirMaliciousUrlLogs = Get-ChildItem -Recurse -Path "$exchangePath\Logging\ECP\Server\*.log" -ErrorAction SilentlyContinue | Select-String "Set-.+VirtualDirectory.+?(?=Url).+<\w+.*>(.*?)<\/\w+>.+?(?=VirtualDirectory)" -List | Select-Object -ExpandProperty Path + $allResults.setVDirMaliciousUrlLogs = Get-ChildItem -Recurse -Path "$exchangePath\Logging\ECP\Server\*.log" -ErrorAction SilentlyContinue | Select-String "Set-.+VirtualDirectory.+?(?=Url).+<\w+.*>(.*?)<\/\w+>.+?(?=VirtualDirectory)" -List | Select-Object -ExpandProperty Path return $allResults } @@ -314,7 +313,7 @@ begin { Suspicious = $null } - if($results.Cve26855.Hits.Count -or $results.Cve26857.Count -or $results.Cve26858.downloadPaths.Count -or $results.Cve27065.resetVDirHits.Count -or $results.Cve27065.setVDirMaliciousUrlLogs.Count){ + if ($results.Cve26855.Hits.Count -or $results.Cve26857.Count -or $results.Cve26858.downloadPaths.Count -or $results.Cve27065.resetVDirHits.Count -or $results.Cve27065.setVDirMaliciousUrlLogs.Count) { $results.Suspicious = @(Get-SuspiciousFile) $results.IssuesFound = $true } From 3694aa4952a0b1098f529d4608183594ee2adb33 Mon Sep 17 00:00:00 2001 From: SharmaAkash1 Date: Thu, 18 Mar 2021 23:04:28 +0530 Subject: [PATCH 3/3] Used workaround to fix formatting error being thrown --- Security/src/Test-ProxyLogon.ps1 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Security/src/Test-ProxyLogon.ps1 b/Security/src/Test-ProxyLogon.ps1 index 5be61dde8e..6027e3b166 100644 --- a/Security/src/Test-ProxyLogon.ps1 +++ b/Security/src/Test-ProxyLogon.ps1 @@ -216,14 +216,12 @@ begin { if ((Get-ChildItem $files[$i] -ErrorAction SilentlyContinue | Select-String -Pattern "ServerInfo~").Count -gt 0) { - $FoundMaliciousResetVDir = $false Import-Csv -Path $files[$i] -ErrorAction SilentlyContinue | Where-Object { $_.AnchorMailbox -Like 'ServerInfo~*/*Reset*VirtualDirectory#' -and $_.HttpStatus -eq 200 } | Select-Object -Property $outProps | ForEach-Object { [Void]$allResults.resetVDirHits.Add( $_ ) - $FoundMaliciousResetVDir = $true } - if ($FoundMaliciousResetVDir) { + if ($allResults.resetVDirHits.Count -gt 0) { [Void]$allResults.resetVDirFiles.Add( $files[$i] ) } }