{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "# Delete this cell to re-enable tracebacks\n", "import sys\n", "ipython = get_ipython()\n", "\n", "def hide_traceback(exc_tuple=None, filename=None, tb_offset=None,\n", " exception_only=False, running_compiled_code=False):\n", " etype, value, tb = sys.exc_info()\n", " value.__cause__ = None # suppress chained exceptions\n", " return ipython._showtraceback(etype, value, ipython.InteractiveTB.get_exception_only(etype, value))\n", "\n", "ipython.showtraceback = hide_traceback" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "# JSON output syntax highlighting\n", "from __future__ import print_function\n", "from pygments import highlight\n", "from pygments.lexers import JsonLexer, TextLexer\n", "from pygments.formatters import HtmlFormatter\n", "from IPython.display import display, HTML\n", "from IPython.core.interactiveshell import InteractiveShell\n", "\n", "InteractiveShell.ast_node_interactivity = \"all\"\n", "\n", "def json_print(inpt):\n", " string = str(inpt)\n", " formatter = HtmlFormatter()\n", " if string[0] == '{':\n", " lexer = JsonLexer()\n", " else:\n", " lexer = TextLexer()\n", " return HTML('{}'.format(\n", " formatter.get_style_defs('.highlight'),\n", " highlight(string, lexer, formatter)))\n", "\n", "globals()['print'] = json_print" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## STIX Extensions\n", "\n", "This page is specific for the STIX Extensions mechanism defined in STIX 2.1 CS 03. For the deprecated STIX Customization mechanisms see the [Custom](custom.ipynb) section.\n", "\n", "### Top Level Property Extensions\n", "\n", "The example below shows how to create an `indicator` object with a `toplevel-property-extension`. Because an unregistered toplevel property extension is present, any unrecognized toplevel properties are assumed to be extension properties. So the library lets them pass. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
{\n",
       "    "type": "indicator",\n",
       "    "spec_version": "2.1",\n",
       "    "id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",\n",
       "    "created": "2014-02-20T09:16:08.989Z",\n",
       "    "modified": "2014-02-20T09:16:08.989Z",\n",
       "    "name": "File hash for Poison Ivy variant",\n",
       "    "description": "This file hash indicates that a sample of Poison Ivy is present.",\n",
       "    "pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",\n",
       "    "pattern_type": "stix",\n",
       "    "pattern_version": "2.1",\n",
       "    "valid_from": "2014-02-20T09:00:00Z",\n",
       "    "labels": [\n",
       "        "malicious-activity"\n",
       "    ],\n",
       "    "extensions": {\n",
       "        "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {\n",
       "            "extension_type": "toplevel-property-extension"\n",
       "        }\n",
       "    },\n",
       "    "rank": 5,\n",
       "    "toxicity": 8\n",
       "}\n",
       "
\n" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import stix2\n", "\n", "indicator = stix2.v21.Indicator(\n", " id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',\n", " created='2014-02-20T09:16:08.989000Z',\n", " modified='2014-02-20T09:16:08.989000Z',\n", " name='File hash for Poison Ivy variant',\n", " description='This file hash indicates that a sample of Poison Ivy is present.',\n", " labels=[\n", " 'malicious-activity',\n", " ],\n", " rank=5,\n", " toxicity=8,\n", " pattern='[file:hashes.\\'SHA-256\\' = \\'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\\']',\n", " pattern_type='stix',\n", " valid_from='2014-02-20T09:00:00.000000Z',\n", " extensions={\n", " \"extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8\" : {\n", " 'extension_type': 'toplevel-property-extension',\n", " },\n", " }\n", ")\n", "\n", "print(indicator.serialize(pretty=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using CustomExtension decorator\n", "\n", "However, in order to define which properties are actually included with an extension, the `@CustomExtension` decorator can be used to register an extension type and its properties 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." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
{\n",
       "    "type": "indicator",\n",
       "    "spec_version": "2.1",\n",
       "    "id": "indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c",\n",
       "    "created": "2014-02-20T09:16:08.989Z",\n",
       "    "modified": "2014-02-20T09:16:08.989Z",\n",
       "    "name": "File hash for Poison Ivy variant",\n",
       "    "description": "This file hash indicates that a sample of Poison Ivy is present.",\n",
       "    "pattern": "[file:hashes.'SHA-256' = 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c']",\n",
       "    "pattern_type": "stix",\n",
       "    "pattern_version": "2.1",\n",
       "    "valid_from": "2014-02-20T09:00:00Z",\n",
       "    "labels": [\n",
       "        "malicious-activity"\n",
       "    ],\n",
       "    "extensions": {\n",
       "        "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8": {\n",
       "            "extension_type": "toplevel-property-extension"\n",
       "        }\n",
       "    },\n",
       "    "rank": 5,\n",
       "    "toxicity": 8\n",
       "}\n",
       "
\n" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TOPLEVEL_EXTENSION_DEFINITION_ID = 'extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8'\n", "\n", "@stix2.v21.CustomExtension(\n", " TOPLEVEL_EXTENSION_DEFINITION_ID, [\n", " ('rank', stix2.properties.IntegerProperty(required=True)),\n", " ('toxicity', stix2.properties.IntegerProperty(required=True)),\n", " ],\n", ")\n", "class ExtensionTopLevel:\n", " extension_type = 'toplevel-property-extension'\n", "\n", "indicator = stix2.v21.Indicator(\n", " id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',\n", " created='2014-02-20T09:16:08.989000Z',\n", " modified='2014-02-20T09:16:08.989000Z',\n", " name='File hash for Poison Ivy variant',\n", " description='This file hash indicates that a sample of Poison Ivy is present.',\n", " labels=[\n", " 'malicious-activity',\n", " ],\n", " rank=5,\n", " toxicity=8,\n", " pattern='[file:hashes.\\'SHA-256\\' = \\'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\\']',\n", " pattern_type='stix',\n", " valid_from='2014-02-20T09:00:00.000000Z',\n", " extensions={\n", " TOPLEVEL_EXTENSION_DEFINITION_ID : {\n", " 'extension_type': 'toplevel-property-extension',\n", " },\n", " }\n", ")\n", "\n", "print(indicator.serialize(pretty=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using CustomObservable for Extension Definition\n", "\n", "Similarly, when registering new objects via `@CustomObservable` you can pass the `extension-definition` id that defines this new SCO. \n", "\n", "---\n", "**Note:**\n", "Creating an instance of an extension object **does not** mean it is registered in the library. Please use the appropriate decorator for this step: `@CustomExtension`, `@CustomObject`, `@CustomObservable`, `@CustomMarking`\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
{\n",
       "    "type": "my-favorite-sco",\n",
       "    "spec_version": "2.1",\n",
       "    "id": "my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874",\n",
       "    "name": "This is the name of my favorite SCO",\n",
       "    "some_network_protocol_field": "value",\n",
       "    "extensions": {\n",
       "        "extension-definition--150c1738-28c9-44d0-802d-70523218240b": {\n",
       "            "extension_type": "new-sco"\n",
       "        }\n",
       "    }\n",
       "}\n",
       "
\n" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "@stix2.v21.CustomObservable(\n", " 'my-favorite-sco', [\n", " ('name', stix2.properties.StringProperty(required=True)),\n", " ('some_network_protocol_field', stix2.properties.StringProperty(required=True)),\n", " ], ['name', 'some_network_protocol_field'], 'extension-definition--150c1738-28c9-44d0-802d-70523218240b',\n", ")\n", "class MyFavSCO:\n", " pass\n", "\n", "my_favorite_sco = MyFavSCO(\n", " id='my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874',\n", " name='This is the name of my favorite SCO',\n", " some_network_protocol_field='value',\n", ")\n", "\n", "print(my_favorite_sco.serialize(pretty=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Custom Markings\n", "\n", "The example below show how to create a user-defined marking based on an extension. The STIX `marking-definition` object is essentially a base upon which you build the particulars of your marking, via an extension. This is done in the same way as any other extension. Marking definitions are no different in this regard. The below example illustrates an alternative to building the extension entirely as a dictionary: it can also be built by instantiating the registered class." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
{\n",
       "    "type": "marking-definition",\n",
       "    "spec_version": "2.1",\n",
       "    "id": "marking-definition--9155f07c-dd4c-4320-be6a-0701311c3b84",\n",
       "    "created": "2021-07-12T00:56:31.47566Z",\n",
       "    "name": "This is the name of my favorite Marking",\n",
       "    "extensions": {\n",
       "        "extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff": {\n",
       "            "extension_type": "property-extension",\n",
       "            "some_marking_field": "value"\n",
       "        }\n",
       "    }\n",
       "}\n",
       "
\n" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import stix2\n", "import stix2.properties\n", "\n", "MARKING_EXTENSION_ID = 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'\n", "\n", "@stix2.CustomExtension(MARKING_EXTENSION_ID, [\n", " ('some_marking_field', stix2.properties.StringProperty(required=True))\n", "])\n", "class MyFavMarking:\n", " extension_type = 'property-extension'\n", "\n", "my_favorite_marking = stix2.MarkingDefinition(\n", " name='This is the name of my favorite Marking',\n", " extensions={\n", " MARKING_EXTENSION_ID: MyFavMarking(\n", " some_marking_field='value'\n", " )\n", " }\n", ")\n", "\n", "print(my_favorite_marking.serialize(pretty=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using CustomObject for Extension Definition\n", "\n", "Similar to the examples above, the same can be done for SDOs and SROs." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
{\n",
       "    "type": "my-favorite-sro",\n",
       "    "spec_version": "2.1",\n",
       "    "id": "my-favorite-sro--d6306d62-c08d-4d78-baf7-11e7a4c9bc36",\n",
       "    "created": "2021-03-31T22:43:42.807698Z",\n",
       "    "modified": "2021-03-31T22:43:42.807698Z",\n",
       "    "name": "My First SRO",\n",
       "    "some_source_ref": "identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",\n",
       "    "some_target_ref": "identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",\n",
       "    "extensions": {\n",
       "        "extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce": {\n",
       "            "extension_type": "new-sro"\n",
       "        }\n",
       "    }\n",
       "}\n",
       "
\n" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "invalid_refs = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting', 'foobar']\n", "\n", "@stix2.v21.CustomObject(\n", " 'my-favorite-sro', [\n", " ('name', stix2.properties.StringProperty(required=False)),\n", " ('some_source_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),\n", " ('some_target_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),\n", " ], extension_name='extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce', is_sdo=False,\n", ")\n", "class MyFavSRO:\n", " pass\n", "\n", "\n", "my_favorite_sro = MyFavSRO(\n", " name=\"My First SRO\",\n", " some_source_ref=\"identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d\",\n", " some_target_ref=\"identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685\",\n", ")\n", "\n", "print(my_favorite_sro.serialize(pretty=True))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.0a6" } }, "nbformat": 4, "nbformat_minor": 2 }