Skip to content

Commit 3bc5708

Browse files
authored
[Rule Tuning] PowerShell ES|QL Rules Tuning (#4785)
* [Rule Tuning] PowerShell ES|QL Rules Tuning * Update defense_evasion_posh_obfuscation_whitespace_special_proportion.toml
1 parent 386a4b8 commit 3bc5708

5 files changed

+37
-12
lines changed

rules/windows/defense_evasion_posh_obfuscation_backtick.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2025/04/15"
33
integration = ["windows"]
44
maturity = "production"
5-
updated_date = "2025/04/15"
5+
updated_date = "2025/06/10"
66

77
[rule]
88
author = ["Elastic"]
@@ -64,6 +64,10 @@ FROM logs-windows.powershell_operational* metadata _id, _version, _index
6464
6565
// Filter FPs, and due to the behavior of the LIKE operator, allow null values
6666
| WHERE (file.name NOT LIKE "TSS_*.psm1" or file.name IS NULL)
67+
68+
| WHERE
69+
// VSCode Shell integration
70+
NOT powershell.file.script_block_text LIKE "*$([char]0x1b)]633*"
6771
'''
6872

6973
[[rule.threat]]

rules/windows/defense_evasion_posh_obfuscation_high_number_proportion.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2025/04/16"
33
integration = ["windows"]
44
maturity = "production"
5-
updated_date = "2025/04/16"
5+
updated_date = "2025/06/10"
66

77
[rule]
88
author = ["Elastic"]
@@ -65,8 +65,12 @@ FROM logs-windows.powershell_operational* metadata _id, _version, _index
6565
// Keep the fields relevant to the query, although this is not needed as the alert is populated using _id
6666
| KEEP special_count, script_len, proportion, replaced_with_fire, powershell.file.script_block_text, powershell.file.script_block_id, file.path, powershell.sequence, powershell.total, _id, _index, host.name, agent.id, user.id
6767
68-
// Filter for scripts with a 25%+ proportion of numbers
69-
| WHERE proportion > 0.25
68+
// Filter for scripts with a 30%+ proportion of numbers
69+
| WHERE proportion > 0.30
70+
71+
// Exclude noisy patterns
72+
| WHERE
73+
NOT powershell.file.script_block_text RLIKE """.*\"[a-fA-F0-9]{64}\"\,.*"""
7074
'''
7175

7276

rules/windows/defense_evasion_posh_obfuscation_string_concat.toml

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

77
[rule]
88
author = ["Elastic"]
@@ -14,7 +14,7 @@ from = "now-9m"
1414
language = "esql"
1515
license = "Elastic License v2"
1616
name = "Potential PowerShell Obfuscation via String Concatenation"
17-
risk_score = 21
17+
risk_score = 47
1818
rule_id = "f6d8c743-0916-4483-8333-3c6f107e0caa"
1919
setup = """## Setup
2020
@@ -34,7 +34,7 @@ Steps to implement the logging policy via registry:
3434
reg add "hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1
3535
```
3636
"""
37-
severity = "low"
37+
severity = "medium"
3838
tags = [
3939
"Domain: Endpoint",
4040
"OS: Windows",

rules/windows/defense_evasion_posh_obfuscation_string_format.toml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2025/04/03"
33
integration = ["windows"]
44
maturity = "production"
5-
updated_date = "2025/04/03"
5+
updated_date = "2025/06/10"
66

77
[rule]
88
author = ["Elastic"]
@@ -65,6 +65,20 @@ FROM logs-windows.powershell_operational* metadata _id, _version, _index
6565
// Keep the fields relevant to the query, although this is not needed as the alert is populated using _id
6666
| KEEP count, replaced_with_fire, powershell.file.script_block_text, powershell.file.script_block_id, file.path, powershell.sequence, powershell.total, _id, _index, host.name, agent.id, user.id
6767
| WHERE count > 3
68+
69+
// Exclude Noisy Patterns
70+
71+
// Icinga Framework
72+
| WHERE (file.name NOT LIKE "framework_cache.psm1" or file.name IS NULL)
73+
| WHERE NOT
74+
// https://wtfbins.wtf/17
75+
(
76+
(powershell.file.script_block_text LIKE "*sentinelbreakpoints*" OR
77+
powershell.file.script_block_text LIKE "*:::::\\\\windows\\\\sentinel*")
78+
AND
79+
(powershell.file.script_block_text LIKE "*$local:Bypassed*" OR
80+
powershell.file.script_block_text LIKE "*origPSExecutionPolicyPreference*")
81+
)
6882
'''
6983

7084

rules/windows/defense_evasion_posh_obfuscation_whitespace_special_proportion.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
creation_date = "2025/04/16"
33
integration = ["windows"]
44
maturity = "production"
5-
updated_date = "2025/04/16"
5+
updated_date = "2025/06/10"
66

77
[rule]
88
author = ["Elastic"]
@@ -50,20 +50,23 @@ query = '''
5050
FROM logs-windows.powershell_operational* metadata _id, _version, _index
5151
| WHERE event.code == "4104"
5252
53+
// Replace repeated spaces used for formatting after a new line with a single space to reduce FPs
54+
| EVAL dedup_space_script_block = REPLACE(powershell.file.script_block_text, """\n\s+""", "\n ")
55+
5356
// Look for scripts with more than 1000 chars that contain a related keyword
54-
| EVAL script_len = LENGTH(powershell.file.script_block_text)
57+
| EVAL script_len = LENGTH(dedup_space_script_block)
5558
| WHERE script_len > 1000
5659
5760
// Replace string format expressions with 🔥 to enable counting the occurrence of the patterns we are looking for
5861
// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1
59-
| EVAL replaced_with_fire = REPLACE(powershell.file.script_block_text, """[\s\$\{\}\+\@\=\(\)\^\\\"~\[\]\?\.]""", "🔥")
62+
| EVAL replaced_with_fire = REPLACE(dedup_space_script_block, """[\s\$\{\}\+\@\=\(\)\^\\\"~\[\]\?\.]""", "🔥")
6063
6164
// Count the occurrence of numbers and their proportion to the total chars in the script
6265
| EVAL special_count = script_len - LENGTH(REPLACE(replaced_with_fire, "🔥", ""))
6366
| EVAL proportion = special_count::double / script_len::double
6467
6568
// Keep the fields relevant to the query, although this is not needed as the alert is populated using _id
66-
| KEEP special_count, script_len, proportion, replaced_with_fire, powershell.file.script_block_text, powershell.file.script_block_id, file.path, powershell.sequence, powershell.total, _id, _index, host.name, agent.id, user.id
69+
| KEEP special_count, script_len, proportion, dedup_space_script_block, replaced_with_fire, powershell.file.script_block_text, powershell.file.script_block_id, file.path, powershell.sequence, powershell.total, _id, _index, host.name, agent.id, user.id
6770
6871
// Filter for scripts with a 75%+ proportion of numbers
6972
| WHERE proportion > 0.75

0 commit comments

Comments
 (0)