From 5ec1f0c03304c3a706b309cdc0c473e465aae55e Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Wed, 10 Mar 2021 08:40:57 +0100 Subject: [PATCH 1/3] Adding parallel processing, exposing credential --- Security/Test-ProxyLogon.ps1 | 48 ++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/Security/Test-ProxyLogon.ps1 b/Security/Test-ProxyLogon.ps1 index 988bb33815..11a31fed3b 100644 --- a/Security/Test-ProxyLogon.ps1 +++ b/Security/Test-ProxyLogon.ps1 @@ -19,6 +19,7 @@ [CmdletBinding(DefaultParameterSetName = "AsScript")] param ( [Parameter(ParameterSetName = "AsScript", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] + [Alias('Fqdn')] [string[]] $ComputerName, @@ -36,11 +37,14 @@ param ( [Parameter(ParameterSetName = 'AsModule')] [switch] - $Export -) - -process { + $Export, + [Parameter(ParameterSetName = "AsScript")] + [System.Management.Automation.PSCredential] + $Credential +) +begin { + #region Functions function Test-ExchangeProxyLogon { <# .SYNOPSIS @@ -261,7 +265,7 @@ process { $parameters = @{ ScriptBlock = $scriptBlock } - if ($Credential) { $parameters.Credential = $Credential } + if ($Credential) { $parameters['Credential'] = $Credential } } process { if ($null -ne $ComputerName) { @@ -482,17 +486,35 @@ process { } } } + #endregion Functions + + $paramTest = @{ } + if ($Credential) { $paramTest['Credential'] = $Credential } + $paramWrite = @{ + OutPath = $OutPath + } + if ($CollectFiles) { $paramWrite['CollectFiles'] = $true } + if ($DisplayOnly) { + $paramWrite = @{ DisplayOnly = $true} + } + + $computerTargets = New-Object System.Collections.ArrayList +} +process { if ($Export) { Set-Item function:global:Test-ExchangeProxyLogon (Get-Command Test-ExchangeProxyLogon) Set-Item function:global:Write-ProxyLogonReport (Get-Command Write-ProxyLogonReport) - } else { - if ($DisplayOnly) { - $ComputerName | Test-ExchangeProxyLogon | Write-ProxyLogonReport -DisplayOnly - } elseif ($CollectFiles) { - $ComputerName | Test-ExchangeProxyLogon | Write-ProxyLogonReport -OutPath $OutPath -CollectFiles - } else { - $ComputerName | Test-ExchangeProxyLogon | Write-ProxyLogonReport -OutPath $OutPath - } + return } + + # Gather up computer targets as they are piped into the command. + # Passing them to Test-ExchangeProxyLogon in one batch ensures parallel processing + foreach ($computer in $ComputerName) { + $null = $computerTargets.Add($computer) + } +} +end { + if ($Export) { return } + Test-ExchangeProxyLogon -ComputerName $computerTargets.ToArray() @paramTest | Write-ProxyLogonReport @paramWrite } From d98ac9bf2a0d6803e88b185182c2293d9984dec3 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Wed, 10 Mar 2021 10:29:50 +0100 Subject: [PATCH 2/3] replacing tabs in help --- Security/Test-ProxyLogon.ps1 | 62 ++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Security/Test-ProxyLogon.ps1 b/Security/Test-ProxyLogon.ps1 index 11a31fed3b..3198ad173a 100644 --- a/Security/Test-ProxyLogon.ps1 +++ b/Security/Test-ProxyLogon.ps1 @@ -47,31 +47,31 @@ begin { #region Functions function Test-ExchangeProxyLogon { <# - .SYNOPSIS - Checks targeted exchange servers for signs of ProxyLogon vulnerability compromise. + .SYNOPSIS + Checks targeted exchange servers for signs of ProxyLogon vulnerability compromise. - .DESCRIPTION - Checks targeted exchange servers for signs of ProxyLogon vulnerability compromise. + .DESCRIPTION + Checks targeted exchange servers for signs of ProxyLogon vulnerability compromise. - Will do so in parallel if more than one server is specified, so long as names aren't provided by pipeline. - The vulnerabilities are described in CVE-2021-26855, 26858, 26857, and 27065 + Will do so in parallel if more than one server is specified, so long as names aren't provided by pipeline. + The vulnerabilities are described in CVE-2021-26855, 26858, 26857, and 27065 - .PARAMETER ComputerName - The list of server names to scan for signs of compromise. - Do not provide these by pipeline if you want parallel processing. + .PARAMETER ComputerName + The list of server names to scan for signs of compromise. + Do not provide these by pipeline if you want parallel processing. - .PARAMETER Credential - Credentials to use for remote connections. + .PARAMETER Credential + Credentials to use for remote connections. - .EXAMPLE - PS C:\> Test-ExchangeProxyLogon + .EXAMPLE + PS C:\> Test-ExchangeProxyLogon - Scans the current computer for signs of ProxyLogon vulnerability compromise. + Scans the current computer for signs of ProxyLogon vulnerability compromise. - .EXAMPLE - PS C:\> Test-ExchangeProxyLogon -ComputerName (Get-ExchangeServer).Fqdn + .EXAMPLE + PS C:\> Test-ExchangeProxyLogon -ComputerName (Get-ExchangeServer).Fqdn - Scans all exchange servers in the organization for ProxyLogon vulnerability compromises + Scans all exchange servers in the organization for ProxyLogon vulnerability compromises #> [CmdletBinding()] param ( @@ -278,23 +278,23 @@ begin { function Write-ProxyLogonReport { <# - .SYNOPSIS - Processes output of Test-ExchangeProxyLogon for reporting on the console screen. + .SYNOPSIS + Processes output of Test-ExchangeProxyLogon for reporting on the console screen. - .DESCRIPTION - Processes output of Test-ExchangeProxyLogon for reporting on the console screen. + .DESCRIPTION + Processes output of Test-ExchangeProxyLogon for reporting on the console screen. - .PARAMETER InputObject - The reports provided by Test-ExchangeProxyLogon + .PARAMETER InputObject + The reports provided by Test-ExchangeProxyLogon - .PARAMETER OutPath - Path to a FOLDER in which to generate output logfiles. - This command will only write to the console screen if no path is provided. + .PARAMETER OutPath + Path to a FOLDER in which to generate output logfiles. + This command will only write to the console screen if no path is provided. - .EXAMPLE - PS C:\> Test-ExchangeProxyLogon -ComputerName (Get-ExchangeServer).Fqdn | Write-ProxyLogonReport -OutPath C:\logs + .EXAMPLE + PS C:\> Test-ExchangeProxyLogon -ComputerName (Get-ExchangeServer).Fqdn | Write-ProxyLogonReport -OutPath C:\logs - Gather data from all exchange servers in the organization and write a report to C:\logs + Gather data from all exchange servers in the organization and write a report to C:\logs #> [CmdletBinding()] param ( @@ -495,7 +495,7 @@ begin { } if ($CollectFiles) { $paramWrite['CollectFiles'] = $true } if ($DisplayOnly) { - $paramWrite = @{ DisplayOnly = $true} + $paramWrite = @{ DisplayOnly = $true } } $computerTargets = New-Object System.Collections.ArrayList @@ -517,4 +517,4 @@ process { end { if ($Export) { return } Test-ExchangeProxyLogon -ComputerName $computerTargets.ToArray() @paramTest | Write-ProxyLogonReport @paramWrite -} +} \ No newline at end of file From ae6a2dae6dc5f90fe04f219d370ffac131099ab4 Mon Sep 17 00:00:00 2001 From: Bill Long Date: Wed, 10 Mar 2021 09:16:40 -0600 Subject: [PATCH 3/3] Keep progress bars from overwriting each other --- Security/Test-ProxyLogon.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Security/Test-ProxyLogon.ps1 b/Security/Test-ProxyLogon.ps1 index 3198ad173a..cc3fadfe11 100644 --- a/Security/Test-ProxyLogon.ps1 +++ b/Security/Test-ProxyLogon.ps1 @@ -116,14 +116,16 @@ begin { FileList = [System.Collections.ArrayList]@() } - Write-Progress -Activity $Activity + $progressId = [Math]::Abs(($env:COMPUTERNAME).GetHashCode()) + + Write-Progress -Activity $Activity -Id $progressId $sw = New-Object System.Diagnostics.Stopwatch $sw.Start() For ( $i = 0; $i -lt $files.Count; ++$i ) { - if ($sw.ElapsedMilliseconds -gt 500) { - Write-Progress -Activity $Activity -Status "$i / $($files.Count)" -PercentComplete ($i * 100 / $files.Count) + if ($sw.ElapsedMilliseconds -gt 1000) { + Write-Progress -Activity $Activity -Status "$i / $($files.Count)" -PercentComplete ($i * 100 / $files.Count) -Id $progressId $sw.Restart() } @@ -139,7 +141,7 @@ begin { } } - Write-Progress -Activity $Activity -Completed + Write-Progress -Activity $Activity -Id $progressId -Completed return $allResults }