MITRE ATT&CK¶
Table of Contents¶
Release Notes¶
Version |
Date |
Notes |
---|---|---|
1.0.0 |
04/2019 |
Initial Release |
1.0.1 |
04/2019 |
Update Document |
2.0.0 |
11/2019 |
Customizations for group identification, software retrieval, MITRE collection support, and data format changes. |
2.0.1 |
04/2020 |
Support added for App Host |
2.0.2 |
09/2020 |
Added proxy support |
2.1.0 |
10/2024 |
Added verify support |
v2.1.0¶
When upgrading from a previous version to v2.1.0, manually update your app.config to use verify. The app.config changes are documented here App Configuration. The previous version of the app.config from versions before 2.1.0 are compatible with version 2.1.0+.
Overview¶
IBM SOAR Components for ‘fn_mitre_integration’
MITRE’s TAXIITM 2.0 Server provides Adversarial Tactics, Techniques, and Common Knowledge (ATT&CK or ATTACK) content. This content is critical for cyber security industry in order to make a holistic approach to detection and mitigation of Advanced Persistent Threats (APTs). MITRE Integration Function enables SOAR users to gather ATT&CK information on cyber intrusion once a tactic or technique has been identified. This information can help security analysts respond quickly to a (potential) breach.
Key Features¶
It comes with a set of customizations that query MITRE ATT&CK for the following:
Techniques
Tactics
Software used in techniques
Groups using techniques
Groups that use a specific set of techniques
Mitigations
Requirements¶
This app supports the IBM Security QRadar SOAR Platform and the IBM Security QRadar SOAR for IBM Cloud Pak for Security.
SOAR platform¶
The SOAR platform supports two app deployment mechanisms, Edge Gateway (also known as App Host) and integration server.
If deploying to a SOAR platform with an App Host, the requirements are:
SOAR platform >=
51.0.0
.The app is in a container-based format (available from the AppExchange as a
zip
file).
If deploying to a SOAR platform with an integration server, the requirements are:
SOAR platform >=
51.0.0
.The app is in the older integration format (available from the AppExchange as a
zip
file which contains atar.gz
file).Integration server is running
resilient_circuits>=51.0.0
.If using an API key account, make sure the account provides the following minimum permissions:
Name
Permissions
Org Data
Read
Function
Read
The following SOAR platform guides provide additional information:
Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
Integration Server Guide: provides installation, configuration, and troubleshooting information, including proxy server settings.
System Administrator Guide: provides the procedure to install, configure and deploy apps.
The above guides are available on the IBM Documentation website at ibm.biz/soar-docs. On this web page, select your SOAR platform version. On the follow-on page, you can find the Edge Gateway Deployment Guide, App Host Deployment Guide, or Integration Server Guide by expanding Apps in the Table of Contents pane. The System Administrator Guide is available by expanding System Administrator.
Cloud Pak for Security¶
If you are deploying to IBM Cloud Pak for Security, the requirements are:
IBM Cloud Pak for Security >=
1.10.15
.Cloud Pak is configured with an Edge Gateway.
The app is in a container-based format (available from the AppExchange as a
zip
file).
The following Cloud Pak guides provide additional information:
Edge Gateway Deployment Guide or App Host Deployment Guide: provides installation, configuration, and troubleshooting information, including proxy server settings. From the Table of Contents, select Case Management and Orchestration & Automation > Orchestration and Automation Apps.
System Administrator Guide: provides information to install, configure, and deploy apps. From the IBM Cloud Pak for Security IBM Documentation table of contents, select Case Management and Orchestration & Automation > System administrator.
These guides are available on the IBM Documentation website at ibm.biz/cp4s-docs. From this web page, select your IBM Cloud Pak for Security version. From the version-specific IBM Documentation page, select Case Management and Orchestration & Automation.
Proxy Server¶
The app does support a proxy server.
Python Environment¶
Python 3.6 and Python 3.9 are supported. Additional package dependencies may exist for each of these packages:
resilient_circuits>=51.0.0
resilient_lib
stix2
taxii2-client>=2.0.0
Configuration¶
Config |
Required |
Example |
Description |
---|---|---|---|
http_proxy or https_proxy |
No |
https://proxyhost:8080 |
Optional settings for access to Mitre via a proxy. |
verify |
No |
True/False |
True or False or path to cert |
Installation¶
Install¶
To install or uninstall an App or Integration on the SOAR platform, see the documentation at ibm.biz/soar-docs.
To install or uninstall an App on IBM Cloud Pak for Security, see the documentation at ibm.biz/cp4s-docs and follow the instructions above to navigate to Orchestration and Automation.
Function - MITRE Get Groups Using All Given Techniques¶
For given Techniques, return the Groups that are known to use all of them. Techniques can be specified with a comma separated strings of IDs or Names. In case both are provided, the ID values take precedence as names are not guaranteed to be unique.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
- |
|
|
No |
|
- |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
# TODO: Generate an example of the Function Output within this code block.
# To get the output of a Function:
# 1. Run resilient-circuits in DEBUG mode: $ resilient-circuits run --loglevel=DEBUG
# 2. Invoke the Function in SOAR
# 3. Gather the results using: $ resilient-sdk codegen -p fn_mitre_integration --gather-results
# 4. Run docgen again: $ resilient-sdk docgen -p fn_mitre_integration
# Or simply paste example outputs manually here. Be sure to remove any personal information
}
Example Function Input Script:
# The priority order of inputs is:
# 1. Values entered in the Activity Field pop-up
# 2. Values in the Input Fields added to the layout
# 3. Inputs in the function's workflow
activity_field_given = rule.properties.mitre_technique_id or rule.properties.mitre_technique_name
incident_properties_given = incident.properties.mitre_technique_name or incident.properties.mitre_technique_id
if activity_field_given:
inputs.mitre_technique_name = rule.properties.mitre_technique_name
inputs.mitre_technique_id = rule.properties.mitre_technique_id
elif incident_properties_given:
inputs.mitre_technique_id = incident.properties.mitre_technique_id
inputs.mitre_technique_name = incident.properties.mitre_technique_name
Example Function Post Process Script:
"""
Data returned as a part of ResultPayload:
{
"technique": "T0042",
"name": "Wet Bandits",
"id": "G0032",
"ref": "url to MITRE",
"description": "lorem ipsum",
"aliases": ["name 1", "name 2"]
}
"""
groups_mitre = results.content["mitre_groups"]
for group in groups_mitre:
group_row = incident.addRow("mitre_attack_groups")
group_row["groups_technique"] = group["technique"]
ref = '<a href="{}">'.format(group["ref"]) +'{}</a> '
group_row["groups_name"] = helper.createRichText(ref.format(group["name"]))
group_row["groups_id"] = helper.createRichText(ref.format(group["id"]))
group_row["groups_aliases"] = ",".join(group["aliases"])
group_row["groups_description"] = helper.createRichText(group["description"])
Function - MITRE Groups Using Given Techniques¶
For each given Technique, find all of the Groups using it. Techniques can be specified with a comma separated strings of IDs or Names. In case both are provided, the ID values take precedence as names are not guaranteed to be unique.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
- |
|
|
No |
|
- |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
# TODO: Generate an example of the Function Output within this code block.
# To get the output of a Function:
# 1. Run resilient-circuits in DEBUG mode: $ resilient-circuits run --loglevel=DEBUG
# 2. Invoke the Function in SOAR
# 3. Gather the results using: $ resilient-sdk codegen -p fn_mitre_integration --gather-results
# 4. Run docgen again: $ resilient-sdk docgen -p fn_mitre_integration
# Or simply paste example outputs manually here. Be sure to remove any personal information
}
Example Function Input Script:
# The priority order of inputs is:
# 1. Values entered in the Activity Field pop-up
# 2. Values in the Input Fields added to the layout
# 3. Inputs in the function's workflow
activity_field_given = rule.properties.mitre_technique_id or rule.properties.mitre_technique_name
incident_properties_given = incident.properties.mitre_technique_name or incident.properties.mitre_technique_id
if activity_field_given:
inputs.mitre_technique_name = rule.properties.mitre_technique_name
inputs.mitre_technique_id = rule.properties.mitre_technique_id
elif incident_properties_given:
inputs.mitre_technique_id = incident.properties.mitre_technique_id
inputs.mitre_technique_name = incident.properties.mitre_technique_name
Example Function Post Process Script:
"""
Data returned as a part of ResultPayload:
{
"technique": "T0042",
"name": "Wet Bandits",
"id": "G0032",
"ref": "url to MITRE",
"description": "lorem ipsum",
"aliases": ["name 1", "name 2"]
}
"""
groups_mitre = results.content["mitre_groups"]
for group in groups_mitre:
group_row = incident.addRow("mitre_attack_groups")
group_row["groups_technique"] = group["technique"]
ref = '<a href="{}">'.format(group["ref"]) +'{}</a> '
group_row["groups_name"] = helper.createRichText(ref.format(group["name"]))
group_row["groups_id"] = helper.createRichText(ref.format(group["id"]))
group_row["groups_aliases"] = ",".join(group["aliases"])
group_row["groups_description"] = helper.createRichText(group["description"])
Function - MITRE Tactic Information¶
Get information about MITRE tactic. Tactics can be specified with a comma separated string of IDs or Names. In case both are provided, the ID values take precedence as names are not guaranteed to be unique.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
MITRE ATT&CK Tactic ID |
|
|
No |
|
MITRE Tactic Name |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
# TODO: Generate an example of the Function Output within this code block.
# To get the output of a Function:
# 1. Run resilient-circuits in DEBUG mode: $ resilient-circuits run --loglevel=DEBUG
# 2. Invoke the Function in SOAR
# 3. Gather the results using: $ resilient-sdk codegen -p fn_mitre_integration --gather-results
# 4. Run docgen again: $ resilient-sdk docgen -p fn_mitre_integration
# Or simply paste example outputs manually here. Be sure to remove any personal information
}
Example Function Input Script:
# The priority order of inputs is:
# 1. Values entered in the Activity Field pop-up
# 2. Values in the Input Fields added to the layout
# 3. Inputs in the function's workflow
activity_field_given = rule.properties.mitre_tactic_name or rule.properties.mitre_tactic_id
incident_propery_given = incident.properties.mitre_tactic_id or incident.properties.mitre_tactic_name
if activity_field_given:
inputs.mitre_tactic_name = rule.properties.mitre_tactic_name
inputs.mitre_tactic_id = rule.properties.mitre_tactic_id
elif incident_propery_given:
inputs.mitre_tactic_name = incident.properties.mitre_tactic_name
inputs.mitre_tactic_id = incident.properties.mitre_tactic_id
Example Function Post Process Script:
""" Example of data returned in ResultPayload's content
{
"mitre_tactics": [
{
"name": String,
"id": String,
"ref": "String",
"collection": "String",
"mitre_techniques": [
{
"name": "String",
"description": "String",
"external_references": [{"url": "String"}],
"x_mitre_detection": "String",
"id": "String",
"collection": "String"
}
]
}
]
}
"""
tactics = results.content["mitre_tactics"]
for tactic in tactics:
#
# MITRE ATTACK of Incident Datatable
#
tactic_row = incident.addRow("mitre_attack_of_incident")
tactic_row["collection"] = tactic["collection"]
tactic_row["attack_tactic"] = tactic["name"]
tactic_row["tactic_code"] = tactic["id"]
url_html = '<a href="' + tactic["ref"] + '">' + tactic["ref"] + '</a><br>'
tactic_row["reference"] = helper.createRichText(url_html)
tactic_row["confidence"] = " "
#
# MITRE ATT&CK techniques Datatable
#
techs = tactic["mitre_techniques"]
for att_tech in techs:
tech_row = incident.addRow("mitre_attack_techniques")
tech_row["collection"] = tactic["collection"]
tech_row["tactic"] = tactic["name"]
tech_row["technique_name"] = att_tech["name"]
tech_row["technique_description"] = helper.createRichText(att_tech["description"])
refs = att_tech["external_references"]
ref_html = ""
for ref in refs:
url = ref["url"]
https_str = "https://"
http_str = "http://"
start_pos = url.find(https_str)
if start_pos != -1:
start_pos = start_pos + len(https_str)
else:
# try http://
start_pos = url.find(http_str)
if start_pos != -1:
start_pos = start_pos + len(http_str)
else:
start_pos = 0
end_pos = url.find('/', start_pos)
if end_pos == 0:
# We don't know how to extract
display_str = url
elif end_pos == -1:
display_str = url[start_pos:]
else:
display_str = url[start_pos:end_pos]
ref_html = ref_html + '<a href="' + ref["url"] + '">' + display_str + '</a><br>'
tech_row["references"] = helper.createRichText(ref_html)
tech_row["detection"] = helper.createRichText(att_tech["x_mitre_detection"])
tech_row["technique_id"] = att_tech["id"]
Function - MITRE Technique Information¶
Get ATT&CK information about MITRE ATT&CK technique. In case both ID and name are provided, the ID value takes precedence as names are not guaranteed to be unique.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
- |
|
|
No |
|
Retrieve the mitigation only |
|
|
No |
|
- |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
# TODO: Generate an example of the Function Output within this code block.
# To get the output of a Function:
# 1. Run resilient-circuits in DEBUG mode: $ resilient-circuits run --loglevel=DEBUG
# 2. Invoke the Function in SOAR
# 3. Gather the results using: $ resilient-sdk codegen -p fn_mitre_integration --gather-results
# 4. Run docgen again: $ resilient-sdk docgen -p fn_mitre_integration
# Or simply paste example outputs manually here. Be sure to remove any personal information
}
Example Function Input Script:
inputs.mitre_technique_id = row.technique_id
inputs.mitre_technique_name = row.technique_name
Example Function Post Process Script:
""" An example of returned data in ResultPayload. Whether it's queried by id or name a list will be returned.
{
"mitre_techniques": [
{
"name": "String",
"description": "String",
"external_references": [{"url": "String"}],
"x_mitre_detection": "String",
"id": "String",
"collection": "String",
"tactic": "String",
"mitre_mitigations": [
{
"name": "String",
"description": "String",
"id": "String",
"collection": "String"
}
]
}
]
}
"""
techniques = results.content["mitre_techniques"]
if not isinstance(techniques, list):
techniques = [techniques]
for technique in techniques:
task_title = "MITRE ATT&CK Technique: " + technique["name"]
mitigations = technique.get("mitre_mitigations", None)
if not mitigations:
mitigation_text = "No mitigations found"
else:
mitigation_text = []
for mitigation in mitigations:
mitigation_text.append(u"""
<h3>{0}</h3>
<p>{1}</p>
""".format(mitigation["name"], mitigation["description"]))
mitigation_text = "".join(mitigation_text)
task_summary=u"""
<h1> Description </h1>
{des}
<h1> Detection </h1>
{det}
<h1> Mitigation </h1>
{miti}
""".format(des=technique.get("description", ""), det=technique.get("x_mitre_detection", ""), miti=mitigation_text)
incident.addTask(task_title, "Detect/Analyze", helper.createRichText(task_summary))
Function - MITRE Technique’s Software¶
Gets a list of Software used by each of the Techniques queried. Techniques can be specified with comma separated strings of IDs or Names. In case both are provided, the ID values take precedence as names are not guaranteed to be unique.
Inputs:
Name |
Type |
Required |
Example |
Tooltip |
---|---|---|---|---|
|
|
No |
|
- |
|
|
No |
|
- |
Outputs:
NOTE: This example might be in JSON format, but
results
is a Python Dictionary on the SOAR platform.
results = {
# TODO: Generate an example of the Function Output within this code block.
# To get the output of a Function:
# 1. Run resilient-circuits in DEBUG mode: $ resilient-circuits run --loglevel=DEBUG
# 2. Invoke the Function in SOAR
# 3. Gather the results using: $ resilient-sdk codegen -p fn_mitre_integration --gather-results
# 4. Run docgen again: $ resilient-sdk docgen -p fn_mitre_integration
# Or simply paste example outputs manually here. Be sure to remove any personal information
}
Example Function Input Script:
# The priority order of inputs is:
# 1. Values entered in the Activity Field pop-up
# 2. Values in the Input Fields added to the layout
# 3. Inputs in the function's workflow
activity_field_given = rule.properties.mitre_technique_id or rule.properties.mitre_technique_name
incident_properties_given = incident.properties.mitre_technique_name or incident.properties.mitre_technique_id
if activity_field_given:
inputs.mitre_technique_name = rule.properties.mitre_technique_name
inputs.mitre_technique_id = rule.properties.mitre_technique_id
elif incident_properties_given:
inputs.mitre_technique_id = incident.properties.mitre_technique_id
inputs.mitre_technique_name = incident.properties.mitre_technique_name
Example Function Post Process Script:
"""
Data returned as a part of ResultPayload:
{
"technique": "STIX ID of the technique",
"name": "Software's name",
"id": "Software's id",
"ref": "URL of software on MITRE's website",
"description": "description of the website",
"platforms": "platforms the software runs on",
"type": "Type - 'malware' or 'tool'"
}
"""
software = results.content["mitre_software"]
for soft in software:
soft_row = incident.addRow("mitre_attack_software")
soft_row["software_technique"] = soft["technique"]
ref = '<a href="{}">'.format(soft["ref"]) +'{}</a> '
soft_row["software_name"] = helper.createRichText(ref.format(soft["name"]))
soft_row["software_id"] = helper.createRichText(ref.format(soft["id"]))
soft_row["software_description"] = helper.createRichText(soft["description"])
soft_row["software_type"] = soft["type"]
soft_row["software_platform"] = ",".join(soft["platforms"])
soft_row["software_description"] = helper.createRichText(soft["description"])
Custom Layouts¶
Import the Data Tables and Custom Fields like the screenshot below:
Data Table - MITRE ATT&CK Groups¶
API Name:¶
mitre_attack_groups
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Group Aliases |
|
|
Known aliases for the Group |
Group Description |
|
|
- |
Group ID |
|
|
MITRE ID for the Group |
Group Name |
|
|
Name of the Group |
Technique ID |
|
|
Technique(s) that the group was queried by. |
Data Table - MITRE ATT&CK Software¶
API Name:¶
mitre_attack_software
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Software Description |
|
|
- |
Software ID |
|
|
Software’s ID in MITRE ATT&CK |
Software Name |
|
|
Name of the software |
Software Platform |
|
|
Platform where the software can be used |
Software Type |
|
|
Category for this software in ATT&CK |
Technique ID |
|
|
MITRE ID of the technique queried for the list of software |
Data Table - MITRE ATT&CK Tactics¶
API Name:¶
mitre_attack_of_incident
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
Confidence |
|
|
Confidence of the mapping |
MITRE Collection |
|
|
Collection/Domain in MITRE that the Tactic comes from |
Tactic ID |
|
|
Tactic’s ID in MITRE |
Tactic Name |
|
|
Tactic’s name in MITRE |
Tactic Reference |
|
|
url links for MITRE ATT&CK Tactic |
Data Table - MITRE ATT&CK Techniques¶
API Name:¶
mitre_attack_techniques
Columns:¶
Column Name |
API Access Name |
Type |
Tooltip |
---|---|---|---|
MITRE Collection |
|
|
Domain/Collection in MITRE that the Technique comes from |
Tactic Name |
|
|
MITRE ATT&CK Tactic name |
Technique Description |
|
|
Description of MITRE ATT&CK Technique |
Technique Detection |
|
|
Detection of MITRE ATT&CK Technique |
Technique ID |
|
|
MITRE ATT&CK Technique ID |
Technique Name |
|
|
MITRE ATT&CK Technique name |
Technique References |
|
|
url references for MITRE ATT&CK Technique |
Custom Fields¶
Label |
API Access Name |
Type |
Prefix |
Placeholder |
Tooltip |
---|---|---|---|---|---|
MITRE ATT&CK Tactic ID |
|
|
|
- |
MITRE ID for Tactic |
MITRE ATT&CK Tactic name |
|
|
|
MITRE tactic name |
MITRE ATT&CK Tactic name |
MITRE ATT&CK Technique ID |
|
|
|
- |
MITRE ID for technique |
MITRE ATT&CK Technique name |
|
|
|
MITRE technique name |
MITRE ATT&CK Technique name |
Rules¶
Rule Name |
Object |
Workflow Triggered |
Condition |
---|---|---|---|
MITRE: Create Task for ATT&CK Technique |
mitre_attack_techniques |
|
|
MITRE: Get Groups per Technique |
incident |
|
|
MITRE: Get Groups using all Techniques |
incident |
|
|
MITRE: Get Tactic information |
incident |
|
|
MITRE: Get Technique information |
incident |
|
|
MITRE: Get Technique’s Software |
incident |
|
|
Troubleshooting & Support¶
Refer to the documentation listed in the Requirements section for troubleshooting information.
For Support¶
This is an IBM supported app. Please search ibm.com/mysupport for assistance.