STIX helper module
FIXME
- validate_stix_id(uuid: str, object_type: str = '') bool
Test whether a string is a STIX standard ID ([object-type]–[UUID])
Examples:
>>> validate_stix_id('indicator--167565fe-69da-5e2f-a1c1-0542736f9f9a') True >>> validate_stix_id('marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da', 'marking-definition') True >>> validate_stix_id('marking-definition--34098fce-860f-48ae-8e50-ebd3cc5e41da', 'ipv4-addr') False
- pydantic model SCOBundle
Show JSON schema
{ "title": "SCOBundle", "type": "object", "properties": { "sco": { "anyOf": [], "title": "Sco" }, "nested_objs": { "default": [], "items": { "anyOf": [] }, "title": "Nested Objs", "type": "array" } }, "required": [ "sco" ] }
- Config:
arbitrary_types_allowed: bool = True
- Fields:
nested_objs (list[stix2.v21.observables.Artifact | stix2.v21.observables.AutonomousSystem | stix2.v21.observables.Directory | stix2.v21.observables.DomainName | stix2.v21.observables.EmailAddress | stix2.v21.observables.EmailMessage | stix2.v21.observables.File | stix2.custom._custom_observable_builder.
sco (stix2.v21.observables.Artifact | stix2.v21.observables.AutonomousSystem | stix2.v21.observables.Directory | stix2.v21.observables.DomainName | stix2.v21.observables.EmailAddress | stix2.v21.observables.EmailMessage | stix2.v21.observables.File | stix2.custom._custom_observable_builder.
- field nested_objs: list[~stix2.v21.observables.Artifact | ~stix2.v21.observables.AutonomousSystem | ~stix2.v21.observables.Directory | ~stix2.v21.observables.DomainName | ~stix2.v21.observables.EmailAddress | ~stix2.v21.observables.EmailMessage | ~stix2.v21.observables.File | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.IPv4Address | ~stix2.v21.observables.IPv6Address | ~stix2.v21.observables.MACAddress | ~stix2.v21.observables.Mutex | ~stix2.v21.observables.NetworkTraffic | ~stix2.v21.observables.Process | ~stix2.v21.observables.Software | ~stix2.v21.observables.URL | ~stix2.v21.observables.UserAccount | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.WindowsRegistryKey | ~stix2.v21.observables.X509Certificate] = []
- field sco: X509Certificate [Required]
- objects() list[~stix2.v21.observables.Artifact | ~stix2.v21.observables.AutonomousSystem | ~stix2.v21.observables.Directory | ~stix2.v21.observables.DomainName | ~stix2.v21.observables.EmailAddress | ~stix2.v21.observables.EmailMessage | ~stix2.v21.observables.File | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.IPv4Address | ~stix2.v21.observables.IPv6Address | ~stix2.v21.observables.MACAddress | ~stix2.v21.observables.Mutex | ~stix2.v21.observables.NetworkTraffic | ~stix2.v21.observables.Process | ~stix2.v21.observables.Software | ~stix2.v21.observables.URL | ~stix2.v21.observables.UserAccount | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.WindowsRegistryKey | ~stix2.v21.observables.X509Certificate]
- tlp_marking_from_string(tlp_string: str | None)
Map a TLP string to a corresponding marking definition, or None
Any characters up to and including “:” are stripped and case is ignored.
Examples:
>>> tlp_marking_from_string('white') 'marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9' >>> tlp_marking_from_string('TLP:amBEr') 'marking-definition--f88d31f6-486f-44da-b317-01333bde0b82' >>> tlp_marking_from_string('foo') Traceback (most recent call last): ... ValueError: foo is not a valid marking definition
- tlp_allowed(entity: dict, max_tlp: Literal['TLP:CLEAR', 'TLP:WHITE', 'TLP:GREEN', 'TLP:AMBER', 'TLP:AMBER+STRICT', 'TLP:RED']) bool
If the entity has a TLP marking definition, ensure it is within a maximum allowed TLP
- entity_value(entity: dict) str | None
Return an observable’s (or vulnerability’s) value
- entity_values(entity: dict) list[Any]
Return an observable’s (or vulnerability’s) values
- entity_name_value(entity: dict)
Return the name and value of an entity, space separated
- incident_entity_relation_type(entity: dict)
Return the expected relationship type for the entity in the incident
- remove_unref_objs(bundle: ~typing.Sequence[~stix2.v21.observables.Artifact | ~stix2.v21.observables.AutonomousSystem | ~stix2.v21.observables.Directory | ~stix2.v21.observables.DomainName | ~stix2.v21.observables.EmailAddress | ~stix2.v21.observables.EmailMessage | ~stix2.v21.observables.File | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.IPv4Address | ~stix2.v21.observables.IPv6Address | ~stix2.v21.observables.MACAddress | ~stix2.v21.observables.Mutex | ~stix2.v21.observables.NetworkTraffic | ~stix2.v21.observables.Process | ~stix2.v21.observables.Software | ~stix2.v21.observables.URL | ~stix2.v21.observables.UserAccount | ~stix2.custom._custom_observable_builder.<locals>._CustomObservable | ~stix2.v21.observables.WindowsRegistryKey | ~stix2.v21.observables.X509Certificate | ~stix2.v21.sdo.AttackPattern | ~stix2.v21.sdo.Campaign | ~stix2.v21.sdo.CourseOfAction | ~stix2.v21.sdo.Grouping | ~stix2.v21.sdo.Identity | ~stix2.v21.sdo.Incident | ~stix2.v21.sdo.Indicator | ~stix2.v21.sdo.Infrastructure | ~stix2.v21.sdo.IntrusionSet | ~stix2.v21.sdo.Location | ~stix2.v21.sdo.Malware | ~stix2.v21.sdo.MalwareAnalysis | ~stix2.v21.sdo.Note | ~stix2.v21.sdo.ObservedData | ~stix2.v21.sdo.Opinion | ~stix2.v21.sdo.Report | ~stix2.v21.sdo.ThreatActor | ~stix2.v21.sdo.Tool | ~stix2.v21.sdo.Vulnerability | ~stix2.v21.sro.Relationship | ~stix2.v21.sro.Sighting]) Sighting]
Return a new bundle only with SCOs/SDOs that are referenced in SROs
All observables and domain objects that are referenced by relationships or sightings (not as nested objects) are kept in the list, in order. All unreferenced objects are removed.
Examples:
>>> f1 = stix2.File(name='foo', allow_custom=True, test_id='file_foo') >>> f2 = stix2.File(name='bar', allow_custom=True, test_id='file_bar') >>> f3 = stix2.File(name='baz', allow_custom=True, test_id='file_baz') >>> r1 = stix2.Relationship(relationship_type='related-to', source_ref=f1, target_ref=f2, allow_custom=True, test_id='rel') >>> i1 = stix2.Indicator(pattern="[file:name = 'foo']", pattern_type='stix', valid_from='2024-04-04T15:46:03.282304Z', allow_custom=True, test_id='ind') >>> id1 = stix2.Identity(name='id1', allow_custom=True, test_id='id1') >>> id2 = stix2.Identity(name='id2', allow_custom=True, test_id='id2') >>> id3 = stix2.Identity(name='id3', allow_custom=True, test_id='id3') >>> s1 = stix2.Sighting(sighting_of_ref=i1.id, where_sighted_refs=[id1, id2], allow_custom=True, test_id='sight') >>> bundle = [f1, r1, f2, f3, id1, i1, id2, s1, id3] >>> [o.test_id for o in remove_unref_objs(bundle)] ['file_foo', 'rel', 'file_bar', 'id1', 'ind', 'id2', 'sight']
- find_hashes(obj: Mapping, fields: list[list[str]], overwrite: bool = False) dict[str, dict[str, str]]
Return a dict suitable for the argument ‘hashes’ in stix2.File from hash properties in an alert
The hash keys will be transformed into the keys expected by STIX, e.g. ‘sha256_after’ will be replaced with ‘SHA-256’. Any field containing ‘sha256’ or ‘sha-256’ in any case will be matched. The hashes themselves are not verified.
The fields is a list of list of fields, where the outer list determines the order of preference. The overwrite parameter determines whether a hash member found in a previous field list will be replaced or not.
Examples:
>>> alert = {"syscheck": { "md5_before": "11ee6b89a2500aa326d45bc0f0d93821", "sha256_before": "87b3bfb07fa641adf426961c9d5e8a81c321fd03c32d9afb0f761a2c876cb6a1", "sha1_after": "950c5897c1e1b8b7686b976472d19fd815beccd7", "md5_after": "502ad4209d3eb3267d08708f0807de1c", "sha1_before": "ff916c71058daa68e2951a50bed8b3e5bfd7aff3", "sha256_after": "6f2a43b4d954d9984701a23513bb4476736dd4aed5b5ec47ad99e7943eacd7bf"}} >>> find_hashes(alert, [['syscheck.sha256_after', 'syscheck.md5_after', 'syscheck.sha1_after'], ['syscheck.sha256_before']]) {'SHA-256': '6f2a43b4d954d9984701a23513bb4476736dd4aed5b5ec47ad99e7943eacd7bf', 'MD5': '502ad4209d3eb3267d08708f0807de1c', 'SHA-1': '950c5897c1e1b8b7686b976472d19fd815beccd7'} >>> find_hashes(alert, [['syscheck.sha256_after', 'syscheck.md5_after', 'syscheck.sha1_after'], ['syscheck.sha256_before']], overwrite=True) {'SHA-256': '87b3bfb07fa641adf426961c9d5e8a81c321fd03c32d9afb0f761a2c876cb6a1', 'MD5': '502ad4209d3eb3267d08708f0807de1c', 'SHA-1': '950c5897c1e1b8b7686b976472d19fd815beccd7'}
- pydantic model StixHelper
Helper class to simplify creation of STIX entities
Show JSON schema
{ "title": "StixHelper", "description": "Helper class to simplify creation of STIX entities", "type": "object", "properties": { "common_properties": { "default": {}, "title": "Common Properties", "type": "object" }, "sco_labels": { "default": [], "items": { "type": "string" }, "title": "Sco Labels", "type": "array" }, "filename_behaviour": { "default": [ "create-dir" ], "items": { "$ref": "#/$defs/FilenameBehaviour" }, "title": "Filename Behaviour", "type": "array", "uniqueItems": true } }, "$defs": { "FilenameBehaviour": { "enum": [ "create-dir", "remove-path" ], "title": "FilenameBehaviour", "type": "string" } } }
- Fields:
- Validators:
- field common_properties: dict[str, Any] = {}
- field filename_behaviour: set[FilenameBehaviour] = {FilenameBehaviour.CreateDir}
- Validated by:
- field sco_labels: list[str] = []
- create_account_from_username(username: str | None, **stix_properties)
Create a User-Account from a string that may contain a username or both a username and a user ID
If the username is of the form “name(uid=digits)”, the uid is extracted and the resulting UserAccount will have both account_login and user_id set, otherwise account_login will be used.
Examples:
>>> h = StixHelper() >>> h.create_account_from_username('foo', custom_prop='bar') UserAccount(type='user-account', spec_version='2.1', id='user-account--234499e1-7802-5681-87df-a7667d8e3b6e', account_login='foo', defanged=False, custom_prop='bar') >>> h.create_account_from_username('foo(uid=1000)') UserAccount(type='user-account', spec_version='2.1', id='user-account--7d128e22-4162-5b1e-8df6-d6b8644c6949', user_id='1000', account_login='foo', defanged=False) >>> h.create_account_from_username(username=None,user_id='1000') UserAccount(type='user-account', spec_version='2.1', id='user-account--4b8a1e8e-e7c7-5c91-b832-b1bdad612c36', user_id='1000', defanged=False)
- create_addr_sco(address: str, **properties) IPv4Address | IPv6Address
Create either an IPv4Address or IPv6Address, depending on the address type
- create_file(names: list[str], *, sha256: str | None = None, **properties) SCOBundle
Create a STIX file
If sha256 is non-empty, it will be inserted into a hash object. If names contain more than one string, the first name will be used as “name”, and the rest will be used as x_opencti_additional_names.
If filename_behaviour contains CreateDir, a Directory object is created and referenced in parent_directory_ref. The path is extracted from the one of the filenames that contains a path. If filename_behaviour contains RemovePath, the path component of filenames will be removed.
Examples:
>>> h = StixHelper(filename_behaviour='') >>> h.create_file(names=['filename1', 'filename2']) SCOBundle(sco=File(type='file', spec_version='2.1', id='file--f83c036d-56f6-5246-8585-1616d42c7669', name='filename1', defanged=False, x_opencti_additional_names=['filename2']), nested_objs=[]) >>> h.create_file(names=['/tmp/filename1', '/filename2']) SCOBundle(sco=File(type='file', spec_version='2.1', id='file--09765542-1408-5026-8674-8128438fc940', name='/tmp/filename1', defanged=False, x_opencti_additional_names=['/filename2']), nested_objs=[]) >>> h = StixHelper(filename_behaviour='create-dir') >>> h.create_file(names=['/tmp/filename1', '/home/foo/Downloads/filename2']) SCOBundle(sco=File(type='file', spec_version='2.1', id='file--ed282b5e-3ebe-5d5f-81e3-d52b629abb46', name='/tmp/filename1', parent_directory_ref='directory--b7ed5105-3a80-559d-9bd6-ec208b6d813e', defanged=False, x_opencti_additional_names=['/home/foo/Downloads/filename2']), nested_objs=[Directory(type='directory', spec_version='2.1', id='directory--b7ed5105-3a80-559d-9bd6-ec208b6d813e', path='/home/foo/Downloads', defanged=False)]) >>> h = StixHelper(filename_behaviour='create-dir,remove-path') >>> h.create_file(names=['filename1', '/home/foo/Downloads/filename2']) SCOBundle(sco=File(type='file', spec_version='2.1', id='file--901c064f-7d08-5092-b84e-851f68c67a73', name='filename1', parent_directory_ref='directory--b7ed5105-3a80-559d-9bd6-ec208b6d813e', defanged=False, x_opencti_additional_names=['filename2']), nested_objs=[Directory(type='directory', spec_version='2.1', id='directory--b7ed5105-3a80-559d-9bd6-ec208b6d813e', path='/home/foo/Downloads', defanged=False)])
- create_sco(sco_type: str, value: str | None, **properties) SCOBundle
Create a SCO from its type name and properties
If value is None, properties must contain the observable value.
- create_tool(name: str)
- validator parse_behaviour_string » filename_behaviour