Skip to content

Commit

Permalink
Merge pull request #521 from mitre-attack/develop
Browse files Browse the repository at this point in the history
Update website to 4.2.0
  • Loading branch information
adpare authored Oct 31, 2024
2 parents 9237fc3 + 9ecedc5 commit e7e296b
Show file tree
Hide file tree
Showing 16 changed files with 526 additions and 394 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# v4.2.0 (2024-10-31)

## Features

* Release ATT&CK content version 16.0.
See detailed changes [here](https://github.com/mitre/cti/releases/tag/ATT%26CK-v16.0).

# v4.1.6 (2024-08-15)

## Docs
Expand Down
663 changes: 377 additions & 286 deletions attack-search/package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion attack-search/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"fake-indexeddb": "^4.0.1",
"jest": "^29.5.0",
"terser-webpack-plugin": "^5.3.7",
"webpack": "^5.76.0",
"webpack": "^5.94.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
}
Expand Down
4 changes: 2 additions & 2 deletions attack-theme/templates/general/base-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@
<script src="/theme/scripts/popper.min.js"></script>
<script src="/theme/scripts/bootstrap-select.min.js"></script>
<script src="/theme/scripts/bootstrap.bundle.min.js"></script>
<script src="/theme/scripts/site.js?{{ range(1, 9002) | random }}"></script>
<script src="/theme/scripts/settings.js?{{ range(1, 9002) | random }}"></script>
<script src="/theme/scripts/site.js"></script>
<script src="/theme/scripts/settings.js"></script>
<script src="/theme/scripts/search_bundle.js"></script>
{% endblock %}
</body>
Expand Down
2 changes: 1 addition & 1 deletion data/faq.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
{
"question": "What technologies does ATT&CK apply to?",
"answer": "Enterprise IT systems covering Windows, macOS, Linux, Network infrastructure devices (Network), and Container technologies (Containers); cloud systems covering Infrastructure-as-a-Service (IaaS), Software-as-a-Service (SaaS), Office 365, Azure Active Directory (Azure AD), and Google Workspace; mobile devices covering Android and iOS."
"answer": "Enterprise IT systems covering Windows, macOS, Linux, Network infrastructure devices (Network), and Container technologies (Containers); cloud systems covering Infrastructure-as-a-Service (IaaS), Software-as-a-Service (SaaS), Office Suite, and Identity Provider; mobile devices covering Android and iOS."
},
{
"question": "How can I use ATT&CK?",
Expand Down
17 changes: 13 additions & 4 deletions data/versions.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
{
"current": {
"name": "v15.1",
"date_start": "April 23, 2024",
"changelog": "updates-april-2024",
"cti_url": "https://github.com/mitre/cti/releases/tag/ATT%26CK-v15.1"
"name": "v16.0",
"date_start": "October 31, 2024",
"changelog": "updates-october-2024",
"cti_url": "https://github.com/mitre/cti/releases/tag/ATT%26CK-v16.0"
},
"previous": [
{
"name": "v15.1",
"aliases": [],
"date_start": "April 23, 2024",
"date_end": "October 30, 2024",
"changelog": "updates-april-2024",
"cti_url": "https://github.com/mitre/cti/releases/tag/ATT%26CK-v15.1",
"commit": "8912d0ec2d68f4ea38b1020eb0507e6933a0f017"
},
{
"name": "v14.1",
"aliases": [],
Expand Down
3 changes: 0 additions & 3 deletions modules/datasources/datasources.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ def generate_markdown_files():
if has_datasource:
data = {}

# Amount of characters per category
group_by = 2

notes = rsg.get_objects_using_notes()
side_menu_data = get_datasources_side_nav_data(datasource_list_no_deprecated_revoked)
data["side_menu_data"] = side_menu_data
Expand Down
117 changes: 73 additions & 44 deletions modules/groups/groups.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
from collections.abc import Iterable
import json
import os

from modules import util
from collections.abc import Iterable
from typing import List

from loguru import logger

from . import groups_config
from modules import util

from .. import site_config
from . import groups_config


def generate_groups():
"""Responsible for verifying group directory and starting off
group markdown generation
"""

"""Responsible for verifying group directory and starting off group markdown generation."""
# Create content pages directory if does not already exist
util.buildhelpers.create_content_pages_dir()

Expand Down Expand Up @@ -44,10 +42,7 @@ def generate_groups():


def generate_markdown_files():
"""Responsible for generating group index page and getting shared data for
all groups
"""

"""Responsible for generating group index page and getting shared data for all groups."""
has_group = False

group_list = util.relationshipgetters.get_group_list()
Expand All @@ -60,9 +55,6 @@ def generate_markdown_files():
if has_group:
data = {}

# Amount of characters per category
group_by = 2

notes = util.relationshipgetters.get_objects_using_notes()
side_menu_data = util.buildhelpers.get_side_menu_data("Groups", "/groups/", group_list_no_deprecated_revoked)
data["side_menu_data"] = side_menu_data
Expand All @@ -84,8 +76,7 @@ def generate_markdown_files():


def generate_group_md(group, side_menu_data, notes):
"""Responsible for generating markdown of all groups"""

"""Responsible for generating markdown of all groups."""
attack_id = util.buildhelpers.get_attack_id(group)

if attack_id:
Expand Down Expand Up @@ -132,13 +123,13 @@ def generate_group_md(group, side_menu_data, notes):

# Get navigator layers for this group
layers = util.buildhelpers.get_navigator_layers(
data["name"],
data["attack_id"],
"group",
"used by",
data["version"] if "version" in data else None,
data["technique_table_data"],
inheritance, # extend legend to include color coding for inherited techniques, if applicable
name=data["name"],
attack_id=data["attack_id"],
obj_type="group",
rel_type="used by",
version=data["version"] if "version" in data else None,
techniques_used=data["technique_table_data"],
inheritance=inheritance, # extend legend to include color coding for inherited techniques, if applicable
)

data["layers"] = []
Expand Down Expand Up @@ -166,13 +157,19 @@ def generate_group_md(group, side_menu_data, notes):
)

# get campaign data for campaign table
data["campaign_data"], data["add_campaign_ref"] = get_campaign_table_data(group, reference_list)
data["campaign_data"], data["add_campaign_ref"] = get_campaign_table_data(
group=group, reference_list=reference_list
)

# Grab software data for Software table
data["software_data"], data["add_software_ref"] = get_software_table_data(group, reference_list)
data["software_data"], data["add_software_ref"] = get_software_table_data(
group=group, reference_list=reference_list
)

if group.get("aliases"):
data["alias_descriptions"] = util.buildhelpers.get_alias_data(group["aliases"][1:], ext_ref)
data["alias_descriptions"] = util.buildhelpers.get_alias_data(
alias_list=group["aliases"][1:], ext_refs=ext_ref
)

data["citations"] = reference_list

Expand All @@ -192,8 +189,7 @@ def generate_group_md(group, side_menu_data, notes):


def get_groups_table_data(group_list):
"""Responsible for generating group table data for the group index page"""

"""Responsible for generating group table data for the group index page."""
groups_table_data = []

# Now the table on the right, which is made up of group data
Expand Down Expand Up @@ -223,9 +219,9 @@ def get_groups_table_data(group_list):


def get_techniques_used_by_group_data(group, reference_list):
"""Given a group and its reference list, get the techniques used by the
group. Check the reference list for citations, if not found
in list, add it.
"""Given a group and its reference list, get the techniques used by the group.
Check the reference list for citations, if not found in list, add it.
"""
technique_list = {}

Expand Down Expand Up @@ -304,7 +300,7 @@ def get_campaign_table_data(group, reference_list):
reference_list = util.buildhelpers.update_reference_list(reference_list, campaign["object"])

if campaign["relationship"].get("description"):
if reference == False:
if reference is False:
reference = True

campaign_list[campaign_id]["desc"] = campaign["relationship"]["description"]
Expand Down Expand Up @@ -344,7 +340,7 @@ def get_campaign_table_data(group, reference_list):


def get_software_table_data(group, reference_list):
"""Given a group, get software table data"""
"""Given a group, get software table data."""
software_list = {}
reference = False

Expand All @@ -361,7 +357,11 @@ def get_software_table_data(group, reference_list):
]
# get malware or tools used by group
software_list, reference = update_software_list(
tools_and_malware, software_list, reference_list, reference, group.get("id")
pairings=tools_and_malware,
software_list=software_list,
reference_list=reference_list,
reference=reference,
id=group.get("id"),
)

# campaigns attributed to groups
Expand All @@ -384,7 +384,11 @@ def get_software_table_data(group, reference_list):
campaign_id = campaign["object"]["id"]
# get malware or tools used by campaigns
software_list, reference = update_software_list(
software_used_by_campaigns, software_list, reference_list, reference, campaign_id
pairings=software_used_by_campaigns,
software_list=software_list,
reference_list=reference_list,
reference=reference,
id=campaign_id,
)

# Moving it to an array because jinja does not like to loop through dictionaries
Expand All @@ -400,12 +404,36 @@ def get_software_table_data(group, reference_list):
return data, reference


def update_software_list(pairings, software_list, reference_list, reference, id):
def update_software_list(pairings: List, software_list: List, reference_list: List, reference: bool, id: str):
"""Update the software list with the given pairings.
This function iterates through the given pairings and updates the software list with
the software that matches the given ID. It also updates the reference list with the
corresponding reference.
Parameters
----------
pairings : List
A list of dictionaries that contain software and reference data.
software_list : List
The list of software to be updated.
reference_list : List
The list of references to be updated.
reference : bool
Whether the reference section should be included.
id : str
The ID of the software to be added to the software list.
Returns
-------
tuple
A tuple containing the updated software list and whether the reference section should be included.
"""
for pairing in pairings:
if pairing["software"].get(id):
for software in pairing["software"][id]:
software_stix_id = software["object"]["id"]
software_attack_id = util.buildhelpers.get_attack_id(software["object"])
software_attack_id = util.buildhelpers.get_attack_id(object=software["object"])
# check if software not in software_list dict
if software_stix_id not in software_list and software_attack_id:
software_list[software_stix_id] = {"id": software_attack_id, "name": software["object"]["name"]}
Expand All @@ -416,7 +444,7 @@ def update_software_list(pairings, software_list, reference_list, reference, id)
software_list[software_stix_id]["descr"] = software["relationship"]["description"]
# Update reference list
reference_list = util.buildhelpers.update_reference_list(
reference_list, software["relationship"]
reference_list=reference_list, obj=software["relationship"]
)

# Check if techniques exists, add techniques used by software
Expand All @@ -426,12 +454,12 @@ def update_software_list(pairings, software_list, reference_list, reference, id)

for technique in pairing["techniques"][software_stix_id]:
tech_data = {}
t_id = util.buildhelpers.get_attack_id(technique["object"])
t_id = util.buildhelpers.get_attack_id(object=technique["object"])
if t_id:
if util.buildhelpers.is_sub_tid(t_id):
tech_data["parent_id"] = util.buildhelpers.get_parent_technique_id(t_id)
tech_data["id"] = util.buildhelpers.get_sub_technique_id(t_id)
tech_data["name"] = util.buildhelpers.get_technique_name(tech_data["parent_id"])
if util.buildhelpers.is_sub_tid(sub_tid=t_id):
tech_data["parent_id"] = util.buildhelpers.get_parent_technique_id(sub_tid=t_id)
tech_data["id"] = util.buildhelpers.get_sub_technique_id(sub_tid=t_id)
tech_data["name"] = util.buildhelpers.get_technique_name(tid=tech_data["parent_id"])
tech_data["sub_name"] = technique["object"]["name"]
else:
tech_data["id"] = t_id
Expand All @@ -440,6 +468,7 @@ def update_software_list(pairings, software_list, reference_list, reference, id)
software_list[software_stix_id]["techniques"].append(tech_data)
return software_list, reference


def generate_sidebar_groups(side_menu_data):
"""Responsible for generating the sidebar for the groups pages."""
logger.info("Generating groups sidebar")
Expand Down
Loading

0 comments on commit e7e296b

Please sign in to comment.