Skip to content

Commit

Permalink
Merge pull request #102 from swimlane/5_4_0_release
Browse files Browse the repository at this point in the history
5.4.0 Release
  • Loading branch information
MSAdministrator authored Apr 4, 2022
2 parents 13e1687 + d380bea commit 2689142
Show file tree
Hide file tree
Showing 22 changed files with 148 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 5.4.0 - 2022-04-04

- Added access to malwares from techniques (thanks aacienfuegos)
- Access deprecated attribute from all MITRE ATT&CK objects (thanks aacienfuegos)
- Updated documentation
- Improved support of ICS framework (thanks cohmoti)
- Bumped minor version

## 5.0.0 - 2021-10-22

- Added new V10 data sources support
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
```
A Python package to interact with MITRE ATT&CK Frameworks

> Current Version is 5.0.0
> Current Version is 5.4.0
**pyattck** is a light-weight framework for MITRE ATT&CK Frameworks. This package extracts details from the MITRE Enterprise, PRE-ATT&CK, Mobile, and ICS Frameworks.

Expand Down
6 changes: 6 additions & 0 deletions docs/enterprise/technique.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ This class provides information about the techniques found under each tactic (co
* Tactics a technique is found in
* Mitigation suggestions for a given technique
* Actor or Group(s) identified as using this technique
* Tools used with a given technique
* Malware used with a given technique
* Subtechniques of a technique if `nested_subtechniques` is set to `True`
* NIST 800-53 Controls related to a technique
* Data Components of a technique
* Data Sources of a technique

Each technique enables you to access the following properties on the object:

Expand Down
4 changes: 4 additions & 0 deletions docs/ics/technique.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ This class provides information about the techniques found under each tactic (co

* Tactics a technique is found in
* Mitigation suggestions for a given technique
* Malware used with a given technique
* NIST 800-53 Controls related to a technique
* Data Components of a technique
* Data Sources of a technique

Each technique enables you to access the following properties on the object:

Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
```
A Python package to interact with MITRE ATT&CK Frameworks

> Current Version is 5.0.0
> Current Version is 5.4.0
**pyattck** is a light-weight framework for MITRE ATT&CK Frameworks. This package extracts details from the MITRE Enterprise, PRE-ATT&CK, Mobile, and ICS Frameworks.

Expand Down
4 changes: 4 additions & 0 deletions docs/mobile/technique.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ This class provides information about the techniques found under each tactic (co
* Tactics a technique is found in
* Mitigation suggestions for a given technique
* Actor or Group(s) identified as using this technique
* Tools used with a given technique
* Malware used with a given technique
* Data Components of a technique
* Data Sources of a technique

Each technique enables you to access the following properties on the object:

Expand Down
1 change: 1 addition & 0 deletions pyattck/enterprise/attckobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, **kwargs):
self.modified = self._set_attribute(kwargs, 'modified')
self.stix = self._set_attribute(kwargs, 'id')
self.type = self._set_attribute(kwargs, 'type')
self.deprecated = self._set_attribute(kwargs, 'x_mitre_deprecated')

def __str__(self):
"""
Expand Down
28 changes: 27 additions & 1 deletion pyattck/enterprise/technique.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class AttckTechnique(AttckObject):
1. tactics
2. mitigations
3. actors
4. tools
5. malwares
6. controls
7. data_components
8. data_sources
1. To iterate over an `techniques` list, do the following:
Expand Down Expand Up @@ -114,7 +119,6 @@ def __init__(self, attck_obj = None, **kwargs):
self.wiki = self._set_wiki(kwargs)
self.contributors = self._set_list_items(kwargs, 'x_mitre_contributors')
self.revoked = self._set_attribute(kwargs, 'revoked')
self.deprecated = self._set_attribute(kwargs, 'x_mitre_deprecated')
self.subtechnique = False if self._set_attribute(kwargs, 'x_mitre_is_subtechnique') is None else True
self.__subtechniques = []
self.command_list = self.__get_filtered_dataset('command_list')
Expand Down Expand Up @@ -305,3 +309,25 @@ def tools(self):
if item in item_dict:
return_list.append(AttckTools(attck_obj=self.__attck_obj, **item_dict[item]))
return return_list

@property
def malwares(self):
"""
Returns all malware objects that are used in a technique
Returns:
[list] -- A list of malware objects defined within the
Enterprise MITRE ATT&CK Framework
"""
from .malware import AttckMalware
return_list = []
item_dict = {}
for item in self.__attck_obj['objects']:
if 'type' in item:
if item['type'] == 'malware':
item_dict[item['id']] = item
if self._RELATIONSHIPS.get(self.stix):
for item in self._RELATIONSHIPS.get(self.stix):
if item in item_dict:
return_list.append(AttckMalware(attck_obj=self.__attck_obj, **item_dict[item]))
return return_list
1 change: 1 addition & 0 deletions pyattck/ics/attckobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, **kwargs):
self.modified = self._set_attribute(kwargs, 'modified')
self.stix = self._set_attribute(kwargs, 'id')
self.type = self._set_attribute(kwargs, 'type')
self.deprecated = self._set_attribute(kwargs, 'x_mitre_deprecated')

def __str__(self):
"""
Expand Down
5 changes: 3 additions & 2 deletions pyattck/ics/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class AttckControl(AttckObject):
kwargs (dict) -- Takes the raw control Json object
"""

def __init__(self, attck_obj = None, **kwargs):
def __init__(self, attck_obj = None, _enterprise_attck_obj=None, **kwargs):
"""
This class represents a compliance Control as defined from
external data sources.
Expand All @@ -51,6 +51,7 @@ def __init__(self, attck_obj = None, **kwargs):
"""
super(AttckControl, self).__init__(**kwargs)
self.__attck_obj = attck_obj
self.__enterprise_attck_obj = _enterprise_attck_obj
for key,val in kwargs.items():
prop_name = key.replace('x_mitre_','')
if not hasattr(self, prop_name):
Expand All @@ -72,5 +73,5 @@ def techniques(self):
if self.stix in val:
for item in self.__attck_obj['objects']:
if 'type' in item and item['type'] == 'attack-pattern' and key == item['id']:
technique_list.append(AttckTechnique(attck_obj=self.__attck_obj, **item))
technique_list.append(AttckTechnique(attck_obj=self.__attck_obj, _enterprise_attck_obj=self.__enterprise_attck_obj, **item))
return technique_list
2 changes: 1 addition & 1 deletion pyattck/ics/datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,5 @@ def techniques(self):
if data_sources.get(self.name):
for component in self.data_components:
if component.name in data_sources[self.name]:
return_list.append(AttckTechnique(attck_obj=self.__ics_attck_obj, **item))
return_list.append(AttckTechnique(attck_obj=self.__ics_attck_obj, _enterprise_attck_obj=self.__attck_obj, **item))
return return_list
8 changes: 4 additions & 4 deletions pyattck/ics/icsattck.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ def controls(self):
if self.__nist_controls_json.get('objects'):
for control in self.__nist_controls_json['objects']:
if control.get('type') == 'course-of-action':
self.__controls.append(AttckControl(attck_obj=self.__attck, **control))
self.__controls.append(AttckControl(attck_obj=self.__attck, _enterprise_attck_obj=self.__enterprise_attck, **control))
return self.__controls

@property
Expand Down Expand Up @@ -215,7 +215,7 @@ def tactics(self):
if not self.__tactics:
for tactic in self.__attck['objects']:
if tactic['type'] == 'x-mitre-tactic':
self.__tactics.append(AttckTactic(attck_obj=self.__attck, **tactic))
self.__tactics.append(AttckTactic(attck_obj=self.__attck, _enterprise_attck_obj=self.__enterprise_attck, **tactic))
return self.__tactics

@property
Expand All @@ -229,7 +229,7 @@ def mitigations(self):
if not self.__mitigations:
for mitigation in self.__attck['objects']:
if mitigation['type'] == 'course-of-action':
self.__mitigations.append(AttckMitigation(attck_obj=self.__attck, **mitigation))
self.__mitigations.append(AttckMitigation(attck_obj=self.__attck, _enterprise_attck_obj=self.__enterprise_attck, **mitigation))
return self.__mitigations

@property
Expand All @@ -243,7 +243,7 @@ def malwares(self):
if not self.__malwares:
for malware in self.__attck['objects']:
if malware['type'] == 'malware':
self.__malwares.append(AttckMalware(attck_obj=self.__attck, **malware))
self.__malwares.append(AttckMalware(attck_obj=self.__attck, _enterprise_attck_obj=self.__enterprise_attck, **malware))
return self.__malwares

@property
Expand Down
5 changes: 3 additions & 2 deletions pyattck/ics/malware.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class AttckMalware(AttckObject):
AttckObject (dict) -- Takes the MITRE ATT&CK Json object as a kwargs values
"""

def __init__(self, attck_obj = None, **kwargs):
def __init__(self, attck_obj = None, _enterprise_attck_obj=None, **kwargs):
"""
This class represents malware as defined by the ICS
MITRE ATT&CK framework.
Expand All @@ -65,6 +65,7 @@ def __init__(self, attck_obj = None, **kwargs):
"""
super(AttckMalware, self).__init__(**kwargs)
self.__attck_obj = attck_obj
self.__enterprise_attck_obj = _enterprise_attck_obj
self.id = self._set_id(kwargs)
self.created_by_ref = self._set_attribute(kwargs, 'created_by_ref')
self.name = self._set_attribute(kwargs, 'name')
Expand Down Expand Up @@ -99,5 +100,5 @@ def techniques(self):
if self._RELATIONSHIPS.get(self.stix):
for item in self._RELATIONSHIPS[self.stix]:
if item in item_dict:
return_list.append(AttckTechnique(attck_obj=self.__attck_obj, **item_dict[item]))
return_list.append(AttckTechnique(attck_obj=self.__attck_obj, _enterprise_attck_obj=self.__enterprise_attck_obj, **item_dict[item]))
return return_list
5 changes: 3 additions & 2 deletions pyattck/ics/mitigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class AttckMitigation(AttckObject):
AttckObject (dict) -- Takes the Mitre ATT&CK Json object as a kwargs values
"""

def __init__(self, attck_obj = None, **kwargs):
def __init__(self, attck_obj = None, _enterprise_attck_obj=None, **kwargs):
"""
This class represents mitigation guidance as defined by the
ICS MITRE ATT&CK framework.
Expand All @@ -64,6 +64,7 @@ def __init__(self, attck_obj = None, **kwargs):
"""
super(AttckMitigation, self).__init__(**kwargs)
self.__attck_obj = attck_obj
self.__enterprise_attck_obj = _enterprise_attck_obj
self.created_by_ref = self._set_attribute(kwargs, 'created_by_ref')
self.id = self._set_id(kwargs)
self.name = self._set_attribute(kwargs, 'name')
Expand Down Expand Up @@ -97,5 +98,5 @@ def techniques(self):
if self._RELATIONSHIPS.get(self.stix):
for item in self._RELATIONSHIPS[self.stix]:
if item in item_dict:
return_list.append(AttckTechnique(attck_obj=self.__attck_obj, **item_dict[item]))
return_list.append(AttckTechnique(attck_obj=self.__attck_obj, _enterprise_attck_obj=self.__enterprise_attck_obj, **item_dict[item]))
return return_list
7 changes: 4 additions & 3 deletions pyattck/ics/tactic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


class AttckTactic(AttckObject):

"""ICS MITRE ATT&CK Tactic object.
A child class of AttckObject
Expand Down Expand Up @@ -57,7 +56,7 @@ class AttckTactic(AttckObject):
AttckObject (dict) -- Takes the Mitre ATT&CK Json object as a kwargs values
"""

def __init__(self, attck_obj = None, **kwargs):
def __init__(self, attck_obj=None, _enterprise_attck_obj=None, **kwargs):
"""
This class represents a Tactic as defined by the
ICS MITRE ATT&CK framework.
Expand All @@ -68,6 +67,7 @@ def __init__(self, attck_obj = None, **kwargs):
"""
super(AttckTactic, self).__init__(**kwargs)
self.__attck_obj = attck_obj
self.__enterprise_attck_obj = _enterprise_attck_obj
self.id = self._set_id(kwargs)
self.created_by_ref = self._set_attribute(kwargs, 'created_by_ref')
self.type = self._set_attribute(kwargs, 'type')
Expand Down Expand Up @@ -98,5 +98,6 @@ def techniques(self):
if 'kill_chain_phases' in item:
for prop in item['kill_chain_phases']:
if str(prop['phase_name']).lower() == str(self.short_name).lower():
technique_list.append(AttckTechnique(attck_obj=self.__attck_obj, **item))
technique_list.append(AttckTechnique(attck_obj=self.__attck_obj,
_enterprise_attck_obj=self.__enterprise_attck_obj, **item))
return technique_list
22 changes: 13 additions & 9 deletions pyattck/ics/technique.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


class AttckTechnique(AttckObject):

"""ICS MITRE ATT&CK Technique object.
A child class of AttckObject
Expand Down Expand Up @@ -82,7 +81,7 @@ class AttckTechnique(AttckObject):
AttckObject (dict) -- Takes the MITRE ATT&CK Json object as a kwargs values
"""

def __init__(self, attck_obj = None, _enterprise_attck_obj=None, **kwargs):
def __init__(self, attck_obj=None, _enterprise_attck_obj=None, **kwargs):
"""
This class represents a Technique as defined by the
ICS MITRE ATT&CK framework.
Expand Down Expand Up @@ -117,7 +116,6 @@ def __init__(self, attck_obj = None, _enterprise_attck_obj=None, **kwargs):
self.wiki = self._set_wiki(kwargs)
self.contributors = self._set_list_items(kwargs, 'x_mitre_contributors')
self.revoked = self._set_attribute(kwargs, 'revoked')
self.deprecated = self._set_attribute(kwargs, 'x_mitre_deprecated')
self.subtechnique = False if self._set_attribute(kwargs, 'x_mitre_is_subtechnique') is None else True
self.command_list = self.__get_filtered_dataset('command_list')
self.commands = self.__get_filtered_dataset('commands')
Expand Down Expand Up @@ -170,17 +168,19 @@ def data_sources(self):
if 'x-mitre-data-source' in item['type']:
if temp_data_source_dict.get(item['name']):
data_source_list.append(AttckDataSource(
attck_obj=self.__enterprise_attck_obj,
attck_obj=self.__enterprise_attck_obj,
_data_component_filter=temp_data_source_dict[item['name']],
_ics_attck_obj=self.__attck_obj,
**item)
)
del temp_data_source_dict[item['name']]
if temp_data_source_dict:
for key,val in temp_data_source_dict.items():
for key, val in temp_data_source_dict.items():
data_source_list.append(
AttckDataSource(
attck_obj=self.__enterprise_attck_obj,
_data_component_filter=val,
_ics_attck_obj=self.__attck_obj,
**{
'name': key,
'data_components': val
Expand All @@ -204,7 +204,9 @@ def tactics(self):
if 'x-mitre-tactic' in item['type']:
for tact in self._tactic:
if str(tact).lower() == str(item['x_mitre_shortname']).lower():
tactic_list.append(AttckTactic(attck_obj=self.__attck_obj, **item))
tactic_list.append(
AttckTactic(attck_obj=self.__attck_obj, _enterprise_attck_obj=self.__enterprise_attck_obj,
**item))
return tactic_list

@tactics.setter
Expand All @@ -226,7 +228,7 @@ def tactics(self, obj):
self._tactic = temp_list
except:
self._tactic = ['no phase_name']

@property
def mitigations(self):
"""
Expand All @@ -246,5 +248,7 @@ def mitigations(self):
if self._RELATIONSHIPS.get(self.stix):
for item in self._RELATIONSHIPS[self.stix]:
if item in item_dict:
return_list.append(AttckMitigation(attck_obj=self.__attck_obj, **item_dict[item]))
return return_list
return_list.append(
AttckMitigation(attck_obj=self.__attck_obj, _enterprise_attck_obj=self.__enterprise_attck_obj,
**item_dict[item]))
return return_list
1 change: 1 addition & 0 deletions pyattck/mobile/mobileattckobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, **kwargs):
self.modified = self._set_attribute(kwargs, 'modified')
self.stix = self._set_attribute(kwargs, 'id')
self.type = self._set_attribute(kwargs, 'type')
self.deprecated = self._set_attribute(kwargs, 'x_mitre_deprecated')

def __str__(self):
return_dict = {}
Expand Down
Loading

0 comments on commit 2689142

Please sign in to comment.