STIX Extensions¶
This page is specific for the STIX Extensions mechanism defined in STIX 2.1 CS 02. For the deprecated STIX Customization mechanisms see the Custom section.
Top Level Property Extensions¶
The example below shows how to create an indicator
object with a top-level-property-extension
.
[3]:
import stix2
extension_definition1 = stix2.v21.ExtensionDefinition(
id="extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8",
created_by_ref="identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
created="2014-02-20T09:16:08.000Z",
modified="2014-02-20T09:16:08.000Z",
name="New SDO 1",
description="This schema adds two properties to a STIX object at the toplevel",
schema="https://www.example.com/schema-foo-1a/v1/",
version="1.2.1",
extension_types=["toplevel-property-extension"],
extension_properties=[
"toxicity",
"rank",
],
)
indicator = stix2.v21.Indicator(
id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
created='2014-02-20T09:16:08.989000Z',
modified='2014-02-20T09:16:08.989000Z',
name='File hash for Poison Ivy variant',
description='This file hash indicates that a sample of Poison Ivy is present.',
labels=[
'malicious-activity',
],
rank=5,
toxicity=8,
pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z',
extensions={
extension_definition1.id : {
'extension_type': 'toplevel-property-extension',
},
}
)
print(extension_definition1.serialize(pretty=True))
print(indicator.serialize(pretty=True))
[3]:
{
"type": "extension-definition",
"spec_version": "2.1",
"id": "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8",
"created_by_ref": "identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
"created": "2014-02-20T09:16:08.000Z",
"modified": "2014-02-20T09:16:08.000Z",
"name": "New SDO 1",
"description": "This schema adds two properties to a STIX object at the toplevel",
"schema": "https://www.example.com/schema-foo-1a/v1/",
"version": "1.2.1",
"extension_types": [
"toplevel-property-extension"
],
"extension_properties": [
"toxicity",
"rank"
]
}
[3]:
{
"type": "indicator",
"spec_version": "2.1",
"id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",
"created": "2014-02-20T09:16:08.989Z",
"modified": "2014-02-20T09:16:08.989Z",
"name": "File hash for Poison Ivy variant",
"description": "This file hash indicates that a sample of Poison Ivy is present.",
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"pattern_type": "stix",
"pattern_version": "2.1",
"valid_from": "2014-02-20T09:00:00Z",
"labels": [
"malicious-activity"
],
"extensions": {
"extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {
"extension_type": "toplevel-property-extension"
}
},
"rank": 5,
"toxicity": 8
}
Using CustomExtension decorator¶
However, in order to prevent repetitive instantiation of the same extension, the @CustomExtension
decorator can be used to register the extension-definition
with stix2. Use the extension_type
class variable to define what kind of extension it is. Then its id can be passed into objects that use this extension.
[4]:
TOPLEVEL_EXTENSION_DEFINITION_ID = 'extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8'
@stix2.v21.CustomExtension(
TOPLEVEL_EXTENSION_DEFINITION_ID, [
('rank', stix2.properties.IntegerProperty(required=True)),
('toxicity', stix2.properties.IntegerProperty(required=True)),
],
)
class ExtensionTopLevel:
extension_type = 'toplevel-property-extension'
indicator = stix2.v21.Indicator(
id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
created='2014-02-20T09:16:08.989000Z',
modified='2014-02-20T09:16:08.989000Z',
name='File hash for Poison Ivy variant',
description='This file hash indicates that a sample of Poison Ivy is present.',
labels=[
'malicious-activity',
],
rank=5,
toxicity=8,
pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
pattern_type='stix',
valid_from='2014-02-20T09:00:00.000000Z',
extensions={
TOPLEVEL_EXTENSION_DEFINITION_ID : {
'extension_type': 'toplevel-property-extension',
},
}
)
print(indicator.serialize(pretty=True))
[4]:
{
"type": "indicator",
"spec_version": "2.1",
"id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",
"created": "2014-02-20T09:16:08.989Z",
"modified": "2014-02-20T09:16:08.989Z",
"name": "File hash for Poison Ivy variant",
"description": "This file hash indicates that a sample of Poison Ivy is present.",
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"pattern_type": "stix",
"pattern_version": "2.1",
"valid_from": "2014-02-20T09:00:00Z",
"labels": [
"malicious-activity"
],
"extensions": {
"extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {
"extension_type": "toplevel-property-extension"
}
},
"rank": 5,
"toxicity": 8
}
Using CustomObservable for Extension Definition¶
Similarly, when registering new objects via @CustomObservable
you can pass the extension-definition
id that defines this new SCO.
[3]:
@stix2.v21.CustomObservable(
'my-favorite-sco', [
('name', stix2.properties.StringProperty(required=True)),
('some_network_protocol_field', stix2.properties.StringProperty(required=True)),
], ['name', 'some_network_protocol_field'], 'extension-definition--150c1738-28c9-44d0-802d-70523218240b',
)
class MyFavSCO:
pass
my_favorite_sco = MyFavSCO(
id='my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874',
name='This is the name of my favorite SCO',
some_network_protocol_field='value',
)
print(my_favorite_sco.serialize(pretty=True))
[3]:
{
"type": "my-favorite-sco",
"spec_version": "2.1",
"id": "my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874",
"name": "This is the name of my favorite SCO",
"some_network_protocol_field": "value",
"extensions": {
"extension-definition--150c1738-28c9-44d0-802d-70523218240b": {
"extension_type": "new-sco"
}
}
}
Using CustomMarking for Extension Definition¶
The example below shows the use for MarkingDefinition extensions. Currently this is only supported as a property-extension
. Now, as another option to building the extensions
as a dictionary, it can also be built with objects as shown below by extracting the registered class.
[4]:
from stix2 import registry
MARKING_EXTENSION_ID = 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'
@stix2.v21.CustomMarking(
'my-favorite-marking', [
('some_marking_field', stix2.properties.StringProperty(required=True)),
], MARKING_EXTENSION_ID,
)
class MyFavMarking:
pass
ext_class = registry.class_for_type(MARKING_EXTENSION_ID, '2.1')
my_favorite_marking = MyFavMarking(
name='This is the name of my favorite Marking',
extensions={
MARKING_EXTENSION_ID: ext_class(some_marking_field='value')
}
)
print(my_favorite_marking.serialize(pretty=True))
[4]:
{
"type": "marking-definition",
"spec_version": "2.1",
"id": "marking-definition--28417f9f-1963-4e7f-914d-233f8fd4829f",
"created": "2021-03-31T21:54:46.652069Z",
"name": "This is the name of my favorite Marking",
"extensions": {
"extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff": {
"extension_type": "property-extension"
}
}
}
Using CustomObject for Extension Definition¶
Similar to the examples above, the same can be done for SDOs and SROs.
[4]:
invalid_refs = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting', 'foobar']
@stix2.v21.CustomObject(
'my-favorite-sro', [
('name', stix2.properties.StringProperty(required=False)),
('some_source_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
('some_target_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
], extension_name='extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce', is_sdo=False,
)
class MyFavSRO:
pass
my_favorite_sro = MyFavSRO(
name="My First SRO",
some_source_ref="identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",
some_target_ref="identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",
)
print(my_favorite_sro.serialize(pretty=True))
[4]:
{
"type": "my-favorite-sro",
"spec_version": "2.1",
"id": "my-favorite-sro--d6306d62-c08d-4d78-baf7-11e7a4c9bc36",
"created": "2021-03-31T22:43:42.807698Z",
"modified": "2021-03-31T22:43:42.807698Z",
"name": "My First SRO",
"some_source_ref": "identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",
"some_target_ref": "identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",
"extensions": {
"extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce": {
"extension_type": "new-sro"
}
}
}