Skip to content
Merged
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
116 changes: 70 additions & 46 deletions Security/Test-ProxyLogon.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
[CmdletBinding(DefaultParameterSetName = "AsScript")]
param (
[Parameter(ParameterSetName = "AsScript", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[Alias('Fqdn')]
[string[]]
$ComputerName,

Expand All @@ -36,38 +37,41 @@ param (

[Parameter(ParameterSetName = 'AsModule')]
[switch]
$Export
)

process {
$Export,

[Parameter(ParameterSetName = "AsScript")]
[System.Management.Automation.PSCredential]
$Credential
)
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 (
Expand Down Expand Up @@ -112,14 +116,16 @@ process {
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()
}

Expand All @@ -135,7 +141,7 @@ process {
}
}

Write-Progress -Activity $Activity -Completed
Write-Progress -Activity $Activity -Id $progressId -Completed

return $allResults
}
Expand Down Expand Up @@ -261,7 +267,7 @@ process {
$parameters = @{
ScriptBlock = $scriptBlock
}
if ($Credential) { $parameters.Credential = $Credential }
if ($Credential) { $parameters['Credential'] = $Credential }
}
process {
if ($null -ne $ComputerName) {
Expand All @@ -274,23 +280,23 @@ process {

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 (
Expand Down Expand Up @@ -482,17 +488,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
}