### Install Development Dependencies Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/contributing.md Navigate to the project directory and install necessary development dependencies using pip. ```bash cd cti-python-stix2 ``` ```bash pip install -r requirements.txt ``` -------------------------------- ### Install cti-python-stix2 Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Install the library using pip. Optional TAXII support can be included. ```bash pip install stix2 # Optional: TAXII support pip install stix2 taxii2-client ``` -------------------------------- ### Install stix2 with pip Source: https://github.com/oasis-open/cti-python-stix2/blob/master/README.rst Install the library using pip. The library requires Python 3.6+. ```bash $ pip install stix2 ``` -------------------------------- ### Create MemoryStore and add STIX objects Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/datastore.ipynb Initializes a MemoryStore and populates it with various STIX objects and their relationships. This setup is necessary for de-referencing operations. ```python from stix2 import Campaign, Identity, Indicator, Malware, Relationship mem = MemoryStore() cam = Campaign(name='Charge', description='Attack!') idy = Identity(name='John Doe', identity_class="individual") ind = Indicator(pattern_type='stix', pattern="[file:hashes.MD5 = 'd41d8cd98f00b204e9800998ecf8427e']") mal = Malware(name="Cryptolocker", is_family=False, created_by_ref=idy) rel1 = Relationship(ind, 'indicates', mal,) rel2 = Relationship(mal, 'targets', idy) rel3 = Relationship(cam, 'uses', mal) mem.add([cam, idy, ind, mal, rel1, rel2, rel3]) ``` -------------------------------- ### Install Pre-commit Git Hooks Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/contributing.md Install pre-commit git hooks to ensure code style and quality checks are performed automatically. ```bash pre-commit install ``` -------------------------------- ### Install TAXII Dependencies Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/equivalence.ipynb Install the TAXII dependencies required for using TAXII DataStore classes with the STIX 2.1 Python library. ```bash pip install stix2[taxii] ``` -------------------------------- ### Install Semantic Equivalence Dependencies Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/equivalence.ipynb To use the semantic equivalence functions in the stix2 library, you need to install the optional 'semantic' extra. This command installs the necessary dependencies. ```bash pip install stix2[semantic] ``` -------------------------------- ### Create Indicator with Provided ID Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/creating.ipynb Demonstrates creating an Indicator object with a pre-defined ID, ensuring it starts with the correct prefix. ```python indicator4 = Indicator(id="campaign--63ce9068-b5ab-47fa-a2cf-a602ea01f21a", pattern_type="stix", pattern="[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']") ``` -------------------------------- ### Create Environment with ObjectFactory and MemoryStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/environment.ipynb Combine an ObjectFactory with a MemoryStore within an Environment. This setup allows for creating STIX objects with default properties and immediately storing them in memory. ```python environ = Environment(ObjectFactory(created_by_ref="identity--311b2d2d-f010-4473-83ec-1edf84858f4c"), MemoryStore()) i = environ.create(Indicator, pattern_type="stix", pattern="[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']") environ.add(i) print(environ.get(i.id).serialize(pretty=True)) ``` -------------------------------- ### Create an IPv4Address with Resolves-To References (Object) Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/creating.ipynb Alternatively, Cyber Observable Objects can reference other objects by passing the object itself. This example creates MACAddress objects first and then uses their IDs to reference them from an IPv4Address. ```python from stix2 import MACAddress mac_addr_a = MACAddress(value="a1:b2:c3:d4:e5:f6") mac_addr_b = MACAddress(value="a7:b8:c9:d0:e1:f2") ip4_valid_refs = IPv4Address( value="177.60.40.7", resolves_to_refs=[mac_addr_a.id, mac_addr_b.id] ) print(ip4_valid_refs.serialize(pretty=True)) ``` -------------------------------- ### Run Tests Across Python Versions with Tox Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/contributing.md Utilize tox to test the package across multiple Python versions. Ensure tox is installed and run from the project's root directory. ```bash tox ``` -------------------------------- ### DataSource.all_versions Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/stix2.datastore.md Implement: Similar to get() except returns list of all object versions of the specified “id”. In addition, implement the specific data source API calls, processing, functionality required for retrieving data from the data source. ```APIDOC ## all_versions(stix_id) ### Description Implement: Similar to get() except returns list of all object versions of the specified “id”. In addition, implement the specific data source API calls, processing, functionality required for retrieving data from the data source. ### Parameters * **stix_id** (*str*) – The id of the STIX 2.0 object to retrieve. Should return a list of objects, all the versions of the object specified by the “id”. ### Returns *list* – All versions of the specified STIX object. ``` -------------------------------- ### Query MemoryStore for Malware Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/memory.ipynb Use the `query()` method with `Filter` objects to retrieve specific STIX objects based on their properties. This example retrieves all objects with the malware type 'rootkit'. ```python from stix2 import Filter mal = mem.query([Filter("malware_types","=", "rootkit")])[0] print(mal.serialize(pretty=True)) ``` -------------------------------- ### Apply Custom Marking to Indicator by Object Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/markings.ipynb This example shows how to apply a previously created custom marking definition to a new Indicator object by passing the marking definition object directly to object_marking_refs. ```python indicator2 = Indicator(pattern_type="stix", pattern="[file:hashes.md5 = 'd41d8cd98f00b204e9800998ecf8427e']", object_marking_refs=marking_definition) print(indicator2.serialize(pretty=True)) ``` -------------------------------- ### Create an IPv4Address with Resolves-To References (ID String) Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/creating.ipynb When creating Cyber Observable Objects, references to other objects can be specified using their ID strings. This example shows an IPv4Address referencing a MACAddress by its ID. ```python from stix2 import IPv4Address ip4 = IPv4Address( value="177.60.40.7", resolves_to_refs=["mac-addr--43f380fd-37c6-476d-8643-60849bf9240e"] ) print(ip4.serialize(pretty=True)) ``` -------------------------------- ### Create STIX Relationship Objects (SROs) Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Use `Relationship` and `Sighting` to link SDOs and SCOs, forming graph edges. Examples include directional relationships and sightings of malware. ```python import stix2 identity = stix2.Identity(name="SOC Team", identity_class="group") malware = stix2.Malware(name="BlackMatter", is_family=True, malware_types=["ransomware"]) tool = stix2.Tool(name="Cobalt Strike", tool_types=["exploitation"]) victim = stix2.Identity(name="Acme Corp", identity_class="organization") # Directional relationship rel = stix2.Relationship( relationship_type="uses", source_ref=malware.id, target_ref=tool.id, description="BlackMatter operators use Cobalt Strike for lateral movement", created_by_ref=identity.id, ) # Sighting: observed malware at a victim site sighting = stix2.Sighting( sighting_of_ref=malware.id, first_seen="2023-06-01T00:00:00Z", last_seen="2023-06-15T00:00:00Z", count=3, where_sighted_refs=[victim.id], created_by_ref=identity.id, ) print(rel.relationship_type) # uses print(sighting.count) # 3 ``` -------------------------------- ### Create and Push STIX Content to TAXII Collection Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/taxii.ipynb Instantiate a `TAXIICollectionSink` to push STIX objects to a TAXII collection. This example creates and adds a `ThreatActor` object. ```python from stix2 import TAXIICollectionSink, ThreatActor #create TAXIICollectionSINK and push STIX content to it tc_sink = TAXIICollectionSink(collection) # create new STIX threat-actor ta = ThreatActor(name="Teddy Bear", threat_actor_types=["nation-state"], sophistication="innovator", resource_level="government", goals=[ "compromising environment NGOs", "water-hole attacks geared towards energy sector", ]) tc_sink.add(ta) ``` -------------------------------- ### Define and Use Custom Top-Level Extension Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/extensions.ipynb This example shows how to define a custom top-level extension using the @CustomExtension decorator and then use it when creating a STIX 2.1 Indicator object. This registers the extension type and its properties. ```python 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)) ``` -------------------------------- ### Create and Use FileSystemStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/filesystem.ipynb Demonstrates creating a FileSystemStore for STIX 2.1 content and retrieving objects by ID. Ensure the directory exists or is creatable. ```python from stix2 import FileSystemStore # create FileSystemStore fs = FileSystemStore("/tmp/stix2_store") # retrieve STIX2 content from FileSystemStore ap = fs.get("attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22") mal = fs.get("malware--92ec0cbd-2c30-44a2-b270-73f4ec949841") # for visual purposes print(mal.serialize(pretty=True)) ``` -------------------------------- ### Create and Use FileSystemSource Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/filesystem.ipynb Demonstrates creating a FileSystemSource to retrieve STIX 2.1 objects from the filesystem. Requires a path to the source directory. ```python from stix2 import FileSystemSource # create FileSystemSource fs_source = FileSystemSource("/tmp/stix2_source") # retrieve STIX 2 objects ap = fs_source.get("attack-pattern--0a3ead4e-6d47-4ccb-854c-a6a4f9d96b22") # for visual purposes print(ap) ``` -------------------------------- ### Create and Use FileSystemSink Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/filesystem.ipynb Demonstrates creating a FileSystemSink to push STIX 2.1 content to the filesystem. Requires a path to the sink directory. ```python from stix2 import FileSystemSink, Campaign, Indicator # create FileSystemSink fs_sink = FileSystemSink("/tmp/stix2_sink") # create STIX objects and add to sink camp = Campaign(name="The Crusades", objective="Infiltrating Israeli, Iranian and Palestinian digital infrastructure and government systems.", aliases=["Desert Moon"]) ind = Indicator(description="Crusades C2 implant", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']") ind1 = Indicator(description="Crusades C2 implant", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']") ``` -------------------------------- ### Initialize Environment with MemoryStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/environment.ipynb Create a STIX 2 Environment configured with a MemoryStore for in-memory storage and retrieval of STIX content. This is useful for testing or applications that don't require persistent storage. ```python from stix2 import Environment, MemoryStore env = Environment(store=MemoryStore()) ``` -------------------------------- ### Create and Use CompositeDataSource Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/datastore.ipynb Demonstrates creating a CompositeDataSource by adding FileSystemSource and TAXIICollectionSource instances. It shows how to retrieve objects from the combined data sources. ```python from taxii2client import Collection from stix2 import CompositeDataSource, FileSystemSource, TAXIICollectionSource # create FileSystemStore fs = FileSystemSource("/tmp/stix2_source") # create TAXIICollectionSource colxn = Collection('http://127.0.0.1:5000/trustgroup1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/', user="user1", password="Password1") ts = TAXIICollectionSource(colxn) # add them both to the CompositeDataSource cs = CompositeDataSource() cs.add_data_sources([fs,ts]) # get an object that is only in the filesystem intrusion_set = cs.get('intrusion-set--f3bdec95-3d62-42d9-a840-29630f6cdc1a') print(intrusion_set.serialize(pretty=True)) # get an object that is only in the TAXII collection ind = cs.get('indicator--a740531e-63ff-4e49-a9e1-a0a3eed0e3e7') print(ind.serialize(pretty=True)) ``` -------------------------------- ### Create FileSystemSource with Custom Content Allowed Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/parsing.ipynb Instantiate a FileSystemSource to allow retrieval of unknown custom STIX2 content from the file system. Ensure the path points to your STIX2 data. ```python from stix2 import FileSystemSource # create FileSystemStore fs = FileSystemSource("/path/to/stix2_data/", allow_custom=True) ``` -------------------------------- ### get Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/stix2.workbench.md Retrieve the most recent version of a single STIX object by ID. ```APIDOC ## get ### Description Retrieve the most recent version of a single STIX object by ID. Translate get() call to the appropriate DataSource call. ### Parameters * **stix_id** (*str*) – the id of the STIX object to retrieve. ### Returns *stix_obj* – the single most recent version of the STIX object specified by the “id”. ``` -------------------------------- ### Get Object Markings Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/markings.ipynb Retrieve a list of marking definition IDs associated with a STIX object using the `get_markings()` method. ```python indicator6.get_markings() ``` -------------------------------- ### Initialize Environment with CompositeDataSource and FileSystemSink Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/environment.ipynb Set up a STIX 2 Environment with a composite data source that reads from memory and a filesystem, and a filesystem sink for storing data. This allows for flexible data management across different storage backends. ```python from stix2 import CompositeDataSource, FileSystemSink, FileSystemSource, MemorySource src = CompositeDataSource() src.add_data_sources([MemorySource(), FileSystemSource("/tmp/stix2_source")]) env2 = Environment(source=src, sink=FileSystemSink("/tmp/stix2_sink")) ``` -------------------------------- ### Add STIX Object to TAXIICollectionStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/taxii.ipynb Add a STIX object to a `TAXIICollectionStore`. This example adds an `Indicator` object with a SHA-256 hash. ```python from stix2 import Indicator # add STIX object to TAXIICollectionStore ind = Indicator(description="Smokey Bear implant", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '09c7e05a39a59428743635242e4a867c932140a909f12a1e54fa7ee6a440c73b']") tc_store.add(ind) ``` -------------------------------- ### get(stix_id) Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/stix2.environment.md Retrieve the most recent version of a single STIX object by its ID. This method translates the call to the appropriate DataSource method. ```APIDOC ## get(*args, **kwargs) Retrieve the most recent version of a single STIX object by ID. Translate get() call to the appropriate DataSource call. ### Parameters: * **stix_id** (*str*) – the id of the STIX object to retrieve. * **Returns:** *stix_obj* – the single most recent version of the STIX object specified by the “id”. ``` -------------------------------- ### startstop_cmp Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/equivalence/pattern/compare/stix2.equivalence.pattern.compare.observation.md Compares START/STOP qualifiers in STIX 2 patterns. The comparison is lexicographical, ordering first by start time, then by stop time. ```APIDOC ## startstop_cmp(qual1, qual2) ### Description Compare START/STOP qualifiers. This lexicographically orders by start time, then stop time. ### Parameters * **qual1** – The first START/STOP qualifier * **qual2** – The second START/STOP qualifier ### Returns <0, 0, or >0 depending on whether the first arg is less, equal or greater than the second ``` -------------------------------- ### Set up TAXII Collection Data Source Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/workbench.ipynb This snippet demonstrates how to configure a TAXII 2.1 collection as a data source for the workbench. It requires the `taxii2client` library and specifies the collection URL, username, and password for authentication. ```python from taxii2client import Collection collection = Collection("http://127.0.0.1:5000/trustgroup1/collections/91a7b528-80eb-42ed-a74d-c6fbd5a26116/", user="admin", password="Password0") pc_source = TAXIICollectionSource(collection) add_data_source(tc_source) ``` -------------------------------- ### Handle STIX Object Markings Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates how to get, add, set, remove, and clear markings on STIX objects, including granular markings. ```python import stix2 tlp_green = stix2.TLP_GREEN # Pre-built TLP marking definition tlp_red = stix2.TLP_RED report = stix2.Report( name="APT29 Campaign", report_types=["threat-actor"], published="2023-06-01T00:00:00Z", object_refs=[], object_marking_refs=[tlp_green.id], granular_markings=[ stix2.GranularMarking( marking_ref=tlp_red.id, selectors=["description"], ) ], description="Classified details about the campaign.", ) # Get all object-level markings obj_marks = stix2.get_markings(report) print(obj_marks) # ['marking-definition--TLP_GREEN_id'] # Get granular markings on a specific selector desc_marks = stix2.get_markings(report, selectors="description") print(desc_marks) # ['marking-definition--TLP_RED_id'] # Check if marked print(stix2.is_marked(report, tlp_green.id)) # True print(stix2.is_marked(report, selectors="description")) # True # Add a marking report2 = stix2.add_markings(report, tlp_red.id) print(stix2.is_marked(report2, tlp_red.id)) # True # Clear granular markings for a selector report3 = stix2.clear_markings(report, selectors="description") print(stix2.get_markings(report3, selectors="description")) # [] # Remove an object-level marking report4 = stix2.remove_markings(report, tlp_green.id) print(stix2.is_marked(report4, tlp_green.id)) # False ``` -------------------------------- ### Observation Expressions for File and Process Matching Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/patterns.ipynb Illustrates the creation of ObservationExpressions for matching file names, registry keys, and process names. Note the comment indicating the need for AND/OR observation expressions for certain combinations. ```python ece20 = ObservationExpression(EqualityComparisonExpression(ObjectPath("file", ["name"])), "foo.dll") ece21 = ObservationExpression(EqualityComparisonExpression(ObjectPath("win-registry-key", ["key"])), "HKEY_LOCAL_MACHINE\\foo\\bar") ece22 = EqualityComparisonExpression(ObjectPath("process", ["name"])), "fooproc") ece23 = EqualityComparisonExpression(ObjectPath("process", ["name"])), "procfoo") # NOTE: we need to use AND/OR observation expression instead of just boolean ``` -------------------------------- ### Create and Serialize a STIX Bundle Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates how to create STIX objects (Identity, Malware, Indicator, Relationship) and package them into a Bundle. The bundle can then be serialized to a JSON string. ```python import stix2 identity = stix2.Identity(name="Threat Intel Corp", identity_class="organization") malware = stix2.Malware(name="Ryuk", is_family=True, malware_types=["ransomware"]) indicator = stix2.Indicator( name="Ryuk hash", indicator_types=["malicious-activity"], pattern_type="stix", pattern="[file:hashes.'SHA-256' = 'abc123']", valid_from="2023-01-01T00:00:00Z", ) rel = stix2.Relationship("uses", malware.id, indicator.id, relationship_type="indicates") bundle = stix2.Bundle(objects=[identity, malware, indicator, rel]) print(bundle.id) # bundle--xxxx... print(len(bundle.objects)) # 4 # Serialize json_str = bundle.serialize(pretty=True) print(json_str[:100]) ``` -------------------------------- ### Traverse Relationships and Manage Versions Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates how to create and save relationships, and how to manage different versions of STIX objects. ```python rel = wb.Relationship("indicates", indicator.id, malware.id) wb.save(rel) rels = wb.relationships(malware) print(len(rels)) # 1 updated = wb.new_version(malware, description="Linked to GRU Unit 26165") wb.save(updated) versions = wb.all_versions(malware.id) print(len(versions)) # 2 ``` -------------------------------- ### Add a STIX Indicator to MemoryStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/memory.ipynb Use the `add()` method to insert a single STIX object into the MemoryStore. The `get()` method can then be used to retrieve it by ID. ```python from stix2 import Indicator # insert newly created indicator into memory ind = Indicator(description="Crusades C2 implant", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']") mem.add(ind) # for visual purposes print(mem.get(ind.id).serialize(pretty=True)) ``` -------------------------------- ### Create a Default MemoryStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/memory.ipynb Initializes a MemoryStore, which is an in-memory data store for STIX content. This is useful for temporary storage or testing purposes. ```python from stix2 import MemoryStore, Indicator # create default MemoryStore mem = MemoryStore() ``` -------------------------------- ### Query TAXII Data Source with Filters Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/taxii.ipynb Use the `Filter` object to specify criteria for querying a TAXII data source. This example filters for indicators. ```python from stix2 import Filter f1 = Filter("type","=", "indicator") indicators = tc_source.query([f1]) #for visual purposes for indicator in indicators: print(indicator.serialize(pretty=True)) ``` -------------------------------- ### Defining a Custom STIX Object Type Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/v21/stix2.v21.sdo.md This example demonstrates how to use the CustomObject decorator to define a new STIX object type with custom properties. ```APIDOC ## Defining a Custom STIX Object Type ### Description Use the `@CustomObject` decorator to define a new STIX object type with specified properties. You can also supply an `__init__()` function for custom validations. ### Method Decorator ### Parameters - **type** (string) - Required - The STIX type name for the custom object (e.g., 'x-custom-type'). - **properties** (list of tuples) - Required - A list where each tuple defines a property: `(property_name, property_definition)`. - **extension_name** (string) - Optional - The name of the extension. - **is_sd** (boolean) - Optional - Indicates if it's a STIX Domain Object (SDO). ### Example ```pycon >>> from stix2.v21 import CustomObject >>> from stix2.properties import StringProperty, IntegerProperty >>> @CustomObject('x-type-name', [ ... ('property1', StringProperty(required=True)), ... ('property2', IntegerProperty()), ... ]) ... class MyNewObjectType(): ... pass ``` ### Example with Custom Validation ```pycon >>> from stix2.v21 import CustomObject >>> from stix2.properties import StringProperty, IntegerProperty >>> @CustomObject('x-type-name', [ ... ('property1', StringProperty(required=True)), ... ('property2', IntegerProperty()), ... ]) ... class MyNewObjectType(): ... def __init__(self, property2=None, **kwargs): ... if property2 and property2 < 10: ... raise ValueError("'property2' is too small.") ``` ``` -------------------------------- ### Stateful CTI Workspace with Environment Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates creating and managing STIX objects within a stateful workspace using Environment. Includes setting default object properties via ObjectFactory, querying, and managing relationships. ```python import stix2 # Create a shared identity for all objects my_org = stix2.Identity(name="ACME Threat Intel", identity_class="organization") factory = stix2.ObjectFactory( created_by_ref=my_org.id, object_marking_refs=[stix2.TLP_GREEN.id], ) env = stix2.Environment( factory=factory, store=stix2.MemoryStore(), ) env.add([my_org]) # Create objects with factory defaults applied automatically malware = env.create(stix2.Malware, name="BlackMatter", is_family=True, malware_types=["ransomware"]) indicator = env.create( stix2.Indicator, name="BlackMatter hash", indicator_types=["malicious-activity"], pattern_type="stix", pattern="[file:hashes.MD5 = 'abc123']", valid_from="2023-01-01T00:00:00Z", ) env.add([malware, indicator]) # Query results = env.query([stix2.Filter("type", "=", "malware")]) print(results[0].created_by_ref == my_org.id) # True # Relationships helper rel = stix2.Relationship("indicates", indicator.id, malware.id) env.add(rel) rels = env.relationships(malware, relationship_type="indicates", source_only=False) print(len(rels)) # 1 # creator_of creator = env.creator_of(malware) print(creator.name) # ACME Threat Intel ``` -------------------------------- ### Get Granular Markings Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/markings.ipynb Retrieve granular markings for a specific property of a STIX object by passing the property name to `get_markings()`. This can be called as a standalone function or a method on the object. ```python from stix2 import get_markings get_markings(malware, 'name') ``` ```python malware.get_markings('name') ``` -------------------------------- ### Attach Filters to FileSystemStore and FileSystemSource Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/datastore.ipynb Shows how to attach single or multiple filters to a FileSystemStore and a FileSystemSource. Filters are added to the 'filters' attribute of the store's or source's source object. ```python from stix2 import MemoryStore, FileSystemStore, FileSystemSource fs = FileSystemStore("/tmp/stix2_store") fs_source = FileSystemSource("/tmp/stix2_source") # attach filter to FileSystemStore fs.source.filters.add(f) # attach multiple filters to FileSystemStore fs.source.filters.add([f1,f2]) # can also attach filters to a Source # attach multiple filters to FileSystemSource fs_source.filters.add([f3, f4]) ``` -------------------------------- ### STIX FileSystemStore Operations Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates using FileSystemStore for on-disk STIX data storage, including writing, verifying, reading, and querying objects. ```python import stix2, tempfile, os # Create a temporary directory for the store tmpdir = tempfile.mkdtemp() fs_store = stix2.FileSystemStore(tmpdir) malware = stix2.Malware(name="Trickbot", is_family=True, malware_types=["trojan"]) indicator = stix2.Indicator( name="Trickbot C2", indicator_types=["malicious-activity"], pattern_type="stix", pattern="[domain-name:value = 'trickbot-c2.example.com']", valid_from="2023-01-01T00:00:00Z", ) # Write objects to disk fs_store.add([malware, indicator]) # Verify files on disk malware_dir = os.path.join(tmpdir, "malware", malware.id) print(os.path.isdir(malware_dir)) # True # Read back fs_source = stix2.FileSystemSource(tmpdir) retrieved = fs_source.get(malware.id) print(retrieved.name) # Trickbot # Query from filesystem results = fs_source.query([stix2.Filter("type", "=", "indicator")]) print(results[0].name) # Trickbot C2 ``` -------------------------------- ### Invalid Selector Example Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/markings.ipynb This code demonstrates an error scenario where an invalid selector ('title') is used with granular markings on a Malware object. This will raise an InvalidSelectorError because 'title' is not a valid field. ```python Malware(name="Poison Ivy", description="A ransomware related to ...", is_family=False, granular_markings=[ { "selectors": ["title"], "marking_ref": marking_definition } ]) ``` -------------------------------- ### Attach Filters to MemoryStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/datastore.ipynb Demonstrates attaching single or multiple filters to a MemoryStore. This is useful as MemorySink or MemorySource are often impractical for direct use. ```python mem = MemoryStore() # As it is impractical to only use MemorySink or MemorySource, # attach a filter to a MemoryStore mem.source.filters.add(f) # attach multiple filters to a MemoryStore mem.source.filters.add([f1,f2]) ``` -------------------------------- ### Define and Use Custom STIX Objects Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Demonstrates how to define and instantiate custom STIX objects like DNSQuery and InternalMarking using decorators. Ensure the necessary properties are defined with appropriate types. ```python import stix2 from stix2 import StringProperty @stix2.CustomObservable( "x-dns-query", [ ("domain", StringProperty(required=True)), ("query_type", StringProperty()), ], id_contrib_props=["domain"], ) class DNSQuery: pass dns = DNSQuery(domain="evil.example.com", query_type="A") print(dns.domain) # evil.example.com # Custom Marking Definition @stix2.CustomMarking( "x-internal-marking", [("classification", StringProperty(required=True))], ) class InternalMarking: pass marking = stix2.MarkingDefinition( definition_type="x-internal-marking", definition=InternalMarking(classification="TOP SECRET"), ) print(marking.definition.classification) # TOP SECRET ``` -------------------------------- ### Custom String Comparison for a Property Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/equivalence.ipynb Use a custom comparison function for a specific property like 'name' by providing it in the weights dictionary. This example uses a simple equality check for strings. ```python def my_string_compare(p1, p2): if p1 == p2: return 1 else: return 0 weights = { "threat-actor": { "name": (45, my_string_compare), "threat_actor_types": (10, stix2.equivalence.object.partial_list_based), "aliases": (45, stix2.equivalence.object.partial_list_based), }, } print("Using custom string comparison: %s" % (env.object_similarity(ta5, ta6, **weights))) ``` -------------------------------- ### Add STIX Objects to FileSystemStore Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/filesystem.ipynb Shows how to create STIX objects (ThreatActor and Indicator) and add them to a FileSystemStore. Multiple objects can be added in a single call. ```python from stix2 import ThreatActor, Indicator # create new STIX threat-actor ta = ThreatActor(name="Adjective Bear", sophistication="innovator", resource_level="government", goals=[ "compromising media outlets", "water-hole attacks geared towards political, military targets", "intelligence collection" ]) # create new indicators ind = Indicator(description="Crusades C2 implant", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '54b7e05e39a59428743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']") ind1 = Indicator(description="Crusades C2 implant 2", pattern_type="stix", pattern="[file:hashes.'SHA-256' = '64c7e05e40a59511743635242e4a867c932140a999f52a1e54fa7ee6a440c73b']") # add STIX object (threat-actor) to FileSystemStore fs.add(ta) # can also add multiple STIX objects to FileSystemStore in one call fs.add([ind, ind1]) ``` -------------------------------- ### Create and Serialize a Custom Cyber Observable Instance Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/custom.ipynb Instantiate a custom Cyber Observable and serialize it. Required properties must be provided. ```python new_observable = NewObservable(a_property="something", property_2=10) print(new_observable.serialize(pretty=True)) ``` -------------------------------- ### Aggregate Data Sources with CompositeDataSource Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Shows how to combine multiple data sources (MemoryStore and FileSystemStore) into a single queryable interface using CompositeDataSource. Results are automatically deduplicated. ```python import stix2, tempfile # Build two separate stores mem_store = stix2.MemoryStore() mem_store.add(stix2.Malware(name="Emotet", is_family=True, malware_types=["trojan"])) tmpdir = tempfile.mkdtemp() fs_store = stix2.FileSystemStore(tmpdir) fs_store.add(stix2.Malware(name="Ryuk", is_family=True, malware_types=["ransomware"])) # Composite: query both at once composite = stix2.CompositeDataSource() composite.add_data_source(mem_store.source) composite.add_data_source(stix2.FileSystemSource(tmpdir)) results = composite.query([stix2.Filter("type", "=", "malware")]) print([r.name for r in results]) # ['Emotet', 'Ryuk'] # Also works with Environment env = stix2.Environment(source=composite) all_malware = env.query([stix2.Filter("type", "=", "malware")]) print(len(all_malware)) # 2 ``` -------------------------------- ### Create Indicator with Unregistered Top-Level Extension Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/extensions.ipynb This example demonstrates creating a STIX 2.1 Indicator object with an unregistered top-level property extension. Unrecognized top-level properties are treated as extensions by default. ```python import stix2 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-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8" : { 'extension_type': 'toplevel-property-extension', }, } ) print(indicator.serialize(pretty=True)) ``` -------------------------------- ### Parse STIX JSON String Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/parsing.ipynb Demonstrates parsing a STIX 2.x Observed Data object from a JSON string. Ensure the `stix2` library is installed. The `parse()` function automatically detects the object type. ```python from stix2 import parse input_string = """ { "type": "observed-data", "id": "observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf", "spec_version": "2.1", "created": "2016-04-06T19:58:16.000Z", "modified": "2016-04-06T19:58:16.000Z", "first_observed": "2015-12-21T19:00:00Z", "last_observed": "2015-12-21T19:00:00Z", "number_observed": 50, "object_refs": [ "file--5d2dc832-b137-4e8c-97b2-5b00c18be611" ] } """ obj = parse(input_string) print(type(obj)) print(obj.serialize(pretty=True)) ``` -------------------------------- ### Create ObjectFactory with Multiple Defaults Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/environment.ipynb Initialize an ObjectFactory with multiple default properties, such as 'created_by_ref' and 'created'. These defaults will be applied to all objects created by this factory. ```python factory2 = ObjectFactory(created_by_ref="identity--311b2d2d-f010-4473-83ec-1edf84858f4c", created="2017-09-25T18:07:46.255472Z") ``` -------------------------------- ### Retrieve Indicators with Filters Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/workbench.ipynb Filter indicator retrieval by specifying criteria using `stix2.Filter` objects. This example retrieves indicators created by a particular identity, demonstrating how to narrow down results based on object properties. ```python response = indicators(filters=Filter('created_by_ref', '=', 'identity--adede3e8-bf44-4e6f-b3c9-1958cbc3b188')) ``` -------------------------------- ### Define a Custom STIX Marking Object Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/v21/stix2.v21.common.md Illustrates how to define a custom STIX marking object using the CustomMarking decorator. This example defines a marking with a required string property and an optional integer property. ```python >>> from stix2.v21 import CustomMarking >>> from stix2.properties import IntegerProperty, StringProperty >>> @CustomMarking('x-custom-marking', [ ... ('property1', StringProperty(required=True)), ... ('property2', IntegerProperty()), ... ]) ... class MyNewMarkingObjectType(): ... pass ``` -------------------------------- ### Create STIX 2 Filters Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/datastore.ipynb Demonstrates creating various filters for STIX objects based on different criteria such as external references, object types, labels, modification timestamps, and revocation status. Ensure the 'stix2' library is imported. ```python import sys from stix2 import Filter # create filter for STIX objects that have external references to MITRE ATT&CK framework f = Filter("external_references.source_name", "=", "mitre-attack") # create filter for STIX objects that are not of SDO type Attack-Pattnern f1 = Filter("type", "!=", "attack-pattern") # create filter for STIX objects that have the "threat-report" label f2 = Filter("labels", "in", "threat-report") # create filter for STIX objects that have been modified past the timestamp f3 = Filter("modified", ">=", "2017-01-28T21:33:10.772474Z") # create filter for STIX objects that have been revoked f4 = Filter("revoked", "=", True) ``` -------------------------------- ### DNFTransformer Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/equivalence/pattern/transform/stix2.equivalence.pattern.transform.comparison.md Converts a STIX pattern comparison expression AST into Disjunctive Normal Form (DNF). This transformation expands expressions to simplify logical structures, for example, converting 'A and (B or C)' to '(A and B) or (A and C)'. ```APIDOC ## DNFTransformer Convert a comparison expression AST to DNF. E.g.: > A and (B or C) => (A and B) or (A and C) ``` -------------------------------- ### Access Related Objects Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/workbench.ipynb Retrieve objects directly related to an indicator using the `.related()` method. This allows for easy navigation of the STIX graph. The example iterates through related objects and prints their serialized JSON representation. ```python for i in indicators(): for obj in i.related(): print(obj.serialize(pretty=True)) ``` -------------------------------- ### Identity Object Serialization Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/stix2.v20.md Demonstrates how to create an Identity object and serialize it to JSON, with options for pretty printing and sorting keys. ```APIDOC ## Identity.serialize() ### Description Serialize a STIX object to a JSON string. ### Method `serialize(pretty=False, include_optional_defaults=False, **kwargs)` ### Parameters - **pretty** (bool) - Optional - If True, format the JSON output with indentation. - **include_optional_defaults** (bool) - Optional - If True, include optional properties even if they have default values. - **kwargs** - Additional keyword arguments for serialization options. ### Request Example ```python import stix2 identity = stix2.Identity(name='Example Corp.', identity_class='organization') print(identity.serialize(sort_keys=True)) print(identity.serialize(sort_keys=True, indent=4)) ``` ### Response #### Success Response (str) - The serialized JSON object as a string. #### Response Example ```json { "created": "2018-06-08T19:03:54.066Z", "id": "identity--d7f3e25a-ba1c-447a-ab71-6434b092b05e", "identity_class": "organization", "modified": "2018-06-08T19:03:54.066Z", "name": "Example Corp.", "type": "identity" } ``` ### SEE ALSO `stix2.serialization.serialize` for options. ``` -------------------------------- ### Create STIX Domain Objects (SDOs) Source: https://context7.com/oasis-open/cti-python-stix2/llms.txt Construct STIX 2.1 SDOs by passing keyword arguments to their respective classes. Common properties like type, id, spec_version, created, and modified are auto-generated if omitted. Required for attribution. ```python import stix2 # Identity (required for attribution) identity = stix2.Identity( name="ACME Security", identity_class="organization", ) # Malware SDO malware = stix2.Malware( name="Emotet", is_family=True, malware_types=["trojan", "ransomware"], description="Banking trojan / ransomware dropper", created_by_ref=identity.id, kill_chain_phases=[ stix2.KillChainPhase(kill_chain_name="mitre-attack", phase_name="execution") ], ) # Indicator SDO with STIX pattern indicator = stix2.Indicator( name="Emotet C2 IP", indicator_types=["malicious-activity"], pattern_type="stix", pattern="[ipv4-addr:value = '198.51.100.0']", valid_from="2023-01-01T00:00:00Z", created_by_ref=identity.id, ) # Vulnerability vuln = stix2.Vulnerability( name="CVE-2021-44228", description="Log4Shell remote code execution vulnerability", external_references=[ stix2.ExternalReference( source_name="nvd", external_id="CVE-2021-44228", url="https://nvd.nist.gov/vuln/detail/CVE-2021-44228", ) ], ) print(malware.id) # malware--xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx print(indicator.pattern) # [ipv4-addr:value = '198.51.100.0'] ``` -------------------------------- ### Traverse Relationships from Indicators Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/guide/workbench.ipynb Iterate through indicators and access their relationships. The `.relationships()` method returns all direct relationship objects associated with an indicator. This example prints the source reference, relationship type, and target reference for each relationship. ```python for i in indicators(): for rel in i.relationships(): print(rel.source_ref) print(rel.relationship_type) print(rel.target_ref) ``` -------------------------------- ### create Source: https://github.com/oasis-open/cti-python-stix2/blob/master/docs/api/stix2.workbench.md Create a STIX object using object factory defaults. ```APIDOC ## create ### Description Create a STIX object using object factory defaults. ### Parameters * **cls** – the python-stix2 class of the object to be created (eg. Indicator) * **kwargs** – The property/value pairs of the STIX object to be created ```