Skip to content

Commit 126e68a

Browse files
committed
[Tuning] Windows BruteForce Rules Tuning
#1 Multiple Logon Failure from the same Source Address: converted to ES|QL and raised the threshold to 100 failed auths, alert quality should be better since it aggregates all failed auths info into one alert vs multiple EQL matches. (expected reduction more than 50%) #2 Privileged Account Brute Force - coverted to ESQL and set the threshold to 50 in a minute. this should drop noise volume by more than 50%.
1 parent cabf1c2 commit 126e68a

File tree

2 files changed

+44
-27
lines changed

2 files changed

+44
-27
lines changed

rules/windows/credential_access_bruteforce_admin_account.toml

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2020/08/29"
33
integration = ["system", "windows"]
44
maturity = "production"
5-
updated_date = "2025/11/14"
5+
updated_date = "2025/12/11"
66

77
[transform]
88
[[transform.osquery]]
@@ -39,7 +39,7 @@ password, in an attempt to gain access to accounts.
3939
"""
4040
from = "now-9m"
4141
index = ["logs-system.security*", "logs-windows.forwarded*", "winlogbeat-*"]
42-
language = "eql"
42+
language = "esql"
4343
license = "Elastic License v2"
4444
name = "Privileged Account Brute Force"
4545
note = """## Triage and analysis
@@ -103,16 +103,28 @@ tags = [
103103
"Resources: Investigation Guide",
104104
"Data Source: Windows Security Event Logs",
105105
]
106-
type = "eql"
106+
type = "esql"
107107

108108
query = '''
109-
sequence by winlog.computer_name, source.ip with maxspan=10s
110-
[authentication where host.os.type == "windows" and
111-
event.action == "logon-failed" and winlog.logon.type : "Network" and
112-
source.ip != null and source.ip != "127.0.0.1" and source.ip != "::1" and user.name : "*admin*" and
113-
114-
/* noisy failure status codes often associated to authentication misconfiguration */
115-
not winlog.event_data.Status : ("0xC000015B", "0XC000005E", "0XC0000133", "0XC0000192")] with runs=5
109+
from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index
110+
| where event.category == "authentication" and host.os.type == "windows" and event.action == "logon-failed" and
111+
winlog.logon.type == "Network" and source.ip is not null and winlog.computer_name is not null and
112+
not cidr_match(TO_IP(source.ip), "127.0.0.0/8", "::1") and
113+
to_lower(winlog.event_data.TargetUserName) like "*admin*" and
114+
/*
115+
noisy failure status codes often associated to authentication misconfiguration
116+
0xC000015B - The user has not been granted the requested logon type (also called the logon right) at this machine.
117+
0XC000005E - There are currently no logon servers available to service the logon request.
118+
0XC0000133 - Clocks between DC and other computer too far out of sync.
119+
0XC0000192 An attempt was made to logon, but the Netlogon service was not started.
120+
0xc00000dc - DC is in shutdown phase, it will normally tell current clients to use another DC for authentication.
121+
*/
122+
not winlog.event_data.Status in ("0xc000015b", "0xc000005e", "0xc0000133", "0xc0000192", "0xc00000dc")
123+
// truncate the timestamp to a 60-second window
124+
| eval Esql.time_window = date_trunc(60 seconds, @timestamp)
125+
| stats Esql.failed_auth_count = COUNT(*), Esql.target_user_name_values = VALUES(winlog.event_data.TargetUserName), Esql.user_domain_values = VALUES(user.domain), Esql.error_codes = VALUES(winlog.event_data.Status) by winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type
126+
| where Esql.failed_auth_count >= 50
127+
| KEEP winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type, Esql.*
116128
'''
117129

118130

rules/windows/credential_access_bruteforce_multiple_logon_failure_same_srcip.toml

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2020/08/29"
33
integration = ["system", "windows"]
44
maturity = "production"
5-
updated_date = "2025/11/14"
5+
updated_date = "2025/12/11"
66

77
[transform]
88
[[transform.osquery]]
@@ -39,7 +39,7 @@ to gain access to accounts.
3939
"""
4040
from = "now-9m"
4141
index = ["logs-system.security*", "logs-windows.forwarded*", "winlogbeat-*"]
42-
language = "eql"
42+
language = "esql"
4343
license = "Elastic License v2"
4444
name = "Multiple Logon Failure from the same Source Address"
4545
note = """## Triage and analysis
@@ -117,24 +117,29 @@ tags = [
117117
"Resources: Investigation Guide",
118118
"Data Source: Windows Security Event Logs",
119119
]
120-
type = "eql"
120+
timestamp_override = "event.ingested"
121+
type = "esql"
121122

122123
query = '''
123-
sequence by winlog.computer_name, source.ip with maxspan=10s
124-
[authentication where host.os.type == "windows" and event.action == "logon-failed" and
125-
/* event 4625 need to be logged */
126-
winlog.logon.type : "Network" and
127-
source.ip != null and source.ip != "127.0.0.1" and source.ip != "::1" and
128-
not user.name : ("ANONYMOUS LOGON", "-", "*$") and not user.domain == "NT AUTHORITY" and
129-
130-
/*
131-
noisy failure status codes often associated to authentication misconfiguration :
124+
from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index
125+
| where event.category == "authentication" and host.os.type == "windows" and event.action == "logon-failed" and
126+
winlog.logon.type == "Network" and source.ip is not null and winlog.computer_name is not null and
127+
not cidr_match(TO_IP(source.ip), "127.0.0.0/8", "::1") and
128+
not user.name in ("ANONYMOUS LOGON", "-") and not user.name like "*$" and user.domain != "NT AUTHORITY" and
129+
/*
130+
noisy failure status codes often associated to authentication misconfiguration
132131
0xC000015B - The user has not been granted the requested logon type (also called the logon right) at this machine.
133-
0XC000005E - There are currently no logon servers available to service the logon request.
134-
0XC0000133 - Clocks between DC and other computer too far out of sync.
135-
0XC0000192 An attempt was made to logon, but the Netlogon service was not started.
136-
*/
137-
not winlog.event_data.Status : ("0xC000015B", "0XC000005E", "0XC0000133", "0XC0000192")] with runs=10
132+
0XC000005E - There are currently no logon servers available to service the logon request.
133+
0XC0000133 - Clocks between DC and other computer too far out of sync.
134+
0XC0000192 An attempt was made to logon, but the Netlogon service was not started.
135+
0xc00000dc - DC is in shutdown phase, it will normally tell current clients to use another DC for authentication.
136+
*/
137+
not winlog.event_data.Status in ("0xc000015b", "0xc000005e", "0xc0000133", "0xc0000192", "0xc00000dc")
138+
// truncate the timestamp to a 60-second window
139+
| eval Esql.time_window = date_trunc(60 seconds, @timestamp)
140+
| stats Esql.failed_auth_count = COUNT(*), Esql.target_user_name_values = VALUES(winlog.event_data.TargetUserName), Esql.user_domain_values = VALUES(user.domain), Esql.error_codes = VALUES(winlog.event_data.Status) by winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type
141+
| where Esql.failed_auth_count >= 100
142+
| KEEP winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type, Esql.*
138143
'''
139144

140145

0 commit comments

Comments
 (0)