If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly (usually, the interactive graphs). Please view the post on dogesec.com for the full interactive viewing experience.
tl;dr
In this post I walk you through the database queries we use to compare Sigma Rules releases. We use these to identify the detail of what has changed before we push any updates internally.
Overview
As I’ve mentioned numerous times before, our intelligence team considers the authoring of detection rules a key deliverable of any research.
We write all our rules in Sigma so that they can be easily translated into other detection languages see SIEM Rules.
In writing our own rules, we take inspiration from other sources, including the core public Sigma ruleset here.
The Sigma team regularly publish updated releases with new rules and enhancements to the existing ruleset. Kudos to the Sigma team for their detailed changelog with each release.
However, to really understand the changes, we like to delve into each updated release more deeply alongside the changelog. In this post I will show you how we did this for the most recent release (r2024-11-10
), should this also be useful for your workflows.
Follow along
In this post I am going to provide ArangoDB queries you can use to analyse and filter Sigma Rules data (represented as STIX objects).
If you would like to follow along, and keep a searchable copy of Sigma STIX objects locally, you can import the data using stix2arango.
Once you’ve installed stix2arango, you can run the following command to import all versions of Sigma that are available at the time of writing (r2023-08-24
- r2024-11-10
)
python3 utilities/arango_cti_processor/insert_archive_sigma_rules.py \
--database blog_demo \
--ignore_embedded_relationships True
Sigma Rule releases over time
FOR doc IN mitre_cwe_vertex_collection
FILTER doc._stix2arango_note != "automatically imported on collection creation"
COLLECT note = doc._stix2arango_note WITH COUNT INTO count
LET release = SUBSTRING(note, 1) // Remove "v" prefix
SORT TO_NUMBER(SPLIT(release, ".")[0]) ASC, TO_NUMBER(SPLIT(release, ".")[1]) ASC
RETURN { release: release, count: count }
Since v2023-08-24
(released about 1.25 years ago), there are 469 more rules in the latest version v2024-11-10
.
Changes between version v2024-11-10
and v2024-09-02
LET version1Docs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "indicator"
RETURN { id: doc.id, modified: doc.modified }
)
LET version2Docs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-09-02"
AND doc.type == "indicator"
RETURN { id: doc.id, modified: doc.modified }
)
LET version1IDs = (FOR v IN version1Docs RETURN v.id)
LET version2IDs = (FOR v IN version2Docs RETURN v.id)
LET added = (
FOR v1 IN version1Docs
FILTER v1.id NOT IN version2IDs
RETURN v1
)
LET removed = (
FOR v2 IN version2Docs
FILTER v2.id NOT IN version1IDs
RETURN v2
)
LET unchanged = (
FOR v2 IN version2Docs
FILTER v2.id IN version1IDs
LET v1 = FIRST(FOR v1Doc IN version1Docs FILTER v1Doc.id == v2.id RETURN v1Doc)
FILTER v1.modified == v2.modified // Same ID and modified time
RETURN v2
)
LET modified = (
FOR v2 IN version2Docs
FILTER v2.id IN version1IDs
LET v1 = FIRST(FOR v1Doc IN version1Docs FILTER v1Doc.id == v2.id RETURN v1Doc)
FILTER v1.modified != v2.modified // Same ID but different modified time
RETURN v2
)
RETURN {
added: LENGTH(added),
removed: LENGTH(removed),
unchanged: LENGTH(unchanged),
modified: LENGTH(modified)
}
Most of the rules remain unchanged (3183), 17 were added, and 38 modified. Let’s take a closer look at those added and modified…
New objects in v2024-11-10
compared to v2024-09-02
This query returns all the new objects in v2024-11-10
;
LET groupings = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "grouping"
RETURN { name: doc.name, object_refs: doc.object_refs }
)
LET version1Docs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "indicator"
RETURN { id: doc.id, name: doc.name, description: doc.description, created: doc.created, modified: doc.modified }
)
LET version2IDs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-09-02"
AND doc.type == "indicator"
RETURN doc.id
)
LET newItems = (
FOR v1 IN version1Docs
FILTER v1.id NOT IN version2IDs
LET grouping_name = FIRST(
FOR grouping IN groupings
FILTER v1.id IN grouping.object_refs
RETURN grouping.name
)
RETURN MERGE(v1, { state: "added", grouping_name })
)
RETURN (
FOR item IN newItems
SORT item.name ASC
RETURN {
id: item.id,
name: item.name,
grouping: item.grouping_name
}
)
name | grouping |
---|---|
.RDP File Created by Outlook Process | rules/windows/file/file_event |
Access To Browser Credential Files By Uncommon Applications - Security | rules-threat-hunting/windows/builtin/security |
Command Executed Via Run Dialog Box - Registry | rules-threat-hunting/windows/registry/registry_set |
ETW Logging/Processing Option Disabled On IIS Server | rules/windows/builtin/iis-configuration |
Group Policy Abuse for Privilege Addition | rules/windows/builtin/security |
HTTP Logging Disabled On IIS Server | rules/windows/builtin/iis-configuration |
Network Connection Initiated To BTunnels Domains | rules/windows/network_connection |
New Module Module Added To IIS Server | rules/windows/builtin/iis-configuration |
Potential Python DLL SideLoading | rules/windows/image_load |
Potentially Suspicious Command Executed Via Run Dialog Box - Registry | rules/windows/registry/registry_set |
PowerShell Web Access Feature Enabled Via DISM | rules/windows/process_creation |
PowerShell Web Access Installation - PsScript | rules/windows/powershell/powershell_script |
Previously Installed IIS Module Was Removed | rules/windows/builtin/iis-configuration |
Process Deletion of Its Own Executable | rules/windows/file/file_delete |
Remote Access Tool - MeshAgent Command Execution via MeshCentral | rules/windows/process_creation |
Scheduled Task Deletion | rules-threat-hunting/windows/builtin/security |
Startup/Logon Script Added to Group Policy Object | rules/windows/builtin/security |
Note: for easier reading, I’ve removed the ID of the rules returned by the search from the table above.
Modified objects in v2024-11-10
compared to v2024-09-02
This query returns all the modified objects in v2024-11-10
;
LET groupings = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "grouping"
RETURN { name: doc.name, object_refs: doc.object_refs }
)
LET version1Docs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "indicator"
RETURN { id: doc.id, modified: doc.modified, created: doc.created, name: doc.name, description: doc.description }
)
LET version2Docs = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-09-02"
AND doc.type == "indicator"
RETURN { id: doc.id, modified: doc.modified, created: doc.created, name: doc.name, description: doc.description }
)
LET version1IDs = (FOR v IN version1Docs RETURN v.id)
LET modified = (
FOR v2 IN version2Docs
FILTER v2.id IN version1IDs
LET v1 = FIRST(FOR v1Doc IN version1Docs FILTER v1Doc.id == v2.id RETURN v1Doc)
FILTER v1.modified != v2.modified // Same ID but different modified time
LET grouping_name = FIRST(
FOR grouping IN groupings
FILTER v2.id IN grouping.object_refs
RETURN grouping.name
)
RETURN MERGE(v2, { state: "modified", grouping_name })
)
RETURN (
FOR item IN modified
SORT item.name ASC
RETURN {
id: item.id,
name: item.name,
grouping: item.grouping_name
}
)
name | grouping |
---|---|
Alternate PowerShell Hosts Pipe | rules/windows/pipe_created |
Antivirus Exploitation Framework Detection | rules/category/antivirus |
Antivirus Hacktool Detection | rules/category/antivirus |
Antivirus Password Dumper Detection | rules/category/antivirus |
Antivirus Ransomware Detection | rules/category/antivirus |
Antivirus Relevant File Paths Alerts | rules/category/antivirus |
Antivirus Web Shell Detection | rules/category/antivirus |
BITS Transfer Job Download From File Sharing Domains | rules/windows/builtin/bits_client |
CodeIntegrity - Unmet Signing Level Requirements By File Under Validation | rules/windows/builtin/code_integrity |
COM Object Hijacking Via Modification Of Default System CLSID Default Value | rules/windows/registry/registry_set |
Disable Windows Defender Functionalities Via Registry Keys | rules/windows/registry/registry_set |
DNS Query To Remote Access Software Domain From Non-Browser App | rules/windows/dns_query |
HackTool - Certipy Execution | rules/windows/process_creation |
Linux HackTool Execution | rules/linux/process_creation |
Linux Network Service Scanning Tools Execution | rules/linux/process_creation |
Local System Accounts Discovery - Linux | rules/linux/process_creation |
LSASS Process Memory Dump Files | rules/windows/file/file_event |
Network Communication Initiated To File Sharing Domains From Process Located In Suspicious Folder | rules/windows/network_connection |
New Connection Initiated To Potential Dead Drop Resolver Domain | rules/windows/network_connection |
Persistence and Execution at Scale via GPO Scheduled Task | rules/windows/builtin/security |
Potential CommandLine Obfuscation Using Unicode Characters | rules-threat-hunting/windows/process_creation |
Potential CommandLine Obfuscation Using Unicode Characters From Suspicious Image | rules/windows/process_creation |
Potential Python Reverse Shell | rules/linux/process_creation |
Potentially Suspicious File Download From File Sharing Domain Via PowerShell.EXE | rules/windows/process_creation |
Powershell Exfiltration Over SMTP | rules-threat-hunting/windows/powershell/powershell_script |
Process Terminated Via Taskkill | rules-threat-hunting/windows/process_creation |
Python Spawning Pretty TTY | rules/linux/process_creation |
RDP File Creation From Suspicious Application | rules/windows/file/file_event |
Renamed Powershell Under Powershell Channel | rules/windows/powershell/powershell_classic |
Suspicious File Download From File Sharing Domain Via Curl.EXE | rules/windows/process_creation |
Suspicious File Download From File Sharing Domain Via Wget.EXE | rules/windows/process_creation |
Suspicious File Download From File Sharing Websites - File Stream | rules/windows/create_stream_hash |
Suspicious Non PowerShell WSMAN COM Provider | rules/windows/powershell/powershell_classic |
Suspicious Office Token Search Via CLI | rules/windows/process_creation |
Suspicious Schtasks From Env Var Folder | rules/windows/process_creation |
Suspicious Windows Service Tampering | rules/windows/process_creation |
UNC2452 Process Creation Patterns | rules-emerging-threats/2020/TA/SolarWinds-Supply-Chain |
Unusual File Download From File Sharing Websites - File Stream | rules/windows/create_stream_hash |
Note: for easier reading, I’ve removed the ID of the rules returned by the search from the table above.
Looking more deeply at modified objects in v2024-11-10
I can also programmatically compare the changes to specific rules between versions using the IDs of the objects. This is what we use to analyse the updated objects before updating our rulesets.
Here I analyse the updates to indicator--61e988d6-6bb4-5dc4-8e0e-2cc900ca9d62
(Alternate PowerShell Hosts Pipe) between versions;
LET specificId = "indicator--61e988d6-6bb4-5dc4-8e0e-2cc900ca9d62"
LET version1Doc = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-11-10"
AND doc.type == "indicator"
AND doc.id == specificId
RETURN doc
)[0]
LET version2Doc = (
FOR doc IN sigma_rules_vertex_collection
FILTER doc._stix2arango_note == "v2024-09-02"
AND doc.type == "indicator"
AND doc.id == specificId
RETURN doc
)[0]
LET changes = (
FOR key IN ATTRIBUTES(version1Doc)
FILTER !STARTS_WITH(key, "_") // Exclude keys starting with "_"
AND version1Doc[key] != version2Doc[key]
RETURN { field: key, old_value: version2Doc[key], new_value: version1Doc[key] }
)
RETURN {
id: specificId,
name: version1Doc.name,
grouping: FIRST(
FOR grouping IN sigma_rules_vertex_collection
FILTER grouping._stix2arango_note == "v2024-11-10"
AND grouping.type == "grouping"
AND specificId IN grouping.object_refs
RETURN grouping.name
),
changes
}
[
{
"id": "indicator--61e988d6-6bb4-5dc4-8e0e-2cc900ca9d62",
"name": "Alternate PowerShell Hosts Pipe",
"grouping": "rules/windows/pipe_created",
"changes": [
{
"field": "pattern",
"old_value": "{'title': 'Alternate PowerShell Hosts Pipe', 'id': '58cb02d5-78ce-4692-b3e1-dce850aae41a', 'related': [{'id': 'ac7102b4-9e1e-4802-9b4f-17c5524c015c', 'type': 'derived'}], 'status': 'test', 'description': 'Detects alternate PowerShell hosts potentially bypassing detections looking for powershell.exe', 'references': ['https://threathunterplaybook.com/hunts/windows/190610-PwshAlternateHosts/notebook.html', 'https://threathunterplaybook.com/hunts/windows/190410-LocalPwshExecution/notebook.html'], 'author': 'Roberto Rodriguez @Cyb3rWard0g, Tim Shelton', 'date': datetime.date(2019, 9, 12), 'modified': datetime.date(2023, 10, 18), 'tags': ['attack.execution', 'attack.t1059.001'], 'logsource': {'product': 'windows', 'category': 'pipe_created', 'definition': 'Note that you have to configure logging for Named Pipe Events in Sysmon config (Event ID 17 and Event ID 18). The basic configuration is in popular sysmon configuration (https://github.com/SwiftOnSecurity/sysmon-config), but it is worth verifying. You can also use other repo, e.g. https://github.com/Neo23x0/sysmon-config, https://github.com/olafhartong/sysmon-modular. How to test detection? You can check powershell script from this site https://svch0st.medium.com/guide-to-named-pipes-and-hunting-for-cobalt-strike-pipes-dc46b2c5f575'}, 'detection': {'selection': {'PipeName|startswith': '\\\\PSHost'}, 'filter_main_generic': {'Image|contains': [':\\\\Program Files\\\\PowerShell\\\\7-preview\\\\pwsh.exe', ':\\\\Program Files\\\\PowerShell\\\\7\\\\pwsh.exe', ':\\\\Windows\\\\system32\\\\dsac.exe', ':\\\\Windows\\\\system32\\\\inetsrv\\\\w3wp.exe', ':\\\\Windows\\\\System32\\\\sdiagnhost.exe', ':\\\\Windows\\\\system32\\\\ServerManager.exe', ':\\\\Windows\\\\system32\\\\wbem\\\\wmiprvse.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe', ':\\\\Windows\\\\System32\\\\wsmprovhost.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe']}, 'filter_main_sqlserver': {'Image|contains|all': [':\\\\Program Files', '\\\\Microsoft SQL Server\\\\'], 'Image|endswith': '\\\\Tools\\\\Binn\\\\SQLPS.exe'}, 'filter_optional_citrix': {'Image|contains': ':\\\\Program Files\\\\Citrix\\\\'}, 'filter_optional_exchange': {'Image|contains': ':\\\\Program Files\\\\Microsoft\\\\Exchange Server\\\\'}, 'filter_main_null': {'Image': None}, 'condition': 'selection and not 1 of filter_main_* and not 1 of filter_optional_*'}, 'falsepositives': ['Programs using PowerShell directly without invocation of a dedicated interpreter.'], 'level': 'medium'}",
"new_value": "{'title': 'Alternate PowerShell Hosts Pipe', 'id': '58cb02d5-78ce-4692-b3e1-dce850aae41a', 'related': [{'id': 'ac7102b4-9e1e-4802-9b4f-17c5524c015c', 'type': 'derived'}], 'status': 'test', 'description': 'Detects alternate PowerShell hosts potentially bypassing detections looking for powershell.exe', 'references': ['https://threathunterplaybook.com/hunts/windows/190610-PwshAlternateHosts/notebook.html', 'https://threathunterplaybook.com/hunts/windows/190410-LocalPwshExecution/notebook.html'], 'author': 'Roberto Rodriguez @Cyb3rWard0g, Tim Shelton', 'date': datetime.date(2019, 9, 12), 'modified': datetime.date(2024, 10, 7), 'tags': ['attack.execution', 'attack.t1059.001'], 'logsource': {'product': 'windows', 'category': 'pipe_created', 'definition': 'Note that you have to configure logging for Named Pipe Events in Sysmon config (Event ID 17 and Event ID 18). The basic configuration is in popular sysmon configuration (https://github.com/SwiftOnSecurity/sysmon-config), but it is worth verifying. You can also use other repo, e.g. https://github.com/Neo23x0/sysmon-config, https://github.com/olafhartong/sysmon-modular. How to test detection? You can check powershell script from this site https://svch0st.medium.com/guide-to-named-pipes-and-hunting-for-cobalt-strike-pipes-dc46b2c5f575'}, 'detection': {'selection': {'PipeName|startswith': '\\\\PSHost'}, 'filter_main_generic': {'Image|contains': [':\\\\Program Files\\\\PowerShell\\\\7-preview\\\\pwsh.exe', ':\\\\Program Files\\\\PowerShell\\\\7\\\\pwsh.exe', ':\\\\Windows\\\\system32\\\\dsac.exe', ':\\\\Windows\\\\system32\\\\inetsrv\\\\w3wp.exe', ':\\\\Windows\\\\System32\\\\sdiagnhost.exe', ':\\\\Windows\\\\system32\\\\ServerManager.exe', ':\\\\Windows\\\\system32\\\\wbem\\\\wmiprvse.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe', ':\\\\Windows\\\\System32\\\\wsmprovhost.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe']}, 'filter_optional_sqlserver': {'Image|startswith': ['C:\\\\Program Files (x86)\\\\', 'C:\\\\Program Files\\\\'], 'Image|contains': '\\\\Microsoft SQL Server\\\\', 'Image|endswith': '\\\\Tools\\\\Binn\\\\SQLPS.exe'}, 'filter_optional_azure_connected_machine_agent': {'Image|startswith': 'C:\\\\Program Files\\\\AzureConnectedMachineAgent\\\\GCArcService', 'Image|endswith': '\\\\GC\\\\gc_worker.exe'}, 'filter_optional_citrix': {'Image|startswith': 'C:\\\\Program Files\\\\Citrix\\\\'}, 'filter_optional_exchange': {'Image|startswith': 'C:\\\\Program Files\\\\Microsoft\\\\Exchange Server\\\\'}, 'filter_main_null': {'Image': None}, 'condition': 'selection and not 1 of filter_main_* and not 1 of filter_optional_*'}, 'falsepositives': ['Programs using PowerShell directly without invocation of a dedicated interpreter.'], 'level': 'medium'}"
},
{
"field": "modified",
"old_value": "2023-10-18T00:00:00.000Z",
"new_value": "2024-10-07T00:00:00.000Z"
}
]
}
]
Here, the big change is an update to the detection;
'detection': {'selection': {'PipeName|startswith': '\\\\PSHost'}, 'filter_main_generic': {'Image|contains': [':\\\\Program Files\\\\PowerShell\\\\7-preview\\\\pwsh.exe', ':\\\\Program Files\\\\PowerShell\\\\7\\\\pwsh.exe', ':\\\\Windows\\\\system32\\\\dsac.exe', ':\\\\Windows\\\\system32\\\\inetsrv\\\\w3wp.exe', ':\\\\Windows\\\\System32\\\\sdiagnhost.exe', ':\\\\Windows\\\\system32\\\\ServerManager.exe', ':\\\\Windows\\\\system32\\\\wbem\\\\wmiprvse.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe', ':\\\\Windows\\\\System32\\\\wsmprovhost.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe']}, 'filter_optional_sqlserver': {'Image|startswith': ['C:\\\\Program Files (x86)\\\\', 'C:\\\\Program Files\\\\'], 'Image|contains': '\\\\Microsoft SQL Server\\\\', 'Image|endswith': '\\\\Tools\\\\Binn\\\\SQLPS.exe'}, 'filter_optional_azure_connected_machine_agent': {'Image|startswith': 'C:\\\\Program Files\\\\AzureConnectedMachineAgent\\\\GCArcService', 'Image|endswith': '\\\\GC\\\\gc_worker.exe'}, 'filter_optional_citrix': {'Image|startswith': 'C:\\\\Program Files\\\\Citrix\\\\'}, 'filter_optional_exchange': {'Image|startswith': 'C:\\\\Program Files\\\\Microsoft\\\\Exchange Server\\\\'}
'detection': {'selection': {'PipeName|startswith': '\\\\PSHost'}, 'filter_main_generic': {'Image|contains': [':\\\\Program Files\\\\PowerShell\\\\7-preview\\\\pwsh.exe', ':\\\\Program Files\\\\PowerShell\\\\7\\\\pwsh.exe', ':\\\\Windows\\\\system32\\\\dsac.exe', ':\\\\Windows\\\\system32\\\\inetsrv\\\\w3wp.exe', ':\\\\Windows\\\\System32\\\\sdiagnhost.exe', ':\\\\Windows\\\\system32\\\\ServerManager.exe', ':\\\\Windows\\\\system32\\\\wbem\\\\wmiprvse.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe', ':\\\\Windows\\\\System32\\\\wsmprovhost.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell_ise.exe', ':\\\\Windows\\\\SysWOW64\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe']}
SIEM Rules
Your detection engineering AI assistant. Turn cyber threat intelligence research into highly-tuned detection rules.
Discuss this post
Head on over to the DOGESEC community to discuss this post.
Never miss an update
Sign up to receive new articles in your inbox as they published.