In [1]:
# Delete this cell to re-enable tracebacks
import sys
ipython = get_ipython()
def hide_traceback(exc_tuple=None, filename=None, tb_offset=None,
exception_only=False, running_compiled_code=False):
etype, value, tb = sys.exc_info()
value.__cause__ = None # suppress chained exceptions
return ipython._showtraceback(etype, value, ipython.InteractiveTB.get_exception_only(etype, value))
ipython.showtraceback = hide_traceback
In [2]:
# JSON output syntax highlighting
from __future__ import print_function
from pygments import highlight
from pygments.lexers import JsonLexer, TextLexer
from pygments.formatters import HtmlFormatter
from IPython.display import display, HTML
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
def json_print(inpt):
string = str(inpt)
formatter = HtmlFormatter()
if string[0] == '{':
lexer = JsonLexer()
else:
lexer = TextLexer()
return HTML('<style type="text/css">{}</style>{}'.format(
formatter.get_style_defs('.highlight'),
highlight(string, lexer, formatter)))
globals()['print'] = json_print
The FileSystem suite contains FileSystemStore, FileSystemSource and FileSystemSink. Under the hood, all FileSystem objects point to a file directory (on disk) that contains STIX 2 content.
The directory and file structure of the intended STIX 2 content should be:
stix2_content/
/STIX2 Domain Object type
STIX2 Domain Object
STIX2 Domain Object
.
.
.
/STIX2 Domain Object type
STIX2 Domain Object
STIX2 Domain Object
.
.
.
.
.
.
/STIX2 Domain Object type
The master STIX 2 content directory contains subdirectories, each of which aligns to a STIX 2 domain object type (i.e. "attack-pattern", "campaign", "malware", etc.). Within each STIX 2 domain object subdirectory are JSON files that are STIX 2 domain objects of the specified type. The name of the json files correspond to the ID of the STIX 2 domain object found within that file. A real example of the FileSystem directory structure:
stix2_content/
/attack-pattern
attack-pattern--00d0b012-8a03-410e-95de-5826bf542de6.json
attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22.json
attack-pattern--1b7ba276-eedc-4951-a762-0ceea2c030ec.json
/campaign
/course-of-action
course-of-action--2a8de25c-f743-4348-b101-3ee33ab5871b.json
course-of-action--2c3ce852-06a2-40ee-8fe6-086f6402a739.json
/identity
identity--c78cb6e5-0c4b-4611-8297-d1b8b55e40b5.json
/indicator
/intrusion-set
/malware
malware--1d808f62-cf63-4063-9727-ff6132514c22.json
malware--2eb9b131-d333-4a48-9eb4-d8dec46c19ee.json
/observed-data
/report
/threat-actor
/vulnerability
FileSystemStore is intended for use cases where STIX 2 content is retrieved and pushed to the same file directory. As FileSystemStore is just a wrapper around a paired FileSystemSource and FileSystemSink that point the same file directory.
For use cases where STIX 2 content will only be retrieved or pushed, then a FileSystemSource and FileSystemSink can be used individually. They can also be used individually when STIX 2 content will be retrieved from one distinct file directory and pushed to another.
A note on get(), all_versions(), and query(): The format of the STIX2 content targeted by the FileSystem suite is JSON files. When the FileSystemStore retrieves STIX 2 content (in JSON) from disk, it will attempt to parse the content into full-featured python-stix2 objects and returned as such.
A note on add(): When STIX content is added (pushed) to the file system, the STIX content can be supplied in the following forms: Python STIX objects, Python dictionaries (of valid STIX objects or Bundles), JSON-encoded strings (of valid STIX objects or Bundles), or a (Python) list of any of the previously listed types. Any of the previous STIX content forms will be converted to a STIX JSON object (in a STIX Bundle) and written to disk.
Use the FileSystemStore when you want to both retrieve STIX content from the file system and push STIX content to it, too.
In [7]:
from stix2 import FileSystemStore
# create FileSystemStore
fs = FileSystemStore("/tmp/stix2_store")
# retrieve STIX2 content from FileSystemStore
ap = fs.get("attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22")
mal = fs.get("malware--92ec0cbd-2c30-44a2-b270-73f4ec949841")
# for visual purposes
print(mal)
Out[7]:
In [8]:
from stix2 import ThreatActor, Indicator
# create new STIX threat-actor
ta = ThreatActor(name="Adjective Bear",
sophistication="innovator",
resource_level="government",
goals=[
"compromising media outlets",
"water-hole attacks geared towards political, military targets",
"intelligence collection"
])
# create new indicators
ind = Indicator(description="Crusades C2 implant",
pattern_type="stix",
pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']")
ind1 = Indicator(description="Crusades C2 implant 2",
pattern_type="stix",
pattern="[file:hashes.'SHA-256' = '64c7e05e40a59511743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']")
# add STIX object (threat-actor) to FileSystemStore
fs.add(ta)
# can also add multiple STIX objects to FileSystemStore in one call
fs.add([ind, ind1])
In [9]:
from stix2 import FileSystemSource
# create FileSystemSource
fs_source = FileSystemSource("/tmp/stix2_source")
# retrieve STIX 2 objects
ap = fs_source.get("attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22")
# for visual purposes
print(ap)
Out[9]:
In [10]:
from stix2 import Filter
# create filter for type=malware
query = [Filter("type", "=", "malware")]
# query on the filter
mals = fs_source.query(query)
for mal in mals:
print(mal.id)
Out[10]:
Out[10]:
Out[10]:
Out[10]:
Out[10]:
Out[10]:
Out[10]:
In [11]:
# add more filters to the query
query.append(Filter("modified", ">" , "2017-05-31T21:33:10.772474Z"))
mals = fs_source.query(query)
# for visual purposes
for mal in mals:
print(mal.id)
Out[11]:
Out[11]:
Out[11]:
Out[11]:
In [13]:
from stix2 import FileSystemSink, Campaign, Indicator
# create FileSystemSink
fs_sink = FileSystemSink("/tmp/stix2_sink")
# create STIX objects and add to sink
camp = Campaign(name="The Crusades",
objective="Infiltrating Israeli, Iranian and Palestinian digital infrastructure and government systems.",
aliases=["Desert Moon"])
ind = Indicator(description="Crusades C2 implant",
pattern_type="stix",
pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']")
ind1 = Indicator(description="Crusades C2 implant",
pattern_type="stix",
pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']")
# add Campaign object to FileSystemSink
fs_sink.add(camp)
# can also add STIX objects to FileSystemSink in on call
fs_sink.add([ind, ind1])