Posts tagged “Report Failed RDP Logon Attempts

Using PowerShell to block unauthorized access


In a prior blog post titled ‘Using PowerShell to report on failed Remote Desktop logon attempts‘, I described how to use AZSBTools PowerShell module functions Report-FailureAudit and Summarize-FailureAudit to report on and summarize certain event log events that indicate an attempt to gain unauthorized access to a Windows computer.

In this post I expand on this effort by automating remediation in the form of creating/updating Windows firewall rule to block the IP addresses from which the unauthorized access attempts originate. This is achieved by the Update-WindowsFirewall and the Block-FailedLogonIPs functions with support from the Backup-EventLog and the Clear-SBEventLog functions of the AZSBTools PowerShell module.

Backup-EventLog is a function to backup one or more Windows Event Logs. For example:

Backup-EventLog -EventLogName Application,Security,Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational -BackupFolder C:\Logs

Note that backing up some logs like Security log may require elevated permissions

Clear-SBEventLog is a function to clear one or more Windows event logs. Unlike the native Clear-EventLog, this function can clear all Windows event logs. This function requires elevated permissions. Example:

$LogList = @(‘Application’,’Security’,’Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational’)
Backup-EventLog -EventLogName $LogList -BackupFolder C:\Logs
Clear-SBEventLog -EventLogName $LogList -Confirm:$false

 

Update-WindowsFirewall

This function accepts as input one or more IPv4 addresses or CIDR ranges to be blocked (BlockIPList), and one or more IPv4 addresses or CIDR ranges (AllowIPList) to ensure that they’re not blocked (you don’t want to cut off legitimate users if they enter the wrong password once :)). The firewall rule name defaults to BlockAttackers but you can enter your own.

Example

If you have one or more CSV reports from the Summarize-FailureAudit function such as

$BlockIPList = (Get-ChildItem -Path .\ -Filter Summarize-FailureAudit_All*.csv | foreach { Import-Csv $_.FullName }).SourceIP | select -Unique | sort

This line searches for CSV reports generated by the Summarize-FailureAudit function in the current folder,  imports the SourceIP column, and deduplicates the IP List.

$AllowIPList = @(
    ‘123.45.67.48/29’ # My WAN subnet
    ‘10.0.1.0/16’        # My LAN subnet
    (Resolve-DnsName -Name someallowedhost.domain.com).IPAddress
    ‘123.45.67.89’     # Some known remote user IP
)

The above code block identifies a number of subnets and IPs that should not be blocked by this firewall rule.

$BlockedIPs = Update-WindowsFirewall -BlockIPList $BlockIPList -AllowIPList $AllowIPList -Verbose

Finally, the above line creates a firewall rule named BlockAttackers and blocks the listed IP addresses

Using the $AllowIPList ensures that ligitimate IPs are not blocked if they show up in the logs due to occasional failed logon. $BlockedIPs list above could have thousands of IPs.

And you can see the firewall rule in the Windows Defender Firewall GUI:


Block-FailedLogonIPs

This function completes this solution. It automates blocking the IPs/subnets of failed Windows and SQL logon attempts. Using the default parameter values, this function will:

  • Create Logs and Reports folders under its current location, with _Archive subfolder under each
  • Schedule itself to run hourly (under LocalSystem context) if not already scheduled
  • Read and parse Security and RDP (Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational) event logs for failed Windows logon events
  • Read and parse Application event log for failed SQL logon events
  • Summarize the data in 6 time-stamped CSV reports under the Reports folder
  • Combine and deduplicate the IP list from the above reports
  • Create/update a windows firewall rule to block these IPs, ensuring the IPs/subnets in the AllowIPList parameter are not blocked
  • Clear the Security, RDP, and Application event logs for faster processing next hour
  • Archive the Log and Report files under the corresponding _Archive folders

Example

Block-FailedLogonIPs -AllowIPList @(
    ‘123.45.67.48/29’ # My WAN subnet
    ‘10.0.1.0/16’        # My LAN subnet
    (Resolve-DnsName -Name someallowedhost.domain.com).IPAddress
    ‘73.45.67.89’       # Some known remote user IP
) -WorkFolder C:\myScriptFolder -ScheduleHourly

All you need to do is:

  1. Save the above example as Block-Attackers.PS1, replace c:\myScriptFolder and the content of AllowIPList as needed
  2. Invoke it once under elevated permissions to let it schedule itself hourly
  3. Comment out or delete the ( -ScheduleHourly) part on the last line and save it

That’s all. What you should expect to see:

  • Logs and Reports folders under C:\myScriptFolder with _Archive subfolders
  • Script logs and Event logs under Logs\_Archive folder hourly
  • CSV reports under Reports\_Archive folder hourly
  • Windows firewall rule named ‘BlockAttackers’
  • Scheduled task named ‘PowerShell-BlockAttackers’ like shown below


To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show


Using PowerShell to report on failed Remote Desktop logon attempts


Many organizations and small businesses use Microsoft Remote Desktop RDP to remotely connect to their work computers, without protections such as end-to-end encryption/VPN tunneling, or MFA (Multi-factor Authentication). Even if the RDP port is changed from the default TCP 3389 to an arbitrary port, attackers are able to:

  • Identify open inbound ports via port scans and other techniques, including non-standard arbitrary ports
  • Identify the service running on that open port via sending test commands/protocol handshake.
  • In the case of RDP, they’re also able to identify the machine name (hostname) and Windows domain name (if the machine is domain-joined)

Next, the attacker will try to gain access by figuring out a name/password to login to the identified RDP server. Attackers commonly try the Windows default admin account ‘Administrator’. They use automated software to attempt different passwords, making several thousand attempts per hour. Every failed RDP connection leaves one or more log entries in the Windows Event logs.

This post describes functions in the AZSBTools PS module that automate the discovery and collection of failed RDP connection logs, report on an RDP attack across one or many computers, and provide some mitigation measures.

Report-FailureAudit

Report-FailureAudit is a new function of the AZSBTools PS module. This function will search Windows Security and RdpCoreTS (Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational) event logs for Failure Audit events (Event IDs 4625, 5061, 140)

This function accepts 2 optional parameters:

PARAMETER MaxCount
If an integer value of this optional parameter is provided, this function will limit its search to the newest $MaxCount events of each of the Security and Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational event logs

PARAMETER LogFile
Path to a file where this function will log its console output

Example

$LogFile = “.\Logs\Report-FailureAudit_$(Get-Date -Format ‘ddMMMMyyyy_hh-mm-ss_tt’).txt”
$EventList = Report-FailureAudit -LogFile $LogFile -Verbose

You can see the count of captured events and the last (most recent) of the returned PS objects using:

$EventList.Count
$EventList[-1]


The next function Summarize-FailureAudit helps sort through that data and answer some questions like where is the attack coming from (which IP addresses, geographical locations), what user accounts are being attempted, …

Summarize-FailureAudit

This is a function to provide summary report on data returned from Report-FailureAudit function. This function is designed to aggregate reporting on multiple computers in the same environment
Summary reporting is provided by:

  • Event Log: Security and RdpCoreTS (Microsoft-Windows-RemoteDesktopServices-RdpCoreTS/Operational)
  • Source IP
  • Source Computer name
  • Logon Type: such as Network/Interactive/…
  • Attempted User Name(s)

This function accepts a few parameters:

PARAMETER FailureAuditData
This function accepts as input the PS objects returned from the previous function Report-FailureAudit. This is a required parameter.

PARAMETER ShowTop
This is an optional parameter containing the count of records to report on, such as show top 20 most frequent source IP addresses. This defaults to 10.

PARAMETER ReportFolder
Path to a folder where this function will save its CSV output reports

PARAMETER LogFile
Path to a file where this function will log its console output

PARAMETERS PerLog, PerSourceIP, PerSourceName, PerLogonType, PerUserName
This optional group of Switch (True/False) parameters help to limit what type of reports you’d like to see. By default, 7 reports are produced such as:

  • Summarize-FailureAudit_All_16April2020_04-22-39_PM.CSV
    This file has all the records from Report-FailureAudit
  • Summarize-FailureAudit_PerLogonType_16April2020_04-22-39_PM.CSV
    This file has break down per Logon Type
  • Summarize-FailureAudit_PerSourceIP_16April2020_04-22-39_PM.CSV
    This file has break down per Source IP
  • Summarize-FailureAudit_PerSourceName_16April2020_04-22-39_PM.CSV
    This file has break down per Source Computer Name
  • Summarize-FailureAudit_PerUserName_16April2020_04-22-39_PM.CSV
    This file has break down per Attempted Account
  • Summarize-FailureAudit_PerLog_Security_16April2020_04-22-39_PM
    This file has break down per Security Event Log
  • Summarize-FailureAudit_PerLog_RdpCoreTS_16April2020_04-22-39_PM
    This file has break down per rdpCoreTS Event Log

Example

Summarize-FailureAudit -FailureAuditData (Report-FailureAudit) -ReportFolder .\Reports

The Summarize-FailureAudit_All file is a dump of the input PS objects into a CSV file. When sorted by ‘DateCreated’ it helps provide a look at attack progression across multiple Windows event logs

This particular view suggests a password spray type attack

You can even have summary reports of failed RDP logons across multiple computers such as:

$ComputerList = @('comp1','comp2','comp3')
$EventList = foreach ($ComputerName in $ComputerList) {
  Invoke-Command -ComputerName $ComputerName -ScriptBlock { Report-FailureAudit }
}
Summarize-FailureAudit -FailureAuditData $EventList -ReportFolder .\Reports

With output similar to:

 

Most of the source IP addresses/source computer names represent other compromised computers used by the attacker.

The default sizes of the Windows event logs can be as small as 1 MB, and by default these logs are configured in a circular fashion where the newest entries over-write the oldest. During an active attack such a small log file can only hold about a single minute’s worth of entries

Mitigation measures:

  • Configure and use a VPN tunnel to connect to the remote office before using RDP
  • Configure your VPN to use MFA
  • Configure the relevant Windows event log files to larger sizes than the default settings. This can be done domain-wide via group policy
  • Configure Windows event logs to be forwarded to a SEIM such as Splunk
  • Rename the Local and Domain ‘Administrator’ accounts, configure it with a long complex password.
  • Identify the WAN IPs/subnet of legitimate RDP users, configure your perimeter firewall to allow only these subnets for inbound RDP traffic
  • Monitor failed RDP logons – such as using the PS Summarize-FailureAudit and Report-FailureAudit functions
  • Possible PS automations can be developed to configure the windows firewall to block incoming RDP connections from the IPs/subnets identified from Report-FailureAudit function. (May first 2020 update: see Using PowerShell to block unauthorized access post for actual implementation)

To use/update the AZSBTools PowerShell module which is available in the PowerShell Gallery, you can use the following code:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 
# PowerShellGallery dropped Ssl3 and Tls as of 1 April 2020
Remove-Module AZSBTools -Force -EA 0 
Install-Module AZSBTools -Force -AllowClobber -SkipPublisherCheck # -Scope CurrentUser
Import-Module AZSBTools -DisableNameChecking -Force 
Get-Command -Module AZSBTools

You need PowerShell 5. To view your PowerShell version, in an elevated PowerShell ISE window type

$PSVersionTable

To download and install the latest version of AZSBTools from the PowerShell Gallery and its dependencies, type

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

To trust the Microsoft PowerShell Gallery repository, then

Install-Module AZSBTools,Az -Force -AllowClobber -Scope CurrentUser

AZSBTools contains functions that depend on Az module, and they’re typically installed together.

To load the AZSBTools, and Az modules type:

Import-Module AZSBTools,Az -DisableNameChecking

To view a list of cmdlets/functions in AZSBTools, type

Get-Command -Module AZSBTools

To view the built-in help of one of the AZSBTools functions/cmdlets, type

help <function/cmdlet name> -show

such as

help Get-DayOfMonth -show