Sometimes attackers will brute force an local user’s account’s password. If the account password is strong, brute force attacks are not effective and might not represent a high value event in themselves.
However, if the brute force attempt succeeds, then it is a very high value event (since brute forcing a password is typically a suspicious activity).
On the endpoint this looks like a bunch of failed logon attempts in quick succession followed by a successful login.
NOTE: In order for this artifact to work we need Windows to be logging failed account login. This is not on by default and should be enabled via group policy.
You can set the policy in group policy management console (gpmc): Computer Configuration\Windows Settings\Security Settings\Local Policies\Audit Policy.
name: Windows.Events.FailedLogBeforeSuccess
description: |
Sometimes attackers will brute force an local user's account's
password. If the account password is strong, brute force attacks are
not effective and might not represent a high value event in
themselves.
However, if the brute force attempt succeeds, then it is a very high
value event (since brute forcing a password is typically a
suspicious activity).
On the endpoint this looks like a bunch of failed logon attempts in
quick succession followed by a successful login.
NOTE: In order for this artifact to work we need Windows to be
logging failed account login. This is not on by default and should
be enabled via group policy.
https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/basic-audit-logon-events
You can set the policy in group policy management console (gpmc):
Computer Configuration\Windows Settings\Security Settings\Local Policies\Audit Policy.
type: CLIENT_EVENT
parameters:
- name: securityLogFile
default: >-
C:/Windows/System32/Winevt/Logs/Security.evtx
- name: failureCount
description: Alert if there are this many failures before the successful logon.
default: 3
- name: failedLogonTimeWindow
default: 3600
sources:
- precondition:
SELECT OS FROM info() where OS = 'windows'
query: |
LET failed_logon = SELECT EventData as FailedEventData,
System as FailedSystem
FROM watch_evtx(filename=securityLogFile)
WHERE System.EventID.Value = 4625
LET last_5_events = SELECT FailedEventData, FailedSystem
FROM fifo(query=failed_logon,
max_rows=500,
max_age=atoi(string=failedLogonTimeWindow))
// Force the fifo to materialize.
LET foo <= SELECT * FROM last_5_events
LET success_logon = SELECT EventData as SuccessEventData,
System as SuccessSystem
FROM watch_evtx(filename=securityLogFile)
WHERE System.EventID.Value = 4624
SELECT * FROM foreach(
row=success_logon,
query={
SELECT SuccessSystem.TimeCreated.SystemTime AS LogonTime,
SuccessSystem, SuccessEventData,
enumerate(items=FailedEventData) as FailedEventData,
FailedSystem, count(items=SuccessSystem) as Count
FROM last_5_events
WHERE FailedEventData.SubjectUserName = SuccessEventData.SubjectUserName
GROUP BY LogonTime
}) WHERE Count > atoi(string=failureCount)