Skip to content
This repository has been archived by the owner on Dec 11, 2023. It is now read-only.

Commit

Permalink
merging develop into master
Browse files Browse the repository at this point in the history
  • Loading branch information
isaisabel committed Oct 5, 2020
2 parents 73aefc1 + 186c59f commit 3ef0ffd
Show file tree
Hide file tree
Showing 13 changed files with 1,328 additions and 15 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# v1.6 - 5 October 2020
## Improvements
- Added [layer to SVG](https://github.com/mitre-attack/attack-scripts/tree/master/layers#to_svgpy) converter. See issue [#1](https://github.com/mitre-attack/attack-scripts/issues/1).
- Added option to filter mappings by tactic in [technique_mappings_to_csv](technique_mappings_to_csv.py). See pull request [#46](https://github.com/mitre-attack/attack-scripts/pull/46).

# v1.5.2 - 2 September 2020
## Improvements
- Clarified documentation on creation of virtual environments for Windows compatibility.
Expand Down
76 changes: 74 additions & 2 deletions layers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,18 @@ This folder contains modules and scripts for working with ATT&CK Navigator layer
| script | description |
|:-------|:------------|
| [to_excel](exporters/to_excel.py) | Provides a means by which to export an ATT&CK Layer to an excel file. A further breakdown can be found in the corresponding [section](#to_excel.py) below. |
| [to_svg](exporters/to_svg.py) | Provides a means by which to export an ATT&CK layer to an svg image file. A further breakdown can be found in the corresponding [section](#to_svg.py) below. This file also contains the `SVGConfig` object that can be used to configure the SVG export.|
##### Utility Modules
| script | description |
|:-------|:------------|
| [excel_templates](exporters/excel_templates.py) | Provides a means by which to convert a matrix into a clean excel matrix template. |
| [matrix_gen](exporters/matrix_gen.py) | Provides a means by which to generate a matrix from raw data, either from the ATT&CK TAXII server or from a local STIX Bundle. |
| [svg_templates](exporters/svg_templates.py) | Provides a means by which to convert a layer file into a marked up svg file. |
| [svg_objects](exporters/svg_objects.py) | Provides raw templates and supporting functionality for generating svg objects. |
##### Command Line Tools
| script | description |
|:-------|:------------|
| [layerExporter_cli.py](layerExporter_cli.py) | A commandline utility to export Layer files to excel or svg formats using the exporter tools. Run with `-h` for usage. |

## Layer
The Layer class provides format validation and read/write capabilities to aid in working with ATT&CK Navigator Layers in python. It is the primary interface through which other Layer-related classes defined in the core module should be used. The Layer class API and a usage example are below.
Expand Down Expand Up @@ -140,9 +147,9 @@ tells the exporter what data source to use when building the output matrix. Vali
x = ToExcel(domain='enterprise', source='taxii', local=None)
```
The ToExcel constructor takes domain, server, and local arguments during instantiation. The domain can
be either `enterprise` or `mobile`, and can be pulled directly from a layer file as `layer.domain`. The source argument tells the matrix generation tool which data source to use when building the matrix. `taxii` indicates that the tool should utilize the `cti-taxii` server when building the matrix, while the `local` option indicates that it should use a local bundle respectively. The local argument is only required if the source is set to `local`, in which case it should be a path to a local stix bundle.
be either `enterprise` or `mobile`, and can be pulled directly from a layer file as `layer.domain`. The source argument tells the matrix generation tool which data source to use when building the matrix. `taxii` indicates that the tool should utilize the official ATT&CK Taxii Server (`cti-taxii`) when building the matrix, while the `local` option indicates that it should use a local bundle respectively. The local argument is only required if the source is set to `local`, in which case it should be a path to a local stix bundle.

##### .to_file() Method
##### .to_xlsx() Method
```python
x.to_xlsx(layer=layer, filepath="layer.xlsx")
```
Expand All @@ -162,4 +169,69 @@ t.to_xlsx(layer=lay, filepath="demo.xlsx")
#Using local stix data for template
t2 = ToExcel(domain='mobile', source='local', local='path/to/local/stix.json')
t2.to_xlsx(layer=lay, filepath="demo2.xlsx")
```

## to_svg.py
to_svg.py provides the ToSvg class, which is a way to export an existing layer file as an SVG image file. The ToSvg class, like the ToExcel class, has an optional parameter for the initialization function, that
tells the exporter what data source to use when building the output matrix. Valid options include using live data from cti-taxii.mitre.org or using a local STIX bundle.

##### ToSvg()
```python
x = ToSvg(domain='enterprise', source='taxii', local=None, config=None)
```
The ToSvg constructor, just like the ToExcel constructor, takes domain, server, and local arguments during instantiation. The domain can be either `enterprise` or `mobile`, and can be pulled directly from a layer file as `layer.domain`. The source argument tells the matrix generation tool which data source to use when building the matrix. `taxii` indicates that the tool should utilize the `cti-taxii` server when building the matrix, while the `local` option indicates that it should use a local bundle respectively. The local argument is only required if the source is set to `local`, in which case it should be a path to a local stix bundle. The `config` parameter is an optional SVGConfig object that can be used to configure the export as desired. If not provided, the configuration for the export will be set to default values.

##### SVGConfig()
```python
y = SVGConfig(width=8.5, height=11, headerHeight=1, unit="in", showSubtechniques="expanded",
font="sans-serif", tableBorderColor="#6B7279", showHeader=True, legendDocked=True,
legendX=0, legendY=0, legendWidth=2, legendHeight=1, showLegend=True, showFilters=True,
showAbout=True, border=0.104)
```
The SVGConfig object is used to configure how an SVG export behaves. The defaults for each of the available values can be found in the declaration above, and a brief explanation for each field is included in the table below. The config object should be provided to the ToSvg object during instantiation, but if values need to be updated on the fly, the currently loaded configuration can be interacted with at `ToSvg().config`. The configuration can also be populated from a json file using the `.load_from_file(filename="path/to/file.json")` method, or stored to one using the `.save_to_file(filename="path/to/file.json)` method.

| attribute| description | type | default value |
|:-------|:------------|:------------|:------------|
| width | Desired SVG width | number | 8.5 |
| height | Desired SVG height | number | 11 |
| headerHeight | Desired Header Block height | number | 1 |
| unit | SVG measurement units (qualifies width, height, etc.) - "in", "cm", "px", "em", or "pt"| string | "in" |
| showSubtechniques | Display form for subtechniques - "all", "expanded" (decided by layer), or "none" | string | "expanded" |
| font | What font style to use - "serif", "sans-serif", or "monospace" | string | "sans-serif" |
| tableBorderColor | Hex color to use for the technique borders | string | "#6B7279" |
| showHeader | Whether or not to show Header Blocks | bool | True |
| legendDocked | Whether or not the legend should be docked | bool | True |
| legendX | Where to place the legend on the x axis if not docked | number | 0 |
| legendY | Where to place the legend on the y axis if not docked | number | 1 |
| legendWidth | Width of the legend if not docked | number | 2 |
| legendHeight | Height of the legend if not docked | number | 1 |
| showLegend | Whether or not to show the legend | bool | True |
| showFilters | Whether or not to show the Filter Header Block | bool | True |
| showAbout | Whether or not to show the About Header Block | bool | True |
| border | What default border width to use | number | 0.104 |

##### .to_svg() Method
```python
x.to_svg(layer=layer, filepath="layer.svg")
```
The to_svg method exports the layer file referenced as `layer`, as an excel file to the
`filepath` specified.

#### Example Usage
```python
from layers import Layer
from layers import ToSvg, SVGConfig

lay = Layer()
lay.from_file("path/to/layer/file.json")
# Using taxii server for template
t = ToSvg(domain=lay.layer.domain, source='taxii')
t.to_svg(layer=lay, filepath="demo.svg")
#Using local stix data for template

conf = SVGConfig()
conf.load_from_file(filename="path/to/poster/config.json")

t2 = ToSvg(domain='mobile', source='local', local='path/to/local/stix.json', config=conf)
t2.to_svg(layer=lay, filepath="demo2.svg")
```
4 changes: 3 additions & 1 deletion layers/exporters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .excel_templates import ExcelTemplates
from .matrix_gen import MatrixGen
from .to_excel import ToExcel
from .to_excel import ToExcel
from .to_svg import ToSvg, SVGConfig
from .svg_templates import SvgTemplates
Binary file added layers/exporters/fonts/monospace.ttf
Binary file not shown.
Binary file added layers/exporters/fonts/sans-serif.ttf
Binary file not shown.
Binary file added layers/exporters/fonts/serif.ttf
Binary file not shown.
24 changes: 20 additions & 4 deletions layers/exporters/matrix_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,20 @@ def __init__(self, source='taxii', local=None):
self.matrix = {}
self._build_matrix()

@staticmethod
def _remove_revoked_deprecated(content):
"""Remove any revoked or deprecated objects from queries made to the data source"""
return list(
filter(
lambda x: x.get("x_mitre_deprecated", False) is False and x.get("revoked", False) is False,
content
)
)

def _search(self, domain, query):
interum = self.collections[domain].query(query)
return self._remove_revoked_deprecated(interum)

def _get_tactic_listing(self, domain='enterprise'):
"""
INTERNAL - retrieves tactics for the associated domain
Expand All @@ -117,11 +131,11 @@ def _get_tactic_listing(self, domain='enterprise'):
"""
tactics = {}
t_filt = []
matrix = self.collections[domain].query([Filter('type', '=', 'x-mitre-matrix')])
matrix = self._search(domain, [Filter('type', '=', 'x-mitre-matrix')])
for i in range(len(matrix)):
tactics[matrix[i]['name']] = []
for tactic_id in matrix[i]['tactic_refs']:
tactics[matrix[i]['name']].append(self.collections[domain].query([Filter('id', '=', tactic_id)])[0])
tactics[matrix[i]['name']].append(self._search(domain,([Filter('id', '=', tactic_id)]))[0])
for entry in tactics[matrix[0]['name']]:
self.convert_data[entry['x_mitre_shortname']] = entry['name']
self.convert_data[entry['name']] = entry['x_mitre_shortname']
Expand All @@ -137,9 +151,11 @@ def _get_technique_listing(self, tactic, domain='enterprise'):
"""
techniques = []
subtechs = {}
techs = self.collections[domain].query([Filter('type', '=', 'attack-pattern'), Filter('kill_chain_phases.phase_name', '=', tactic)])
techs = self._search(domain,[Filter('type', '=', 'attack-pattern'),
Filter('kill_chain_phases.phase_name', '=', tactic)])
for entry in techs:
if entry['kill_chain_phases'][0]['kill_chain_name'] == 'mitre-attack':
if entry['kill_chain_phases'][0]['kill_chain_name'] == 'mitre-attack' or \
entry['kill_chain_phases'][0]['kill_chain_name'] == 'mitre-mobile-attack':
tid = [t['external_id'] for t in entry['external_references'] if 'attack' in t['source_name']]
if '.' not in tid[0]:
techniques.append(MatrixEntry(id=tid[0], name=entry['name']))
Expand Down
Loading

0 comments on commit 3ef0ffd

Please sign in to comment.