The pySigma Kusto Backend transforms Sigma Rules into queries using Kusto Query Language (KQL). This backend supports multiple Microsoft products, including:
Note: This backend was previously named pySigma Microsoft 365 Defender Backend.
sigma.backends.kusto
with KustoBackend
classmicrosoft_xdr_pipeline
, sentinelasim_pipeline
, and azure_monitor_pipeline
for query tables and field renamesInstall the package:
pip install pysigma-backend-kusto
Note: This package requires
pySigma
version 0.10.0 or higher.
Convert a Sigma rule to MIcrosoft XDR KQL query using sigma-cli:
sigma convert -t kusto -p microsoft_xdr path/to/your/rule.yml
Or use in a Python script:
from sigma.rule import SigmaRule
from sigma.backends.kusto import KustoBackend
from sigma.pipelines.microsoftxdr import microsoft_xdr_pipeline
# Load your Sigma rule
rule = SigmaRule.from_yaml(
"""
title: Mimikatz CommandLine
status: test
logsource:
category: process_creation
product: windows
detection:
sel:
CommandLine|contains: mimikatz.exe
condition: sel
"""
)
# Convert the rule
xdr_pipeline = microsoft_xdr_pipeline()
backend = KustoBackend(processing_pipeline=xdr_pipeline)
print(backend.convert_rule(rule)[0])
Use with sigma-cli
per typical sigma-cli usage:
sigma convert -t kusto -p microsoft_xdr -f default -s ~/sigma/rules
Use the backend and pipeline in a standalone Python script. Note, the backend automatically applies the pipeline, but you can manually add it if you would like.
from sigma.rule import SigmaRule
from sigma.backends.kusto import KustoBackend
from sigma.pipelines.microsoftxdr import microsoft_xdr_pipeline
# Define an example rule as a YAML str
sigma_rule = SigmaRule.from_yaml("""
title: Mimikatz CommandLine
status: test
logsource:
category: process_creation
product: windows
detection:
sel:
CommandLine|contains: mimikatz.exe
condition: sel
""")
# Create backend, which automatically adds the pipeline
kusto_backend = KustoBackend()
# Or apply the pipeline manually
pipeline = microsoft_xdr_pipeline()
pipeline.apply(sigma_rule)
# Convert the rule
print(sigma_rule.title + " KQL Query: \n")
print(kusto_backend.convert_rule(sigma_rule)[0])
Output:
Mimikatz CommandLine KQL Query:
DeviceProcessEvents
| where ProcessCommandLine contains "mimikatz.exe"
For the microsoft_xdr_pipeline
:
transform_parent_image
: Controls ParentImage field mapping behavior
True
(default), maps ParentImage to InitiatingProcessParentFileNameFalse
, maps ParentImage to InitiatingProcessFileNamefrom sigma.pipelines.microsoftxdr import microsoft_xdr_pipeline
pipeline = microsoft_xdr_pipeline(transform_parent_image=False)
This argument allows fine-tuning of the ParentImage field mapping, which can be crucial for accurate rule conversion in certain scenarios. By default, it follows the behavior of mapping ParentImage to the parent process name, but setting it to False
allows for mapping to the initiating process name instead.
The query_table
argument allows users to override table mappings and set custom table names. This is useful for converting Sigma rules where the rule category does not easily map to the default table names.
To set a custom table name, ensure your pipeline has a priority of 9 or lower, as sigma-cli merges pipelines based on priority (default is 10). Field mappings in mappings.py
will apply according to your specified table name, along with any custom field mapping transformations.
# test_table_name_pipeline.yml
name: Custom Query Table Pipeline
priority: 1
transformations:
- id: test_name_name
type: set_state
key: "query_table"
val: ["DeviceProcessEvents"]
sigma convert -t kusto -p microsoft_xdr -p test_table_name_pipeline.yml test_rule.yml
You can also set the table name in the pipeline via Python by passing the query_table
parameter to the pipeline.
from sigma.pipelines.microsoftxdr import microsoft_xdr_pipeline
my_pipeline = microsoft_xdr_pipeline(query_table="DeviceProcessEvents")
This project includes three main processing pipelines, each designed for a specific Microsoft product:
Microsoft XDR Pipeline (formerly Microsoft 365 Defender)
Sentinel ASIM Pipeline
Azure Monitor Pipeline
SecurityEvent
and SigninLogs
tables onlyEach pipeline includes a query_table
parameter for setting custom table names.
Rules are supported if either:
query_table
parameter or YAML pipelinemappings.py
fileSpecific pipelines may support additional categories. Check each pipeline's mappings.py
file for details.
This package includes several custom ProcessingPipeline
Transformation
classes:
DynamicFieldMappingTransformation
query_table
state parameterGenericFieldMappingTransformation
BaseHashesValuesTransformation
ParentImageValueTransformation
SplitDomainUserTransformation
RegistryActionTypeValueTransformation
InvalidFieldTransformation
SetQueryTableStateTransformation
query_table
state based on rule category or custom settingsYou can set the table name for a rule by adding the query_table
parameter to the pipeline and setting it to the table name you want to use.
from sigma.pipelines.microsoftxdr import microsoft_xdr_pipeline
pipeline = microsoft_xdr_pipeline(query_table="DeviceProcessEvents")
You can set the table name for a rule in YAML by adding the query_table
parameter to the pipeline and setting it to the table name you want to use.
# test_table_name_pipeline.yml
name:
priority: 1
transformations:
- id: test_name_name
type: set_state
key: "query_table"
val: ["DeviceProcessEvents"]
sigma convert -t kusto -p microsoft_xdr -p test_table_name_pipeline.yml test_rule.yml
The table name is set by the SetQueryTableStateTransformation
transformation, which is the first transformation in each pipeline. It will use the query_table
parameter if it is set by either a YAML pipeline or by passing the parameter to the pipeline in a Python script, otherwise it will select the table based on the rule category. The table name to rule category logic is defined in each pipeline's mappings.py
file.
The field mappings are determined by the DynamicFieldMappingTransformation
transformation. It will use the table name from the pipeline state's query_table
key. The field mapping logic is defined in each pipeline's mappings.py
file for each table. If a field is not found in the table, the GenericFieldMappingTransformation
will apply generic field mappings. If a field is not found in the generic field mappings, the field will be kept the same.
The tables that are supported for each pipeline are defined in each pipeline's tables.py
file. This file is automatically generated by the scripts in the utils
folder. These scripts pull documentation from Microsoft to get all documented tables and their fields and schema.
Invalid SigmaDetectionItem field name encountered
error. What does this mean?This error means that the field name(s) provided in the error are not found in the tables fields defined in tables.py
for the pipeline you are using. This probably means that a Sigma rule's field was not found in the field mappings for the table. To fix this error, you can supply your own custom field mappings to convert the unsupported field into a supported one. For example, in using YAML:
# custom_field_mapping_pipeline.yml
name: Custom Field Mapping
priority: 1
transformations:
- id: field_mapping
type: field_name_mapping
mapping:
MyNotSupportedField: a_supported_field
rule_conditions:
- type: logsource
service: sysmon
sigma convert -t kusto -p custom_field_mapping_pipeline.yml -p microsoft_xdr test_rule.yml
If you find the field mapping useful, please consider submitting a PR to add it to the pipeline's field mappings :)
Each pipeline in the project has a priority of 10. If you are trying to set the table name or custom field mappings, your pipeline needs to have a priority of 9 or less. You can set the priority in the YAML pipeline like so:
# test_table_name_pipeline.yml
name:
priority: 9
transformations:
- id: test_name_name
type: set_state
key: "query_table"
val: ["DeviceProcessEvents"]
Contributions are welcome, especially for table and field mappings! Please feel free to submit a Pull Request.
git checkout -b feature/AmazingFeature
)git commit -m 'Add some AmazingFeature'
)git push origin feature/AmazingFeature
)Please make sure to update tests as appropriate.
This project is licensed under the GNU Lesser General Public License v3.0 - see the LICENSE file for details.