Category: Security

PowerShell script to collect ADFS Extranet Smart Lockout events sequence

Below is slightly modified script from here to collect the sequence of the EventIDs 1203 and 1210 on single AD FS server that might help you understanding and troubleshooting the AD FS Extranet Smart Lockout (ESL) behavior.

You can read more about AD FS ESL behavior here and here.

$events = Get-WinEvent -MaxEvents 2000 -FilterHashtable @{Logname='Security';Id=1203,1210}
$events2 = ($events | select ID, Message,TimeCreated -ExpandProperty Message)
$info = @()

$events2 | foreach {

$IpAddresses = $null
$UserId = $null
$BadCount = $null

    $IpStart = $_.Message.IndexOf("<IpAddress>")
    $IpEnd = $_.Message.IndexOf("</IpAddress>")
    $IpAddresses = $_.Message.Substring($IpStart+11,($IpEnd-$IpStart-11))

    $UserIdStart = $_.Message.IndexOf("<UserId>")
    $UserIdEnd = $_.Message.IndexOf("</UserId>")
    $UserId = $_.Message.Substring($UserIdStart+8,($UserIdEnd-$UserIdStart-8))
 if ($_.Id -like 1210) 
    $BadCountStart = $_.Message.IndexOf("<CurrentBadPasswordCount>")
    $BadCountEnd = $_.Message.IndexOf("</CurrentBadPasswordCount>")
    $BadCount = $_.Message.Substring($BadCountStart+25,($BadCountEnd-$BadCountStart-25))
    else {$BadCount = $null}

$Fail = New-object -TypeName PSObject
add-member -inputobject $Fail -membertype noteproperty -name "EventID" -value $_.Id
add-member -inputobject $Fail -membertype noteproperty -name "TimeStamp" -value $_.TimeCreated
add-member -inputobject $Fail -membertype noteproperty -name "IPaddress" -value $IpAddresses
add-member -inputobject $Fail -membertype noteproperty -name "User ID" -value $UserId
add-member -inputobject $Fail -membertype noteproperty -name "BadCount" -value $BadCount

$info +=$Fail
$info | ft

AD FS 2016 Extranet Smart Lockout eventIDs 1203 and 1210 clarification

Continuing my journey of learning the great AD FS Extranet Smart Lockout (ESL) feature.

As mentioned in my other post, the enhancement were made in AD FS 2016 auditing and there will be Event ID 1203 logged in the ADFS Security log by ADFS Auditing in case there was a failure to validate user credentials against Active Directory.

When you have enabled ADFS Extranet Smart Lockout feature in either log or enforce mode and AD FS Security auditing was enabled (the user has AD FS ESL bad password counts set to zero), as soon as the external bad password attempt count reaches the value specified in the ExtranetLockoutThreshold (you will see event ID 1203 for each bad password attempt), the account will be locked out on AD FS for a duration specified in the ExtranetObservationWindow, the event ID 1210 will be logged in Security event log and password validation attempts will not be sent to Active directory.

As mentioned in AD FS ESL public documentation:

AD FS will write extranet lockout events to the security audit log:

  • When a user is locked out (reaches the lockout threshold for unsuccessful login attempts)
  • When AD FS receives a login attempt for a user who is already in lockout state

At the same time, no event ID 1203 will be logged, since no password validation against Active Directory is taking place.

Only after the extranet observation window expires, the password attempts will be forwarded to AD and if the password validation fails, the event ID 1203 is logged.

Please note, that the CurrentBadPasswordCount value in event ID 1210 only increases when the password validation happens against AD and at the time the account is locked on AD FS.

Also keep in mind, that when the AD FS ESL extranet observation window expires, it doesn’t clear the AD FS ESL bad password count until good password was provided, so one single 1203 event from the same bad IP location with no bad password counts cleared will put account in ESL state again for the time specified in the ExtranetObservationWindow.

Hope this information will be helpful for you.

AD FS Extranet Smart Lockout user management via remote PowerShell

Recently had experienced issue when trying to execute AD FS Extranet Smart Lockout user management cmdlet via remote PowerShell.

Invoke-Command -ComputerName Win2016-ADFS01 -scriptBlock {Get-AdfsAccountActivity -Identity}

Error in PowerShell:

Exception of type
‘Microsoft.IdentityServer.User.UserActivityRestServiceException’ was thrown.
+ CategoryInfo         : NotSpecified: (:) [Get-AdfsAccountActivity], User
+ FullyQualifiedErrorId : Microsoft.IdentityServer.User.UserActivityRestSer
+ PSComputerName       : Win2016-ADFS01

In AD FS Admin logs on Win2016-ADFS01 server saw following error:

Log Name:     AD FS/Admin
Source:       AD FS
Date:         10/29/2018 5:20:39 PM
Event ID:     1100
Task Category: None
Level:         Error
Keywords:     AD FS
User:         domain\adfs_service_account
Computer:     Win2016-ADFS01
The Federation Service could not authorize a request to one of the REST endpoints.
Additional Data
Exception details:
Microsoft.IdentityServer.WebHost.Rest.RestRequestAuthorizationFailedException: Only AD FS Service can access this endpoint. The client was authenticated as NT AUTHORITY\ANONYMOUS LOGON.
at Microsoft.IdentityServer.Web.UserActivity.UserStoreAuthenticationVerificationMethod.VerifyTrustedRequest(WrappedHttpListenerContext context, String& auditInformation)
at Microsoft.IdentityServer.Web.Rest.RestRequestHandler.OnGetContext(WrappedHttpListenerContext context)

Solution was to enable CredSSP on management machine and Win2016-ADFS01 server and use following commands:

$cred = Get-Credential
Invoke-Command -ComputerName Win2016-ADFS01 -Authentication Credssp -credential $cred -ScriptBlock {Get-AdfsAccountActivity}

You can read more about managing the second hop in PowerShell remoting and consideration when enabling CredSSP in this article –

Update 2-14-2019: Microsoft has updated the documentation how to delegate ADFS PowerShell access to non-admin users –


AD FS 2016 Extranet Smart Lockout behavior

I’m sure you are familiar with the following articles discussing the Federated account lockouts and AD FS Extranet Smart Lockout (ESL) feature and set up recommendations.

Recently was helping the customer whose environment was experiencing high volume of on-premises AD accounts lockouts due to the external bad passwords attempts via AD FS 2016 farm.

As per second article, Microsoft recommends enabling the AD FS ESL in the log only mode. It is recommended to run AD FS ESL in such mode for 5-7 days to build the list of familiar locations per user.

Since the impact of the AD lockouts was high to the customer, they decided to switch from log to enforce mode after 24 hours of enabling the ESL, but ran into following issue.

It was not enough time to build the familiar IPs list, and some users accounts still experiencing heavy bad passwords attempts were locked out on AD FS side due to empty familiar IP addresses list.

This happened because in case in the output of Get-AdfsAccountActivity PowerShell cmdlet you see the familiar IP list is empty and the UnknownLockout = True, the user will not be able to sign in with correct password until the observationWindows time elapses or ADFS admin resets the count. In such scenario AD FS ESL works in AD FS Extranet Lockout mode introduced in AD FS 3.0.

This issue was addressed in AD FS 2019 where you can enable audit mode for smart lockout while continuing to enforce the soft lockout behavior (ADPasswordCounter)

Discover and protect from crypto miners in your network using pfSense firewall

In a raise of popularity of crypto mining there is a shift in the threat landscape. Attackers “are beginning to recognize that they can realize all the financial upside of previous attacks, like ransomware, without needing to actually engage the victim and without the extraneous law enforcement attention that comes with ransomware attacks,” Talos researchers write in a new post( ).

One of the steps you can take to protect your network, is to block outgoing connection to the IP addresses associated with crypto mining pools. Those IPs are easy to get from SANS API (See for details).

I have used following PowerShell scrip to get the latest IP list.

$date = Get-Date -format "yyyyMMdd"
$url = ""
$membersList = Invoke-RestMethod -Uri $url
$membersList | select threatlist -ExpandProperty threatlist |
select miner -ExpandProperty miner | select ipv4 -ExpandProperty ipv4 |
Sort-Object ipv4 -Descending |
out-file "D:\Temp\miners$date.txt"

After that sign in your pfSense firewall, go to Firewall – Aliases menu.

pfSense Aliases menu allows bulk IP addresses upload. Press Import button on the bottom of Aliases page and use the content of the TXT file created earlier to create the alias for the IPs associated with crypto mining pools. I would recommend giving the alias meaningful name which includes the date of creation (will make the firewall rule and aliases management easier as you update the list).


After creating the alias, go to your LAN rules and create the rule to block any connection from your LAN network to the CryptoMining alias and make sure the rule is on the top of the list (right after rules allowing access to pfSense management ports). Optionally you can select log to monitor what stations in your network tried the malicious outbound connection.


On regular basis you can update the IP list and create the new alias (with new date in the name). After that you can easily update the firewall rule by simply changing the destination to new alias.

Also its always recommended to place a default block all LAN rule for outgoing traffic to make sure only authorized connections are successful to the Internet from your hosts.