If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly. Please view the post on signalscorps.com for the full interactive viewing experience.
In this post I will talk about customising STIX Objects when the predefined specification does not meet the needs of a data creators.
Note: this post is written for OASIS STIX version 2.1. The concepts discussed are not always correct for earlier versions of OASIS STIX.
The STIX 2.1 Specification covers many of the most common cyber threat intelligence concepts.
However, sometimes there are times where the STIX 2.1 will not be broad enough for your needs. This is typically the case for data producers.
There are two ways to customise STIX 2.1:
- Extensions: allow you to define new STIX Objects and Properties by creating an Extension Definition that defines a schema for them
- Legacy Custom Properties / Objects: deprecated in the current specification, but shown in this tutorial because a lot of producers are still using this approach to define custom properties (e.g. MITRE ATT&CK).
Breaking each one of these options into detail…
1. STIX Extensions
Custom Objects and Properties can be declared using a custom extension, defined by an Extension Definition.
There are three ways to extend STIX using STIX Extensions.
- Define one or more new STIX Object types.
- Define additional properties for an existing STIX Object type as a nested property extension. This is typically done to represent a sub-component or module of one or more STIX Object types.
- Define additional properties for an existing STIX Object type at the object’s top-level. This can be done to represent properties that form an inherent part of the definition of an object type.
1.1. Custom Objects defined using an Extension Definition
Whilst STIX 2.1 has a broad range of Objects, there are times when an existing one does not quite meet need existing needs.
You can define the new Object using an Extension Defintion Object, using the extension_types
property new-sdo
, like so;
{
"id": "extension-definition--9c59fd79-4215-4ba2-920d-3e4f320e1e62",
"type": "extension-definition",
"spec_version": "2.1",
"name": "New SDO 1",
"description": "This schema creates a new object type called my-favorite-sdo-1",
"created": "2014-02-20T09:16:08.989000Z",
"modified": "2014-02-20T09:16:08.989000Z",
"created_by_ref": "identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
"schema": "https://www.example.com/schema-my-favorite-sdo-1/v1/",
"version": "1.2.1",
"extension_types": [ "new-sdo" ]
}
The schema
property should link to a schema that defines the properties for the Object. The OASIS core STIX 2.1 schemas will help you to do this (I use them as templates when creating new objects).
In the case of new Objects, the extension_types
can be either new-sdo
for SDOs, new-sco
for SCOs, or new-sro
for SROs.
Once defined in an Extension Definition, you can then create new objects, making sure to reference the Extension Definition Object in the new Objects extensions
property along with the extension_type
(in this case a new SDO);
{
"type": "my-favorite-sdo",
"spec_version": "2.1",
"id": "my-favorite-sdo--ac97aae4-83f1-46ca-a351-7aeb76678189",
"created": "2014-02-20T09:16:08.989000Z",
"modified": "2014-02-20T09:16:08.989000Z",
"name": "This is the name of my favorite",
"some_property_name1": "value1",
"some_property_name2": "value2",
"extensions": {
"extension-definition--9c59fd79-4215-4ba2-920d-3e4f320e1e62" : {
"extension_type" : "new-sdo"
}
}
}
1.2. Custom Properties defined using an Extension Definition
Custom properties using Extension Definitions are defined in a very similar to creating new Objects, the only difference being the extension_type
will equal either property-extension
or toplevel-property-extension
.
Generally I strongly recommend using property-extension
s as these are better understood by downstream tools.
To compare the two, here is a property-extension
{
"id": "extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e",
"type": "extension-definition",
"spec_version": "2.1",
"name": "Extension Foo 1",
"description": "This schema adds two properties to a STIX object",
"created": "2014-02-20T09:16:08.989000Z",
"modified": "2014-02-20T09:16:08.989000Z",
"created_by_ref": "identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
"schema": "https://www.example.com/schema-foo-1/v1/",
"version": "1.2.1",
"extension_types": [ "property-extension" ]
},
{
"type": "indicator",
"spec_version": "2.1",
"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"
],
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"pattern_type": "stix",
"valid_from": "2014-02-20T09:00:00.000000Z",
"extensions": {
"extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e" : {
"extension_type": "property-extension",
"rank": 5,
"toxicity": 8
}
}
}
As you can see the custom properties rank
and toxicity
are nested inside the extension definition (extension-definition--d83fce45-ef58-4c6c-a3f4-1fbc32e98c6e
)property.
Compared to a toplevel-property-extension
;
{
"id": "extension-definition--71736db5-10db-43d3-b0e3-65cf81601fe1",
"type": "extension-definition",
"spec_version": "2.1",
"name": "Extension Foo 1a",
"description": "This schema adds two properties to a STIX object at the toplevel",
"created": "2014-02-20T09:16:08.989000Z",
"modified": "2014-02-20T09:16:08.989000Z",
"created_by_ref": "identity--11b76a96-5d2b-45e0-8a5a-f6994f370731",
"schema": "https://www.example.com/schema-foo-1a/v1/",
"version": "1.2.1",
"extension_types": [ "toplevel-property-extension" ],
"extension_properties" : [
"toxicity",
"rank"
]
},
{
"type": "indicator",
"spec_version": "2.1",
"id": "indicator--66a63e16-92d7-4b2f-bd3d-21540d6b3fc7",
"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"
],
"pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",
"pattern_type": "stix",
"valid_from": "2014-02-20T09:00:00.000000Z",
"rank": 1,
"toxicity": 2,
"extensions": {
"extension-definition--71736db5-10db-43d3-b0e3-65cf81601fe1" : {
"extension_type": "toplevel-property-extension"
}
}
}
As you can see, the key difference being the custom properties in the toplevel-property-extension
(rank
and toxicity
) exist at the top level of the object. Many consuming products will throw errors in such a scenario as they won’t consider the Extension Definition and only consider the Indicator SRO pure STIX 2.1 properties.
Having them nested inside an extension definition in the property-extension
is much more widely supported in downstream tools as they don’t conflict with the pure STIX 2.1 Indicator properties.
1.3 A real world example of Extension Definitions
Here at Signals Corps I use extension defintions to define a wide range of custom objects (e.g. custom Bank Card SCO).
You can see all of our extension definitions here.
2. Legacy custom Objects / Properties
2.1 Legacy Custom Objects
Legacy custom Objects can be created by specifying a type
Property value prefixed with x-
(e.g. "type": "x-my-custom-object"
).
MITRE ATT&CK is a good example of STIX 2.1 Custom Objects. To represent MITRE ATT&CK Tactics, MITRE use a custom Tactic Object (x-mitre-tactic--
).
ATT&CK also uses Custom Objects for x-mitre-data-component
, x-mitre-data-source
, and x-mitre-matrix
.
Custom Objects can contain both Common Properties, Unique Object Properties defined in the STIX 2.1 specification, or Custom Properties (ultimately the producer defines the specification of their Custom Object).
Custom Objects make no distinction between SDO, SCO, or SRO. The producer defines the type
value of the Custom Object and it can be used for any of these three cases (or something else entirely, if need be).
2.2 Legacy Custom Properties
Custom Properties have historically been the most common way producers extend STIX 2.1 Objects because they are very useful for specific information relating to their service or processes, for example, internal references.
Custom Properties in a STIX 2.1 predefined Object or a Custom Object can be declared using the prefix x_
(e.g "x_custom_property": "value"
).
Here is an example of a Custom Property (x_phising_score
) in an Attack Pattern Object;
2.3 A real world example of Legacy Custom Objects / Properties
MITRE’s representation of ATT&CK is a good example of the need for customisation.
MITRE use both Custom Objects and Custom Properties for ATT&CK.
The Matrix view you often see rendering ATT&CK Tactics and Techniques is defined by a custom x-mitre-matrix
SDO.
Inside each Mitre ATT&CK SDO, you will see Custom Properties MITRE uses for their own references (prefixed with x_mitre_
).
See the Custom Property in the Attack Pattern SDO for the Technique T1047: Windows Management Instrumentation including; x_mitre_platforms
and x_mitre_domains
, to name just two examples.
Versioning changes to your Objects
Now you are confident enough to start creating new STIX 2.1 Objects, it is important you know how to update them when needed.
In my next post I will share when and how to version changes to your Objects.
STIX 2.1 Certification (Virtual and In Person)
The content used in this post is a small subset of our full training material used in our STIX 2.1 training.
If you want to join a select group of certified STIX 2.1 professionals, subscribe to our newsletter below to be notified of new course dates.
Discuss this post

Never miss an update
Sign up to receive new articles in your inbox as they published.