Merge branch 'master' of github.com:oasis-open/cti-python-stix2

master
chrisr3d 2020-04-02 17:55:24 +02:00
commit 65a943d892
17 changed files with 223 additions and 265 deletions

View File

@ -7,10 +7,10 @@ import re
import stix2 import stix2
from .base import _STIXBase from .base import _Observable, _STIXBase
from .exceptions import ParseError from .exceptions import ParseError
from .markings import _MarkingsMixin from .markings import _MarkingsMixin
from .utils import _get_dict from .utils import SCO21_EXT_REGEX, TYPE_REGEX, _get_dict
STIX2_OBJ_MAPS = {} STIX2_OBJ_MAPS = {}
@ -275,22 +275,54 @@ def _register_observable(new_observable, version=None):
OBJ_MAP_OBSERVABLE[new_observable._type] = new_observable OBJ_MAP_OBSERVABLE[new_observable._type] = new_observable
def _register_observable_extension(observable, new_extension, version=None): def _register_observable_extension(
observable, new_extension, version=stix2.DEFAULT_VERSION,
):
"""Register a custom extension to a STIX Cyber Observable type. """Register a custom extension to a STIX Cyber Observable type.
Args: Args:
observable: An observable object observable: An observable class or instance
new_extension (class): A class to register in the Observables new_extension (class): A class to register in the Observables
Extensions map. Extensions map.
version (str): Which STIX2 version to use. (e.g. "2.0", "2.1"). If version (str): Which STIX2 version to use. (e.g. "2.0", "2.1").
None, use latest version. Defaults to the latest supported version.
""" """
if version: obs_class = observable if isinstance(observable, type) else \
v = 'v' + version.replace('.', '') type(observable)
else: ext_type = new_extension._type
# Use default version (latest) if no version was provided.
v = 'v' + stix2.DEFAULT_VERSION.replace('.', '') if not issubclass(obs_class, _Observable):
raise ValueError("'observable' must be a valid Observable class!")
if version == "2.0":
if not re.match(TYPE_REGEX, ext_type):
raise ValueError(
"Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." %
ext_type,
)
else: # 2.1+
if not re.match(SCO21_EXT_REGEX, ext_type):
raise ValueError(
"Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, hyphen (-), and end "
"with '-ext'." % ext_type,
)
if len(ext_type) < 3 or len(ext_type) > 250:
raise ValueError(
"Invalid extension type name '%s': must be between 3 and 250"
" characters." % ext_type,
)
if not new_extension._properties:
raise ValueError(
"Invalid extension: must define at least one property: " +
ext_type,
)
v = 'v' + version.replace('.', '')
try: try:
observable_type = observable._type observable_type = observable._type
@ -304,7 +336,7 @@ def _register_observable_extension(observable, new_extension, version=None):
EXT_MAP = STIX2_OBJ_MAPS[v]['observable-extensions'] EXT_MAP = STIX2_OBJ_MAPS[v]['observable-extensions']
try: try:
EXT_MAP[observable_type][new_extension._type] = new_extension EXT_MAP[observable_type][ext_type] = new_extension
except KeyError: except KeyError:
if observable_type not in OBJ_MAP_OBSERVABLE: if observable_type not in OBJ_MAP_OBSERVABLE:
raise ValueError( raise ValueError(
@ -313,7 +345,7 @@ def _register_observable_extension(observable, new_extension, version=None):
% observable_type, % observable_type,
) )
else: else:
EXT_MAP[observable_type] = {new_extension._type: new_extension} EXT_MAP[observable_type] = {ext_type: new_extension}
def _collect_stix2_mappings(): def _collect_stix2_mappings():

View File

@ -1,6 +1,8 @@
from collections import OrderedDict from collections import OrderedDict
import re import re
import six
from .base import _cls_init, _Extension, _Observable, _STIXBase from .base import _cls_init, _Extension, _Observable, _STIXBase
from .core import ( from .core import (
STIXDomainObject, _register_marking, _register_object, STIXDomainObject, _register_marking, _register_object,
@ -113,24 +115,23 @@ def _custom_observable_builder(cls, type, properties, version, id_contrib_props=
def _custom_extension_builder(cls, observable, type, properties, version): def _custom_extension_builder(cls, observable, type, properties, version):
if not observable or not issubclass(observable, _Observable):
raise ValueError("'observable' must be a valid Observable class!") try:
prop_dict = OrderedDict(properties)
except TypeError as e:
six.raise_from(
ValueError(
"Extension properties must be dict-like, e.g. a list "
"containing tuples. For example, "
"[('property1', IntegerProperty())]",
),
e,
)
class _CustomExtension(cls, _Extension): class _CustomExtension(cls, _Extension):
if not re.match(TYPE_REGEX, type):
raise ValueError(
"Invalid extension type name '%s': must only contain the "
"characters a-z (lowercase ASCII), 0-9, and hyphen (-)." % type,
)
elif len(type) < 3 or len(type) > 250:
raise ValueError("Invalid extension type name '%s': must be between 3 and 250 characters." % type)
if not properties or not isinstance(properties, list):
raise ValueError("Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]")
_type = type _type = type
_properties = OrderedDict(properties) _properties = prop_dict
def __init__(self, **kwargs): def __init__(self, **kwargs):
_Extension.__init__(self, **kwargs) _Extension.__init__(self, **kwargs)

View File

@ -821,27 +821,24 @@ def test_custom_extension_invalid_type_name():
def test_custom_extension_no_properties(): def test_custom_extension_no_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', None) @stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', None)
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_empty_properties(): def test_custom_extension_empty_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', []) @stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', [])
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_dict_properties(): def test_custom_extension_dict_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', {}) @stix2.v20.CustomExtension(stix2.v20.DomainName, 'x-new-ext2', {})
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_no_init_1(): def test_custom_extension_no_init_1():

View File

@ -14,14 +14,7 @@ COA_WITH_BIN_JSON = """{
"created": "2016-04-06T20:03:48.000Z", "created": "2016-04-06T20:03:48.000Z",
"modified": "2016-04-06T20:03:48.000Z", "modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter", "name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...", "description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ..."
"action_type": "textual:text/plain",
"os_execution_envs": [
"a",
"b",
"c"
],
"action_bin": "aGVsbG8gd29ybGQ="
}""" }"""
@ -33,17 +26,7 @@ COA_WITH_REF_JSON = """{
"created": "2016-04-06T20:03:48.000Z", "created": "2016-04-06T20:03:48.000Z",
"modified": "2016-04-06T20:03:48.000Z", "modified": "2016-04-06T20:03:48.000Z",
"name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter", "name": "Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
"description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ...", "description": "This is how to add a filter rule to block inbound access to TCP port 80 to the existing UDP 1434 filter ..."
"action_type": "textual:text/plain",
"os_execution_envs": [
"a",
"b",
"c"
],
"action_reference": {
"source_name": "a source",
"description": "description of a source"
}
}""" }"""
@ -84,15 +67,4 @@ def test_parse_course_of_action(sdo_json, sdo_dict):
assert getattr(coa, attr_name) == cmp_value assert getattr(coa, attr_name) == cmp_value
def test_course_of_action_constraint():
with pytest.raises(stix2.exceptions.MutuallyExclusivePropertiesError):
stix2.v21.CourseOfAction(
name="Add TCP port 80 Filter Rule to the existing Block UDP 1434 Filter",
action_bin="aGVsbG8gd29ybGQ=",
action_reference=stix2.v21.ExternalReference(
source_name="a source",
description="description of a source",
),
)
# TODO: Add other examples # TODO: Add other examples

View File

@ -800,7 +800,7 @@ def test_custom_extension_wrong_observable_type():
) )
def test_custom_extension_with_list_and_dict_properties_observable_type(data): def test_custom_extension_with_list_and_dict_properties_observable_type(data):
@stix2.v21.CustomExtension( @stix2.v21.CustomExtension(
stix2.v21.UserAccount, 'some-extension', [ stix2.v21.UserAccount, 'x-some-extension-ext', [
('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True)), ('keys', stix2.properties.ListProperty(stix2.properties.DictionaryProperty, required=True)),
], ],
) )
@ -876,32 +876,29 @@ def test_custom_extension_invalid_type_name():
def test_custom_extension_no_properties(): def test_custom_extension_no_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-ext2', None) @stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new2-ext', None)
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_empty_properties(): def test_custom_extension_empty_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-ext2', []) @stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new2-ext', [])
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_dict_properties(): def test_custom_extension_dict_properties():
with pytest.raises(ValueError) as excinfo: with pytest.raises(ValueError):
@stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new-ext2', {}) @stix2.v21.CustomExtension(stix2.v21.DomainName, 'x-new2-ext', {})
class BarExtension(): class BarExtension():
pass pass
assert "Must supply a list, containing tuples." in str(excinfo.value)
def test_custom_extension_no_init_1(): def test_custom_extension_no_init_1():
@stix2.v21.CustomExtension( @stix2.v21.CustomExtension(
stix2.v21.DomainName, 'x-new-extension', [ stix2.v21.DomainName, 'x-new-extension-ext', [
('property1', stix2.properties.StringProperty(required=True)), ('property1', stix2.properties.StringProperty(required=True)),
], ],
) )
@ -914,7 +911,7 @@ def test_custom_extension_no_init_1():
def test_custom_extension_no_init_2(): def test_custom_extension_no_init_2():
@stix2.v21.CustomExtension( @stix2.v21.CustomExtension(
stix2.v21.DomainName, 'x-new-ext2', [ stix2.v21.DomainName, 'x-new2-ext', [
('property1', stix2.properties.StringProperty(required=True)), ('property1', stix2.properties.StringProperty(required=True)),
], ],
) )
@ -949,14 +946,14 @@ def test_custom_and_spec_extension_mix():
file_obs = stix2.v21.File( file_obs = stix2.v21.File(
name="my_file.dat", name="my_file.dat",
extensions={ extensions={
"x-custom1": { "x-custom1-ext": {
"a": 1, "a": 1,
"b": 2, "b": 2,
}, },
"ntfs-ext": { "ntfs-ext": {
"sid": "S-1-whatever", "sid": "S-1-whatever",
}, },
"x-custom2": { "x-custom2-ext": {
"z": 99.9, "z": 99.9,
"y": False, "y": False,
}, },
@ -969,8 +966,8 @@ def test_custom_and_spec_extension_mix():
allow_custom=True, allow_custom=True,
) )
assert file_obs.extensions["x-custom1"] == {"a": 1, "b": 2} assert file_obs.extensions["x-custom1-ext"] == {"a": 1, "b": 2}
assert file_obs.extensions["x-custom2"] == {"y": False, "z": 99.9} assert file_obs.extensions["x-custom2-ext"] == {"y": False, "z": 99.9}
assert file_obs.extensions["ntfs-ext"].sid == "S-1-whatever" assert file_obs.extensions["ntfs-ext"].sid == "S-1-whatever"
assert file_obs.extensions["raster-image-ext"].image_height == 1024 assert file_obs.extensions["raster-image-ext"].image_height == 1024

View File

@ -120,3 +120,14 @@ def test_external_reference_source_required():
assert excinfo.value.cls == stix2.v21.ExternalReference assert excinfo.value.cls == stix2.v21.ExternalReference
assert excinfo.value.properties == ["source_name"] assert excinfo.value.properties == ["source_name"]
def test_external_reference_bad_hash():
with pytest.raises(stix2.exceptions.InvalidValueError):
stix2.v21.ExternalReference(
source_name="ACME Threat Intel",
description="Threat report",
hashes={
"SHA-123": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
},
)

View File

@ -14,9 +14,6 @@ EXPECTED_INDICATOR = """{
"id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7", "id": "indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7",
"created": "2017-01-01T00:00:01.000Z", "created": "2017-01-01T00:00:01.000Z",
"modified": "2017-01-01T00:00:01.000Z", "modified": "2017-01-01T00:00:01.000Z",
"indicator_types": [
"malicious-activity"
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']", "pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"pattern_type": "stix", "pattern_type": "stix",
"pattern_version": "2.1", "pattern_version": "2.1",
@ -29,7 +26,6 @@ EXPECTED_INDICATOR_REPR = "Indicator(" + " ".join("""
id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7', id='indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7',
created='2017-01-01T00:00:01.000Z', created='2017-01-01T00:00:01.000Z',
modified='2017-01-01T00:00:01.000Z', modified='2017-01-01T00:00:01.000Z',
indicator_types=['malicious-activity'],
pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']", pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
pattern_type='stix', pattern_type='stix',
pattern_version='2.1', pattern_version='2.1',
@ -49,7 +45,6 @@ def test_indicator_with_all_required_properties():
pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']", pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
pattern_type="stix", pattern_type="stix",
valid_from=epoch, valid_from=epoch,
indicator_types=['malicious-activity'],
) )
assert ind.revoked is False assert ind.revoked is False
@ -103,8 +98,8 @@ def test_indicator_required_properties():
stix2.v21.Indicator() stix2.v21.Indicator()
assert excinfo.value.cls == stix2.v21.Indicator assert excinfo.value.cls == stix2.v21.Indicator
assert excinfo.value.properties == ["indicator_types", "pattern", "pattern_type", "valid_from"] assert excinfo.value.properties == ["pattern", "pattern_type", "valid_from"]
assert str(excinfo.value) == "No values for required properties for Indicator: (indicator_types, pattern, pattern_type, valid_from)." assert str(excinfo.value) == "No values for required properties for Indicator: (pattern, pattern_type, valid_from)."
def test_indicator_required_property_pattern(): def test_indicator_required_property_pattern():
@ -163,9 +158,6 @@ def test_created_modified_time_are_identical_by_default():
"id": INDICATOR_ID, "id": INDICATOR_ID,
"created": "2017-01-01T00:00:01Z", "created": "2017-01-01T00:00:01Z",
"modified": "2017-01-01T00:00:01Z", "modified": "2017-01-01T00:00:01Z",
"indicator_types": [
"malicious-activity",
],
"pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']", "pattern": "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']",
"pattern_type": "stix", "pattern_type": "stix",
"valid_from": "1970-01-01T00:00:01Z", "valid_from": "1970-01-01T00:00:01Z",
@ -181,7 +173,6 @@ def test_parse_indicator(data):
assert idctr.created == dt.datetime(2017, 1, 1, 0, 0, 1, tzinfo=pytz.utc) assert idctr.created == dt.datetime(2017, 1, 1, 0, 0, 1, tzinfo=pytz.utc)
assert idctr.modified == dt.datetime(2017, 1, 1, 0, 0, 1, tzinfo=pytz.utc) assert idctr.modified == dt.datetime(2017, 1, 1, 0, 0, 1, tzinfo=pytz.utc)
assert idctr.valid_from == dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=pytz.utc) assert idctr.valid_from == dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=pytz.utc)
assert idctr.indicator_types[0] == "malicious-activity"
assert idctr.pattern == "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']" assert idctr.pattern == "[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']"

View File

@ -13,10 +13,7 @@ EXPECTED_INFRASTRUCTURE = """{
"id": "infrastructure--3000ae1b-784c-f03d-8abc-0a625b2ff018", "id": "infrastructure--3000ae1b-784c-f03d-8abc-0a625b2ff018",
"created": "2017-01-01T12:34:56.000Z", "created": "2017-01-01T12:34:56.000Z",
"modified": "2017-01-01T12:34:56.000Z", "modified": "2017-01-01T12:34:56.000Z",
"name": "Poison Ivy C2", "name": "Poison Ivy C2"
"infrastructure_types": [
"command-and-control"
]
}""" }"""
@ -29,7 +26,6 @@ def test_infrastructure_with_all_required_properties():
created=now, created=now,
modified=now, modified=now,
name="Poison Ivy C2", name="Poison Ivy C2",
infrastructure_types=["command-and-control"],
) )
assert str(infra) == EXPECTED_INFRASTRUCTURE assert str(infra) == EXPECTED_INFRASTRUCTURE
@ -76,7 +72,7 @@ def test_infrastructure_required_properties():
stix2.v21.Infrastructure() stix2.v21.Infrastructure()
assert excinfo.value.cls == stix2.v21.Infrastructure assert excinfo.value.cls == stix2.v21.Infrastructure
assert excinfo.value.properties == ["infrastructure_types", "name"] assert excinfo.value.properties == ["name"]
def test_infrastructure_required_property_name(): def test_infrastructure_required_property_name():
@ -105,7 +101,6 @@ def test_invalid_kwarg_to_infrastructure():
"id": INFRASTRUCTURE_ID, "id": INFRASTRUCTURE_ID,
"created": "2017-01-01T12:34:56.000Z", "created": "2017-01-01T12:34:56.000Z",
"modified": "2017-01-01T12:34:56.000Z", "modified": "2017-01-01T12:34:56.000Z",
"infrastructure_types": ["command-and-control"],
"name": "Poison Ivy C2", "name": "Poison Ivy C2",
}, },
], ],
@ -118,7 +113,6 @@ def test_parse_infrastructure(data):
assert infra.id == INFRASTRUCTURE_ID assert infra.id == INFRASTRUCTURE_ID
assert infra.created == dt.datetime(2017, 1, 1, 12, 34, 56, tzinfo=pytz.utc) assert infra.created == dt.datetime(2017, 1, 1, 12, 34, 56, tzinfo=pytz.utc)
assert infra.modified == dt.datetime(2017, 1, 1, 12, 34, 56, tzinfo=pytz.utc) assert infra.modified == dt.datetime(2017, 1, 1, 12, 34, 56, tzinfo=pytz.utc)
assert infra.infrastructure_types == ['command-and-control']
assert infra.name == 'Poison Ivy C2' assert infra.name == 'Poison Ivy C2'

View File

@ -1,5 +1,5 @@
import datetime as dt import datetime as dt
import re import json
import pytest import pytest
import pytz import pytz
@ -16,9 +16,6 @@ EXPECTED_MALWARE = """{
"created": "2016-05-12T08:17:27.000Z", "created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z", "modified": "2016-05-12T08:17:27.000Z",
"name": "Cryptolocker", "name": "Cryptolocker",
"malware_types": [
"ransomware"
],
"is_family": false "is_family": false
}""" }"""
@ -31,7 +28,6 @@ def test_malware_with_all_required_properties():
id=MALWARE_ID, id=MALWARE_ID,
created=now, created=now,
modified=now, modified=now,
malware_types=["ransomware"],
name="Cryptolocker", name="Cryptolocker",
is_family=False, is_family=False,
) )
@ -80,7 +76,7 @@ def test_malware_required_properties():
stix2.v21.Malware() stix2.v21.Malware()
assert excinfo.value.cls == stix2.v21.Malware assert excinfo.value.cls == stix2.v21.Malware
assert excinfo.value.properties == ["is_family", "malware_types"] assert excinfo.value.properties == ["is_family"]
def test_malware_required_property_name(): def test_malware_required_property_name():
@ -116,7 +112,6 @@ def test_invalid_kwarg_to_malware():
"id": MALWARE_ID, "id": MALWARE_ID,
"created": "2016-05-12T08:17:27.000Z", "created": "2016-05-12T08:17:27.000Z",
"modified": "2016-05-12T08:17:27.000Z", "modified": "2016-05-12T08:17:27.000Z",
"malware_types": ["ransomware"],
"name": "Cryptolocker", "name": "Cryptolocker",
"is_family": False, "is_family": False,
}, },
@ -130,13 +125,14 @@ def test_parse_malware(data):
assert mal.id == MALWARE_ID assert mal.id == MALWARE_ID
assert mal.created == dt.datetime(2016, 5, 12, 8, 17, 27, tzinfo=pytz.utc) assert mal.created == dt.datetime(2016, 5, 12, 8, 17, 27, tzinfo=pytz.utc)
assert mal.modified == dt.datetime(2016, 5, 12, 8, 17, 27, tzinfo=pytz.utc) assert mal.modified == dt.datetime(2016, 5, 12, 8, 17, 27, tzinfo=pytz.utc)
assert mal.malware_types == ['ransomware']
assert mal.name == 'Cryptolocker' assert mal.name == 'Cryptolocker'
assert not mal.is_family assert not mal.is_family
def test_parse_malware_invalid_labels(): def test_parse_malware_invalid_types():
data = re.compile('\\[.+\\]', re.DOTALL).sub('1', EXPECTED_MALWARE) data = json.loads(EXPECTED_MALWARE)
data["malware_types"] = 1 # Oops, not a list
data = json.dumps(data)
with pytest.raises(InvalidValueError) as excinfo: with pytest.raises(InvalidValueError) as excinfo:
stix2.parse(data) stix2.parse(data)
assert "Invalid value for Malware 'malware_types'" in str(excinfo.value) assert "Invalid value for Malware 'malware_types'" in str(excinfo.value)
@ -197,3 +193,22 @@ def test_malware_non_family_no_name():
"is_family": False, "is_family": False,
"malware_types": ["something"], "malware_types": ["something"],
}) })
def test_malware_with_os_refs():
software = stix2.parse({
"type": "software",
"name": "SuperOS",
"spec_version": "2.1",
})
malware = stix2.parse({
"type": "malware",
"id": MALWARE_ID,
"spec_version": "2.1",
"is_family": False,
"malware_types": ["something"],
"operating_system_refs": [software],
})
assert malware["operating_system_refs"][0] == software["id"]

View File

@ -34,11 +34,13 @@ MALWARE_ANALYSIS_JSON = """{
"submitted": "2018-11-23T06:45:55.747Z", "submitted": "2018-11-23T06:45:55.747Z",
"analysis_started": "2018-11-29T07:30:03.895Z", "analysis_started": "2018-11-29T07:30:03.895Z",
"analysis_ended": "2018-11-29T08:30:03.895Z", "analysis_ended": "2018-11-29T08:30:03.895Z",
"av_result": "malicious", "result_name": "MegaRansom",
"result": "malicious",
"analysis_sco_refs": [ "analysis_sco_refs": [
"file--fc27e371-6c88-4c5c-868a-4dda0e60b167", "file--fc27e371-6c88-4c5c-868a-4dda0e60b167",
"url--6f7a74cd-8eb2-4b88-a4da-aa878e50ac2e" "url--6f7a74cd-8eb2-4b88-a4da-aa878e50ac2e"
] ],
"sample_ref": "email-addr--499a32d7-74c1-4276-ace9-725ac933e243"
}""" }"""

View File

@ -1300,6 +1300,7 @@ def test_software_example():
s = stix2.v21.Software( s = stix2.v21.Software(
name="Word", name="Word",
cpe="cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*", cpe="cpe:2.3:a:microsoft:word:2000:*:*:*:*:*:*:*",
swid="com.acme.rms-ce-v4-1-5-0",
version="2002", version="2002",
vendor="Microsoft", vendor="Microsoft",
) )

View File

@ -26,6 +26,7 @@ NOW = object()
STIX_UNMOD_PROPERTIES = ['created', 'created_by_ref', 'id', 'type'] STIX_UNMOD_PROPERTIES = ['created', 'created_by_ref', 'id', 'type']
TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$' TYPE_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-?$'
SCO21_EXT_REGEX = r'^\-?[a-z0-9]+(-[a-z0-9]+)*\-ext$'
class STIXdatetime(dt.datetime): class STIXdatetime(dt.datetime):

View File

@ -9,9 +9,8 @@ from ..properties import (
class Bundle(_STIXBase): class Bundle(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_nuwp4rox8c7r>`__.
""" """
_type = 'bundle' _type = 'bundle'

View File

@ -4,6 +4,7 @@ from collections import OrderedDict
from ..base import _STIXBase from ..base import _STIXBase
from ..custom import _custom_marking_builder from ..custom import _custom_marking_builder
from ..exceptions import InvalidValueError
from ..markings import _MarkingsMixin from ..markings import _MarkingsMixin
from ..markings.utils import check_tlp_marking from ..markings.utils import check_tlp_marking
from ..properties import ( from ..properties import (
@ -15,9 +16,8 @@ from ..utils import NOW, _get_dict
class ExternalReference(_STIXBase): class ExternalReference(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_bajcvqteiard>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -28,15 +28,30 @@ class ExternalReference(_STIXBase):
('external_id', StringProperty()), ('external_id', StringProperty()),
]) ])
# This is hash-algorithm-ov
_LEGAL_HASHES = {
"MD5", "SHA-1", "SHA-256", "SHA-512", "SHA3-256", "SHA3-512", "SSDEEP",
"TLSH",
}
def _check_object_constraints(self): def _check_object_constraints(self):
super(ExternalReference, self)._check_object_constraints() super(ExternalReference, self)._check_object_constraints()
self._check_at_least_one_property(['description', 'external_id', 'url']) self._check_at_least_one_property(['description', 'external_id', 'url'])
if "hashes" in self:
if any(
hash_ not in self._LEGAL_HASHES
for hash_ in self["hashes"]
):
raise InvalidValueError(
ExternalReference, "hashes",
"Hash algorithm names must be members of hash-algorithm-ov",
)
class KillChainPhase(_STIXBase): class KillChainPhase(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_i4tjv75ce50h>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -46,9 +61,8 @@ class KillChainPhase(_STIXBase):
class GranularMarking(_STIXBase): class GranularMarking(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_robezi5egfdr>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -63,9 +77,8 @@ class GranularMarking(_STIXBase):
class LanguageContent(_STIXBase): class LanguageContent(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_nfwr8z9ax2bi>`__.
""" """
_type = 'language-content' _type = 'language-content'
@ -91,9 +104,8 @@ class LanguageContent(_STIXBase):
class TLPMarking(_STIXBase): class TLPMarking(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_yd3ar14ekwrs>`__.
""" """
_type = 'tlp' _type = 'tlp'
@ -103,9 +115,8 @@ class TLPMarking(_STIXBase):
class StatementMarking(_STIXBase): class StatementMarking(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_3ru8r05saera>`__.
""" """
_type = 'statement' _type = 'statement'
@ -134,9 +145,8 @@ class MarkingProperty(Property):
class MarkingDefinition(_STIXBase, _MarkingsMixin): class MarkingDefinition(_STIXBase, _MarkingsMixin):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_hr5vgqxjk7ns>`__.
""" """
_type = 'marking-definition' _type = 'marking-definition'

View File

@ -22,9 +22,8 @@ from .common import GranularMarking
class Artifact(_Observable): class Artifact(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_rqwyxo6gp7cv>`__.
""" """
_type = 'artifact' _type = 'artifact'
@ -52,9 +51,8 @@ class Artifact(_Observable):
class AutonomousSystem(_Observable): class AutonomousSystem(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_bxebwa6l91fb>`__.
""" """
_type = 'autonomous-system' _type = 'autonomous-system'
@ -74,9 +72,8 @@ class AutonomousSystem(_Observable):
class Directory(_Observable): class Directory(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vhpkn06q7fvl>`__.
""" """
_type = 'directory' _type = 'directory'
@ -100,9 +97,8 @@ class Directory(_Observable):
class DomainName(_Observable): class DomainName(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_i2zf5h7vnrd9>`__.
""" """
_type = 'domain-name' _type = 'domain-name'
@ -121,9 +117,8 @@ class DomainName(_Observable):
class EmailAddress(_Observable): class EmailAddress(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_am7srelb9c14>`__.
""" """
_type = 'email-addr' _type = 'email-addr'
@ -143,9 +138,8 @@ class EmailAddress(_Observable):
class EmailMIMEComponent(_STIXBase): class EmailMIMEComponent(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_kzv52qqc0xw1>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -161,9 +155,8 @@ class EmailMIMEComponent(_STIXBase):
class EmailMessage(_Observable): class EmailMessage(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_loz634bn09om>`__.
""" """
_type = 'email-message' _type = 'email-message'
@ -202,9 +195,8 @@ class EmailMessage(_Observable):
class ArchiveExt(_Extension): class ArchiveExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_mm25z9wuw4tr>`__.
""" """
_type = 'archive-ext' _type = 'archive-ext'
@ -215,9 +207,8 @@ class ArchiveExt(_Extension):
class AlternateDataStream(_STIXBase): class AlternateDataStream(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_nbqgazg6fsma>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -228,9 +219,8 @@ class AlternateDataStream(_STIXBase):
class NTFSExt(_Extension): class NTFSExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_tb77nk1g3y6f>`__.
""" """
_type = 'ntfs-ext' _type = 'ntfs-ext'
@ -241,9 +231,8 @@ class NTFSExt(_Extension):
class PDFExt(_Extension): class PDFExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_30hzxqrmkg8w>`__.
""" """
_type = 'pdf-ext' _type = 'pdf-ext'
@ -257,9 +246,8 @@ class PDFExt(_Extension):
class RasterImageExt(_Extension): class RasterImageExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_20mnz0u5ppxr>`__.
""" """
_type = 'raster-image-ext' _type = 'raster-image-ext'
@ -272,9 +260,8 @@ class RasterImageExt(_Extension):
class WindowsPEOptionalHeaderType(_STIXBase): class WindowsPEOptionalHeaderType(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wyp5qdc2wugy>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -317,9 +304,8 @@ class WindowsPEOptionalHeaderType(_STIXBase):
class WindowsPESection(_STIXBase): class WindowsPESection(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wiqw87xsov3t>`__.
""" """
_properties = OrderedDict([ _properties = OrderedDict([
@ -331,9 +317,8 @@ class WindowsPESection(_STIXBase):
class WindowsPEBinaryExt(_Extension): class WindowsPEBinaryExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_5f9bgdmj91h5>`__.
""" """
_type = 'windows-pebinary-ext' _type = 'windows-pebinary-ext'
@ -354,9 +339,8 @@ class WindowsPEBinaryExt(_Extension):
class File(_Observable): class File(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vq03pryd7u32>`__.
""" """
_type = 'file' _type = 'file'
@ -382,7 +366,7 @@ class File(_Observable):
('granular_markings', ListProperty(GranularMarking)), ('granular_markings', ListProperty(GranularMarking)),
('defanged', BooleanProperty(default=lambda: False)), ('defanged', BooleanProperty(default=lambda: False)),
]) ])
_id_contributing_properties = ["hashes", "name", "extensions"] _id_contributing_properties = ["hashes", "name", "parent_directory_ref", "extensions"]
def _check_object_constraints(self): def _check_object_constraints(self):
super(File, self)._check_object_constraints() super(File, self)._check_object_constraints()
@ -390,9 +374,8 @@ class File(_Observable):
class IPv4Address(_Observable): class IPv4Address(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ta83c412bfsc>`__.
""" """
_type = 'ipv4-addr' _type = 'ipv4-addr'
@ -412,9 +395,8 @@ class IPv4Address(_Observable):
class IPv6Address(_Observable): class IPv6Address(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_f76hsv2pvwwq>`__.
""" """
_type = 'ipv6-addr' _type = 'ipv6-addr'
@ -434,9 +416,8 @@ class IPv6Address(_Observable):
class MACAddress(_Observable): class MACAddress(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6lhrrdef8852>`__.
""" """
_type = 'mac-addr' _type = 'mac-addr'
@ -454,9 +435,8 @@ class MACAddress(_Observable):
class Mutex(_Observable): class Mutex(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_u65ia5eoc7cv>`__.
""" """
_type = 'mutex' _type = 'mutex'
@ -474,9 +454,8 @@ class Mutex(_Observable):
class HTTPRequestExt(_Extension): class HTTPRequestExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_60k6dn28qicj>`__.
""" """
_type = 'http-request-ext' _type = 'http-request-ext'
@ -493,7 +472,7 @@ class HTTPRequestExt(_Extension):
class ICMPExt(_Extension): class ICMPExt(_Extension):
# TODO: Add link # TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_3g6wds21zwzl>`__.
""" """
_type = 'icmp-ext' _type = 'icmp-ext'
@ -504,9 +483,8 @@ class ICMPExt(_Extension):
class SocketExt(_Extension): class SocketExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_f54f1hripxsg>`__.
""" """
_type = 'socket-ext' _type = 'socket-ext'
@ -566,9 +544,8 @@ class SocketExt(_Extension):
class TCPExt(_Extension): class TCPExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_2z78x4m8ewcw>`__.
""" """
_type = 'tcp-ext' _type = 'tcp-ext'
@ -579,9 +556,8 @@ class TCPExt(_Extension):
class NetworkTraffic(_Observable): class NetworkTraffic(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_e5nyr5squmsd>`__.
""" """
_type = 'network-traffic' _type = 'network-traffic'
@ -635,9 +611,8 @@ class NetworkTraffic(_Observable):
class WindowsProcessExt(_Extension): class WindowsProcessExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_4wfs4ve800kf>`__.
""" """
_type = 'windows-process-ext' _type = 'windows-process-ext'
@ -660,9 +635,8 @@ class WindowsProcessExt(_Extension):
class WindowsServiceExt(_Extension): class WindowsServiceExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_s2rmoe7djlt>`__.
""" """
_type = 'windows-service-ext' _type = 'windows-service-ext'
@ -704,9 +678,8 @@ class WindowsServiceExt(_Extension):
class Process(_Observable): class Process(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ur7snm473t1d>`__.
""" """
_type = 'process' _type = 'process'
@ -749,9 +722,8 @@ class Process(_Observable):
class Software(_Observable): class Software(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_jru33yeokrmh>`__.
""" """
_type = 'software' _type = 'software'
@ -760,6 +732,7 @@ class Software(_Observable):
('id', IDProperty(_type, spec_version='2.1')), ('id', IDProperty(_type, spec_version='2.1')),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('cpe', StringProperty()), ('cpe', StringProperty()),
('swid', StringProperty()),
('languages', ListProperty(StringProperty)), ('languages', ListProperty(StringProperty)),
('vendor', StringProperty()), ('vendor', StringProperty()),
('version', StringProperty()), ('version', StringProperty()),
@ -769,13 +742,12 @@ class Software(_Observable):
('granular_markings', ListProperty(GranularMarking)), ('granular_markings', ListProperty(GranularMarking)),
('defanged', BooleanProperty(default=lambda: False)), ('defanged', BooleanProperty(default=lambda: False)),
]) ])
_id_contributing_properties = ["name", "cpe", "vendor", "version"] _id_contributing_properties = ["name", "cpe", "swid", "vendor", "version"]
class URL(_Observable): class URL(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6bsklda6vc0c>`__.
""" """
_type = 'url' _type = 'url'
@ -793,9 +765,8 @@ class URL(_Observable):
class UNIXAccountExt(_Extension): class UNIXAccountExt(_Extension):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_z25gmwyz67kl>`__.
""" """
_type = 'unix-account-ext' _type = 'unix-account-ext'
@ -808,9 +779,8 @@ class UNIXAccountExt(_Extension):
class UserAccount(_Observable): class UserAccount(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_hah33g4ntxnx>`__.
""" """
_type = 'user-account' _type = 'user-account'
@ -841,9 +811,8 @@ class UserAccount(_Observable):
class WindowsRegistryValueType(_STIXBase): class WindowsRegistryValueType(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_6jiqabgqp2hp>`__.
""" """
_type = 'windows-registry-value-type' _type = 'windows-registry-value-type'
@ -871,9 +840,8 @@ class WindowsRegistryValueType(_STIXBase):
class WindowsRegistryKey(_Observable): class WindowsRegistryKey(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_bdim4of4dl37>`__.
""" """
_type = 'windows-registry-key' _type = 'windows-registry-key'
@ -896,9 +864,8 @@ class WindowsRegistryKey(_Observable):
class X509V3ExtenstionsType(_STIXBase): class X509V3ExtenstionsType(_STIXBase):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_c1kt4dheb6vz>`__.
""" """
_type = 'x509-v3-extensions-type' _type = 'x509-v3-extensions-type'
@ -923,9 +890,8 @@ class X509V3ExtenstionsType(_STIXBase):
class X509Certificate(_Observable): class X509Certificate(_Observable):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_g3kniyun8ykv>`__.
""" """
_type = 'x509-certificate' _type = 'x509-certificate'

View File

@ -13,19 +13,17 @@ from ..exceptions import (
InvalidValueError, PropertyPresenceError, STIXDeprecationWarning, InvalidValueError, PropertyPresenceError, STIXDeprecationWarning,
) )
from ..properties import ( from ..properties import (
BinaryProperty, BooleanProperty, EmbeddedObjectProperty, EnumProperty, BooleanProperty, EnumProperty, FloatProperty, IDProperty, IntegerProperty,
FloatProperty, IDProperty, IntegerProperty, ListProperty, ListProperty, ObservableProperty, PatternProperty, ReferenceProperty,
ObservableProperty, PatternProperty, ReferenceProperty, StringProperty, StringProperty, TimestampProperty, TypeProperty,
TimestampProperty, TypeProperty,
) )
from ..utils import NOW from ..utils import NOW
from .common import ExternalReference, GranularMarking, KillChainPhase from .common import ExternalReference, GranularMarking, KillChainPhase
class AttackPattern(STIXDomainObject): class AttackPattern(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_4ohsa4pay4h4>`__.
""" """
_type = 'attack-pattern' _type = 'attack-pattern'
@ -51,9 +49,8 @@ class AttackPattern(STIXDomainObject):
class Campaign(STIXDomainObject): class Campaign(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_vvysvm8mt434>`__.
""" """
_type = 'campaign' _type = 'campaign'
@ -91,9 +88,8 @@ class Campaign(STIXDomainObject):
class CourseOfAction(STIXDomainObject): class CourseOfAction(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_d5yf99f0a230>`__.
""" """
_type = 'course-of-action' _type = 'course-of-action'
@ -106,10 +102,6 @@ class CourseOfAction(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('action_type', StringProperty()),
('os_execution_envs', ListProperty(StringProperty)),
('action_bin', BinaryProperty()),
('action_reference', EmbeddedObjectProperty(ExternalReference)),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
('labels', ListProperty(StringProperty)), ('labels', ListProperty(StringProperty)),
('confidence', IntegerProperty()), ('confidence', IntegerProperty()),
@ -119,19 +111,10 @@ class CourseOfAction(STIXDomainObject):
('granular_markings', ListProperty(GranularMarking)), ('granular_markings', ListProperty(GranularMarking)),
]) ])
def _check_object_constraints(self):
super(CourseOfAction, self)._check_object_constraints()
self._check_mutually_exclusive_properties(
["action_bin", "action_reference"],
at_least_one=False,
)
class Grouping(STIXDomainObject): class Grouping(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_9e3uldaqqha2>`__.
""" """
_type = 'grouping' _type = 'grouping'
@ -157,9 +140,8 @@ class Grouping(STIXDomainObject):
class Identity(STIXDomainObject): class Identity(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ru8fmldl2p6w>`__.
""" """
_type = 'identity' _type = 'identity'
@ -173,7 +155,7 @@ class Identity(STIXDomainObject):
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('roles', ListProperty(StringProperty)), ('roles', ListProperty(StringProperty)),
('identity_class', StringProperty(required=True)), ('identity_class', StringProperty()),
('sectors', ListProperty(StringProperty)), ('sectors', ListProperty(StringProperty)),
('contact_information', StringProperty()), ('contact_information', StringProperty()),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
@ -187,9 +169,8 @@ class Identity(STIXDomainObject):
class Indicator(STIXDomainObject): class Indicator(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_wfiae74706sw>`__.
""" """
_type = 'indicator' _type = 'indicator'
@ -202,7 +183,7 @@ class Indicator(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty()), ('name', StringProperty()),
('description', StringProperty()), ('description', StringProperty()),
('indicator_types', ListProperty(StringProperty, required=True)), ('indicator_types', ListProperty(StringProperty)),
('pattern', PatternProperty(required=True)), ('pattern', PatternProperty(required=True)),
('pattern_type', StringProperty(required=True)), ('pattern_type', StringProperty(required=True)),
('pattern_version', StringProperty()), ('pattern_version', StringProperty()),
@ -247,9 +228,8 @@ class Indicator(STIXDomainObject):
class Infrastructure(STIXDomainObject): class Infrastructure(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_l2alfbbcmfep>`__.
""" """
_type = 'infrastructure' _type = 'infrastructure'
@ -269,7 +249,7 @@ class Infrastructure(STIXDomainObject):
('granular_markings', ListProperty(GranularMarking)), ('granular_markings', ListProperty(GranularMarking)),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('infrastructure_types', ListProperty(StringProperty, required=True)), ('infrastructure_types', ListProperty(StringProperty)),
('aliases', ListProperty(StringProperty)), ('aliases', ListProperty(StringProperty)),
('kill_chain_phases', ListProperty(KillChainPhase)), ('kill_chain_phases', ListProperty(KillChainPhase)),
('first_seen', TimestampProperty()), ('first_seen', TimestampProperty()),
@ -288,9 +268,8 @@ class Infrastructure(STIXDomainObject):
class IntrusionSet(STIXDomainObject): class IntrusionSet(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ticprjb32bc4>`__.
""" """
_type = 'intrusion-set' _type = 'intrusion-set'
@ -331,9 +310,8 @@ class IntrusionSet(STIXDomainObject):
class Location(STIXDomainObject): class Location(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_sqez6sri9vtz>`__.
""" """
_type = 'location' _type = 'location'
@ -439,9 +417,8 @@ class Location(STIXDomainObject):
class Malware(STIXDomainObject): class Malware(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_gc4ooz6oaz7y>`__.
""" """
_type = 'malware' _type = 'malware'
@ -454,13 +431,13 @@ class Malware(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty()), ('name', StringProperty()),
('description', StringProperty()), ('description', StringProperty()),
('malware_types', ListProperty(StringProperty, required=True)), ('malware_types', ListProperty(StringProperty)),
('is_family', BooleanProperty(required=True)), ('is_family', BooleanProperty(required=True)),
('aliases', ListProperty(StringProperty)), ('aliases', ListProperty(StringProperty)),
('kill_chain_phases', ListProperty(KillChainPhase)), ('kill_chain_phases', ListProperty(KillChainPhase)),
('first_seen', TimestampProperty()), ('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()), ('last_seen', TimestampProperty()),
('os_execution_envs', ListProperty(StringProperty)), ('operating_system_refs', ListProperty(ReferenceProperty(valid_types='software', spec_version='2.1'))),
('architecture_execution_envs', ListProperty(StringProperty)), ('architecture_execution_envs', ListProperty(StringProperty)),
('implementation_languages', ListProperty(StringProperty)), ('implementation_languages', ListProperty(StringProperty)),
('capabilities', ListProperty(StringProperty)), ('capabilities', ListProperty(StringProperty)),
@ -492,9 +469,8 @@ class Malware(STIXDomainObject):
class MalwareAnalysis(STIXDomainObject): class MalwareAnalysis(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_dw67pa20zss5>`__.
""" """
_type = 'malware-analysis' _type = 'malware-analysis'
@ -524,20 +500,21 @@ class MalwareAnalysis(STIXDomainObject):
('submitted', TimestampProperty()), ('submitted', TimestampProperty()),
('analysis_started', TimestampProperty()), ('analysis_started', TimestampProperty()),
('analysis_ended', TimestampProperty()), ('analysis_ended', TimestampProperty()),
('av_result', StringProperty()), ('result_name', StringProperty()),
('result', StringProperty()),
('analysis_sco_refs', ListProperty(ReferenceProperty(valid_types="SCO", spec_version='2.1'))), ('analysis_sco_refs', ListProperty(ReferenceProperty(valid_types="SCO", spec_version='2.1'))),
('sample_ref', ReferenceProperty(valid_types="SCO", spec_version="2.1")),
]) ])
def _check_object_constraints(self): def _check_object_constraints(self):
super(MalwareAnalysis, self)._check_object_constraints() super(MalwareAnalysis, self)._check_object_constraints()
self._check_at_least_one_property(["av_result", "analysis_sco_refs"]) self._check_at_least_one_property(["result", "analysis_sco_refs"])
class Note(STIXDomainObject): class Note(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_hr77jvcbs9jk>`__.
""" """
_type = 'note' _type = 'note'
@ -563,9 +540,8 @@ class Note(STIXDomainObject):
class ObservedData(STIXDomainObject): class ObservedData(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_h1590esrzg5f>`__.
""" """
_type = 'observed-data' _type = 'observed-data'
@ -619,9 +595,8 @@ class ObservedData(STIXDomainObject):
class Opinion(STIXDomainObject): class Opinion(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_sr2hswmu5t1>`__.
""" """
_type = 'opinion' _type = 'opinion'
@ -657,9 +632,8 @@ class Opinion(STIXDomainObject):
class Report(STIXDomainObject): class Report(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_ha4fpad0r9pf>`__.
""" """
_type = 'report' _type = 'report'
@ -672,7 +646,7 @@ class Report(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('report_types', ListProperty(StringProperty, required=True)), ('report_types', ListProperty(StringProperty)),
('published', TimestampProperty(required=True)), ('published', TimestampProperty(required=True)),
('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SDO", "SRO"], spec_version='2.1'), required=True)), ('object_refs', ListProperty(ReferenceProperty(valid_types=["SCO", "SDO", "SRO"], spec_version='2.1'), required=True)),
('revoked', BooleanProperty(default=lambda: False)), ('revoked', BooleanProperty(default=lambda: False)),
@ -691,9 +665,8 @@ class Report(STIXDomainObject):
class ThreatActor(STIXDomainObject): class ThreatActor(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_2wowmlcbkqst>`__.
""" """
_type = 'threat-actor' _type = 'threat-actor'
@ -706,7 +679,7 @@ class ThreatActor(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('threat_actor_types', ListProperty(StringProperty, required=True)), ('threat_actor_types', ListProperty(StringProperty)),
('aliases', ListProperty(StringProperty)), ('aliases', ListProperty(StringProperty)),
('first_seen', TimestampProperty()), ('first_seen', TimestampProperty()),
('last_seen', TimestampProperty()), ('last_seen', TimestampProperty()),
@ -738,9 +711,8 @@ class ThreatActor(STIXDomainObject):
class Tool(STIXDomainObject): class Tool(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_m21z3a1f3lou>`__.
""" """
_type = 'tool' _type = 'tool'
@ -753,7 +725,7 @@ class Tool(STIXDomainObject):
('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')),
('name', StringProperty(required=True)), ('name', StringProperty(required=True)),
('description', StringProperty()), ('description', StringProperty()),
('tool_types', ListProperty(StringProperty, required=True)), ('tool_types', ListProperty(StringProperty)),
('aliases', ListProperty(StringProperty)), ('aliases', ListProperty(StringProperty)),
('kill_chain_phases', ListProperty(KillChainPhase)), ('kill_chain_phases', ListProperty(KillChainPhase)),
('tool_version', StringProperty()), ('tool_version', StringProperty()),
@ -768,9 +740,8 @@ class Tool(STIXDomainObject):
class Vulnerability(STIXDomainObject): class Vulnerability(STIXDomainObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_d9f0iay06wtx>`__.
""" """
_type = 'vulnerability' _type = 'vulnerability'

View File

@ -12,9 +12,8 @@ from .common import ExternalReference, GranularMarking
class Relationship(STIXRelationshipObject): class Relationship(STIXRelationshipObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_al0fb8fcd9e7>`__.
""" """
_invalid_source_target_types = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting'] _invalid_source_target_types = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting']
@ -72,9 +71,8 @@ class Relationship(STIXRelationshipObject):
class Sighting(STIXRelationshipObject): class Sighting(STIXRelationshipObject):
# TODO: Add link
"""For more detailed information on this object's properties, see """For more detailed information on this object's properties, see
`the STIX 2.1 specification <link here>`__. `the STIX 2.1 specification <https://docs.oasis-open.org/cti/stix/v2.1/cs01/stix-v2.1-cs01.html#_7p0n81ikux8f>`__.
""" """
_type = 'sighting' _type = 'sighting'