Skip to content

Latest commit

 

History

History
 
 

layers

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

layers

This folder contains modules and scripts for working with ATT&CK Navigator layers. ATT&CK Navigator Layers are a set of annotations overlayed on top of the ATT&CK Matrix. For more about ATT&CK Navigator layers, visit the ATT&CK Navigator repository. The core module allows users to load, validate, manipulate, and save ATT&CK layers. A brief overview of the components can be found below. All scripts adhere to the MITRE ATT&CK Navigator Layer file format, version 4.0, but will accept legacy version 3.0 layers, upgrading them to version 4.

Core Modules

script description
filter Implements a basic filter object.
gradient Implements a basic gradient object.
layer Provides an interface for interacting with core module's layer representation. A further breakdown can be found in the corresponding section below.
layout Implements a basic layout object.
legenditem Implements a basic legenditem object.
metadata Implements a basic metadata object.
technique Implements a basic technique object.
versions Impelments a basic versions object.

Manipulator Scripts

script description
layerops Provides a means by which to combine multiple ATT&CK layer objects in customized ways. A further breakdown can be found in the corresponding section below.

Exporter Scripts

script description
to_excel 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 below.
to_svg 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 below. This file also contains the SVGConfig object that can be used to configure the SVG export.
Utility Modules
script description
excel_templates Provides a means by which to convert a matrix into a clean excel matrix template.
matrix_gen 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 Provides a means by which to convert a layer file into a marked up svg file.
svg_objects Provides raw templates and supporting functionality for generating svg objects.
Command Line Tools
script description
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. The class currently supports version 3 and 4 of the ATT&CK Layer spec, and will upgrade version 3 layers into compatible version 4 ones whenever possible.

method [x = Layer()] description
x.from_str(input) Loads an ATT&CK layer from a string representation of a json layer.
x.from_dict(input) Loads an ATT&CK layer from a dictionary.
x.from_file(filepath) Loads an ATT&CK layer from a file location specified by the filepath.
x.to_file(filepath) Saves the current state of the loaded ATT&CK layer to a json file denoted by the filepath.
x.to_dict() Returns a representation of the current ATT&CK layer object as a dictionary.
x.to_str() Returns a representation of the current ATT&CK layer object as a string representation of a dictionary.

Example Usage

example_layer3_dict = {
    "name": "example layer",
    "version": "3.0",
    "domain": "mitre-enterprise"
}

example_layer4_dict = {
    "name": "layer v4 example",
    "versions" : {
        "layer" : "4.0",
        "navigator": "4.0"
    },
    "domain": "enterprise-attack"
}

example_layer_location = "/path/to/layer/file.json"
example_layer_out_location = "/path/to/new/layer/file.json"

from layers.core import Layer

layer1 = Layer(example_layer3_dict)              # Create a new layer and load existing data
layer1.to_file(example_layer_out_location)  # Write out the loaded layer to the specified file

layer2 = Layer()                                # Create a new layer object
layer2.from_dict(example_layer4_dict)           # Load layer data into existing layer object
print(layer2.to_dict())                        # Retrieve the loaded layer's data as a dictionary, and print it

layer3 = Layer()                                # Create a new layer object
layer3.from_file(example_layer_location)        # Load layer data from a file into existing layer object

layerops.py

Layerops.py provides the LayerOps class, which is a way to combine layer files in an automated way, using user defined lambda functions. Each LayerOps instance, when created, ingests the provided lambda functions, and stores them for use. An existing LayerOps class can be used to combine layer files according to the initialized lambda using the process method. The breakdown of this two step process is documented in the table below, while examples of both the list and dictionary modes of operation can be found below.

LayerOps()
 x = LayerOps(score=score, comment=comment, enabled=enabled, colors=colors, metadata=metadata, name=name, desc=desc, default_values=default_values)

Each of the inputs takes a lambda function that will be used to combine technique object fields matching the parameter. The one exception to this is default_values, which is an optional dictionary argument containing default values to provide the lambda functions if techniques of the combined layers are missing them.

.process() Method
x.process(data, default_values=default_values)

The process method applies the lambda functions stored during initialization to the layer objects in data. data must be either a list or a dictionary of Layer objects, and is expected to match the format of the lambda equations provided during initialization. default_values is an optional dictionary argument that overrides the currently stored default values with new ones for this specific processing operation.

Example Usage

from layers.manipulators.layerops import LayerOps
from layers.core.layer import Layer

demo = Layer()
demo.from_file("C:\Users\attack\Downloads\layer.json")
demo2 = Layer()
demo2.from_file("C:\Users\attack\Downloads\layer2.json")
demo3 = Layer()
demo3.from_file("C:\Users\attack\Downloads\layer3.json")

# Example 1) Build a LayerOps object that takes a list and averages scores across the layers
lo = LayerOps(score=lambda x: sum(x) / len(x), 
              name=lambda x: x[1], 
              desc=lambda x: "This is an list example")     # Build LayerOps object
out_layer = lo.process([demo, demo2])                       # Trigger processing on a list of demo and demo2 layers
out_layer.to_file("C:\demo_layer1.json")                    # Save averaged layer to file
out_layer2 = lo.process([demo, demo2, demo3])               # Trigger processing on a list of demo, demo2, demo3
visual_aid = out_layer2.to_dict()                           # Retrieve dictionary representation of processed layer

# Example 2) Build a LayerOps object that takes a dictionary and averages scores across the layers
lo2 = LayerOps(score=lambda x: sum([x[y] for y in x]) / len([x[y] for y in x]), 
               color=lambda x: x['b'], 
               desc=lambda x: "This is a dict example")      # Build LayerOps object, with lambda
out_layer3 = lo2.process({'a': demo, 'b': demo2})            # Trigger processing on a dictionary of demo and demo2
dict_layer = out_layer3.to_dict()                            # Retrieve dictionary representation of processed layer
print(dict_layer)                                            # Display retrieved dictionary
out_layer4 = lo2.process({'a': demo, 'b': demo2, 'c': demo3})# Trigger processing on a dictionary of demo, demo2, demo3
out_layer4.to_file("C:\demo_layer4.json")                    # Save averaged layer to file

# Example 3) Build a LayerOps object that takes a single element dictionary and inverts the score
lo3 = LayerOps(score=lambda x: 100 - x['a'],
               desc= lambda x: "This is a simple example")  # Build LayerOps object to invert score (0-100 scale)
out_layer5 = lo3.process({'a': demo})                       # Trigger processing on dictionary of demo
print(out_layer5.to_dict())                                 # Display processed layer in dictionary form
out_layer5.to_file("C:\demo_layer5.json")                   # Save inverted score layer to file

# Example 4) Build a LayerOps object that combines the comments from elements in the list, with custom defaults
lo4 = LayerOps(score=lambda x: '; '.join(x),
               default_values= {
                "comment": "This was an example of new default values"
                },
               desc= lambda x: "This is a defaults example")  # Build LayerOps object to combine descriptions, defaults
out_layer6 = lo4.process([demo2, demo3])                      # Trigger processing on a list of demo2 and demo0
out_layer6.to_file("C:\demo_layer6.json")                     # Save combined comment layer to file

to_excel.py

to_excel.py provides the ToExcel class, which is a way to export an existing layer file as an Excel spreadsheet. 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.

ToExcel()
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 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_xlsx() Method
x.to_xlsx(layer=layer, filepath="layer.xlsx")

The to_xlsx method exports the layer file referenced as layer, as an excel file to the filepath specified.

Example Usage

from layers import Layer
from layers import ToExcel

lay = Layer()
lay.from_file("path/to/layer/file.json")
# Using taxii server for template
t = ToExcel(domain=lay.layer.domain, source='taxii')
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()
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()
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
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

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")