diff --git a/rules_building_block/defense_evasion_posh_obfuscation_proportion_special_chars.toml b/rules_building_block/defense_evasion_posh_obfuscation_proportion_special_chars.toml new file mode 100644 index 00000000000..689ebc37b84 --- /dev/null +++ b/rules_building_block/defense_evasion_posh_obfuscation_proportion_special_chars.toml @@ -0,0 +1,110 @@ +[metadata] +bypass_bbr_timing = true +creation_date = "2025/04/16" +integration = ["windows"] +maturity = "production" +updated_date = "2025/04/16" + +[rule] +author = ["Elastic"] +building_block_type = "default" +description = """ +Identifies PowerShell scripts with an abnormally high proportion of non-alphanumeric characters, often resulting from +encoding, string mangling, or dynamic code generation. +""" +from = "now-9m" +language = "esql" +license = "Elastic License v2" +name = "Potential PowerShell Obfuscation via High Special Character Proportion" +risk_score = 21 +rule_id = "f9753455-8d55-4ad8-b70a-e07b6f18deea" +setup = """## Setup + +The 'PowerShell Script Block Logging' logging policy must be enabled. +Steps to implement the logging policy with Advanced Audit Configuration: + +``` +Computer Configuration > +Administrative Templates > +Windows PowerShell > +Turn on PowerShell Script Block Logging (Enable) +``` + +Steps to implement the logging policy via registry: + +``` +reg add "hklm\\SOFTWARE\\Policies\\Microsoft\\Windows\\PowerShell\\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1 +``` +""" +severity = "low" +tags = [ + "Domain: Endpoint", + "OS: Windows", + "Use Case: Threat Detection", + "Tactic: Defense Evasion", + "Data Source: PowerShell Logs", + "Rule Type: BBR" +] +timestamp_override = "event.ingested" +type = "esql" + +query = ''' +FROM logs-windows.powershell_operational* metadata _id, _version, _index +| WHERE event.code == "4104" + +// Look for scripts with more than 1000 chars that contain a related keyword +| EVAL script_len = LENGTH(powershell.file.script_block_text) +| WHERE script_len > 1000 + +// Replace string format expressions with 🔥 to enable counting the occurrence of the patterns we are looking for +// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1 +// Excludes spaces, #, = and - as they are heavily used in scripts for formatting +| EVAL replaced_with_fire = REPLACE(powershell.file.script_block_text, """[^0-9A-Za-z\s#=-]""", "🔥") + +// Count the occurrence of special chars and their proportion to the total chars in the script +| EVAL special_count = script_len - LENGTH(REPLACE(replaced_with_fire, "🔥", "")) +| EVAL proportion = special_count::double / script_len::double + +// Keep the fields relevant to the query, although this is not needed as the alert is populated using _id +| 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 + +// Filter for scripts with a 25%+ proportion of special chars +| WHERE proportion > 0.25 +''' + + +[[rule.threat]] +framework = "MITRE ATT&CK" +[[rule.threat.technique]] +id = "T1027" +name = "Obfuscated Files or Information" +reference = "https://attack.mitre.org/techniques/T1027/" + +[[rule.threat.technique]] +id = "T1140" +name = "Deobfuscate/Decode Files or Information" +reference = "https://attack.mitre.org/techniques/T1140/" + + +[rule.threat.tactic] +id = "TA0005" +name = "Defense Evasion" +reference = "https://attack.mitre.org/tactics/TA0005/" +[[rule.threat]] +framework = "MITRE ATT&CK" +[[rule.threat.technique]] +id = "T1059" +name = "Command and Scripting Interpreter" +reference = "https://attack.mitre.org/techniques/T1059/" +[[rule.threat.technique.subtechnique]] +id = "T1059.001" +name = "PowerShell" +reference = "https://attack.mitre.org/techniques/T1059/001/" + + + +[rule.threat.tactic] +id = "TA0002" +name = "Execution" +reference = "https://attack.mitre.org/tactics/TA0002/" +