Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Create your customized version of Security Content by forking this project and f

# MITRE ATT&CK
### Detection Coverage
To view an up-to-date detection coverage map for all the content tagged with MITRE techniques visit: [https://mitremap.splunkresearch.com/](https://mitremap.splunkresearch.com/) under the **Detection Coverage** layer. Below is a snapshot in time of what we are covering. This map is automatically updated on every release and generated from the [generate-coverage-map.py](https://github.com/splunk/security-content/blob/mitre_maps/bin/generate-coverage-map.py).
To view an up-to-date detection coverage map for all the content tagged with MITRE techniques visit: [https://mitremap.splunkresearch.com/](https://mitremap.splunkresearch.com/) under the **Detection Coverage** layer. Below is a snapshot in time of what technique we currently have some detection coverage for. The darker the shade of blue the more detections we have for this particular technique. This map is automatically updated on every release and generated from the [generate-coverage-map.py](https://github.com/splunk/security-content/blob/mitre_maps/bin/generate-coverage-map.py).

![](docs/mitre-map/coverage.png)

Expand Down
26 changes: 19 additions & 7 deletions bin/generate-actors-map.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ def main(argv):

# parse input variables
parser = argparse.ArgumentParser(description='Detection Priority based on APT groups')
parser.add_argument('--projects_path', default='.', action='store', metavar='N', help='folder containing the projects Mitre Cyber Threat Intelligence Repository, Security Content and Sigma')
parser.add_argument('--output', default='output', action='store', help='result output directory, defaults to output')
parser.add_argument('-p', '--projects_path', default='.', action='store', metavar='N', help='folder containing the projects Mitre Cyber Threat Intelligence Repository, Security Content and Sigma')
parser.add_argument('-o', '--output', default='output', action='store', help='result output directory, defaults to output')
cmdargs = parser.parse_args()

print("get all techniques for group")
Expand All @@ -45,6 +45,7 @@ def main(argv):

def count_techniques(techniques, all_techniques):
counted_techniques = []
final_counted_techniques = []

max_count = 0
actors = []
Expand All @@ -54,7 +55,15 @@ def count_techniques(techniques, all_techniques):
counted_techniques.append({'name': all_technique['name'], 'object': all_technique, 'count': count_technique})
max_count = count_technique if count_technique > max_count else max_count

counted_techniques = sorted(counted_techniques, key = lambda i: i['count'], reverse=True)
for all_technique in all_techniques:
if "." in all_technique["external_references"][0]["external_id"]:
parent_id = all_technique["external_references"][0]["external_id"].split(".")[0]
for counted in counted_techniques:
if parent_id == counted["object"]["external_references"][0]["external_id"]:
counted['count'] += 1
final_counted_techniques.append(counted)

counted_techniques = sorted(final_counted_techniques, key = lambda i: i['count'], reverse=True)

return counted_techniques, max_count

Expand Down Expand Up @@ -131,14 +140,17 @@ def generate_navigator_layer(matched_techniques, max_count, output):
for technique in matched_techniques:
comments = []

if len(technique["splunk_rules"]) > 0:
for splunk_rule in technique["splunk_rules"]:
comments.append("https://github.com/splunk/security-content/blob/develop/detections/" + splunk_rule['filename'])
layer_technique = {
"techniqueID": technique["ID"],
"score" : technique["score"]
"score" : technique["score"],
"showSubtechniques": True
}


if len(technique["splunk_rules"]) > 0:
for splunk_rule in technique["splunk_rules"]:
comments.append("https://github.com/splunk/security-content/blob/develop/detections/" + splunk_rule['filename'])

if len(comments) > 0:
layer_technique["comment"] = "\n\n".join(comments)

Expand Down
30 changes: 21 additions & 9 deletions bin/generate-coverage-map.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ def main(argv):

# parse input variables
parser = argparse.ArgumentParser(description='Detection Coverage')
parser.add_argument('--projects_path', default='.', action='store', metavar='N', help='folder containing the projects Mitre Cyber Threat Intelligence Repository, Security Content and Sigma')
parser.add_argument('--output', default='output', action='store', help='result output directory, defaults to output')
parser.add_argument('-p', '--projects_path', default='.', action='store', metavar='N', help='folder containing the projects Mitre Cyber Threat Intelligence Repository, Security Content and Sigma')
parser.add_argument('-o', '--output', default='output', action='store', help='result output directory, defaults to output')
cmdargs = parser.parse_args()

print("get all techniques")
techniques = get_all_techniques(cmdargs.projects_path)

print("count techniques")
print("load detections")
detections = load_objects(path.join(cmdargs.projects_path),'detections/*.yml')

print("get matched techniques")
Expand All @@ -45,14 +45,24 @@ def main(argv):

def count_detections(matched_techniques):
scored_detections = []
final_scored_detections = []
max_count = 0

for technique in matched_techniques:
if "splunk_rules" in technique:
technique['score'] = len(technique['splunk_rules'])
max_count = technique['score'] if technique['score'] > max_count else max_count
scored_detections.append(technique)
return scored_detections, max_count

for technique in matched_techniques:
if "." in technique['ID']:
parent_id = technique['ID'].split(".")[0]
for scored in scored_detections:
if parent_id == scored['ID']:
scored['score'] += len(technique['splunk_rules'])
final_scored_detections.append(scored)

return final_scored_detections, max_count


def get_all_techniques(projects_path):
Expand Down Expand Up @@ -108,6 +118,7 @@ def generate_navigator_layer(matched_techniques, max_count, output):
layer_technique = {
"techniqueID": technique["ID"],
"score" : technique["score"]

}
else:
layer_technique = {}
Expand All @@ -120,11 +131,12 @@ def generate_navigator_layer(matched_techniques, max_count, output):
# ranging from zero (white) to the maximum score in the file (red)
layer_json["gradient"] = {
"colors": [
"##ffffff",
"#8ec843"
"#ffffff",
"#66b1ff",
"#096ed7"
],
"minValue": 0,
"maxValue": 0
"maxValue": max_count
}

layer_json["filters"] = {
Expand All @@ -146,8 +158,8 @@ def generate_navigator_layer(matched_techniques, max_count, output):
"color": "#ffffff"
},
{
"label": "Available detections",
"color": "#8ec843"
"label": "Some detections available",
"color": "#66b1ff"
}
]

Expand Down
Loading