class _BaseTestMechanism(stix.Entity): _namespace = "http://stix.mitre.org/Indicator-2" _binding = indicator_binding _binding_class = indicator_binding.TestMechanismType() id_ = fields.IdField("id") idref = fields.IdField("idref") efficacy = fields.TypedField("Efficacy", Statement) producer = fields.TypedField("Producer", InformationSource) def __init__(self, id_=None, idref=None): super(_BaseTestMechanism, self).__init__() self.id_ = id_ self.idref = idref self.efficacy = None self.producer = None def to_obj(self, ns_info=None): obj = super(_BaseTestMechanism, self).to_obj(ns_info=ns_info) obj.xsi_type = self._XSI_TYPE return obj def to_dict(self): d = super(_BaseTestMechanism, self).to_dict() d['xsi:type'] = self._XSI_TYPE # added by subclass return d
class MarkingSpecification(stix.Entity): _binding = stix_data_marking_binding _binding_class = stix_data_marking_binding.MarkingSpecificationType _namespace = 'http://data-marking.mitre.org/Marking-1' id_ = fields.IdField("id") idref = fields.IdrefField("idref") version = fields.TypedField("version") controlled_structure = fields.TypedField("Controlled_Structure") marking_structures = fields.TypedField("Marking_Structure", MarkingStructure, factory=MarkingStructureFactory, multiple=True, key_name="marking_structures") information_source = fields.TypedField("Information_Source", InformationSource) def __init__(self, controlled_structure=None, marking_structures=None): super(MarkingSpecification, self).__init__() self.id_ = None self.idref = None self.version = None self.controlled_structure = controlled_structure self.marking_structures = marking_structures self.information_source = None
class Identity(stix.Entity): _binding = common_binding _binding_class = IdentityType _namespace = 'http://stix.mitre.org/common-1' id_ = fields.IdField("id") idref = fields.IdrefField("idref") name = fields.TypedField("Name") related_identities = fields.TypedField( "Related_Identities", type_="stix.common.identity.RelatedIdentities") def __init__(self, id_=None, idref=None, name=None, related_identities=None): super(Identity, self).__init__() self.id_ = id_ self.idref = idref self.name = name self.related_identities = related_identities def to_dict(self): d = super(Identity, self).to_dict() if self._XSI_TYPE: d['xsi:type'] = self._XSI_TYPE return d @staticmethod def lookup_class(xsi_type): return stix.lookup_extension(xsi_type, default=Identity)
class ToolInformation(entities.Entity): _binding = common_binding _binding_class = common_binding.ToolInformationType _namespace = 'http://cybox.mitre.org/common-2' id_ = fields.IdField("id") idref = fields.IdrefField("idref") name = fields.TypedField("Name") type_ = VocabField("Type", ToolType, multiple=True) description = fields.TypedField("Description", StructuredText) vendor = fields.TypedField("Vendor") version = fields.TypedField("Version") service_pack = fields.TypedField("Service_Pack") tool_hashes = fields.TypedField("Tool_Hashes", HashList) def __init__(self, tool_name=None, tool_vendor=None): super(ToolInformation, self).__init__() # TODO: Implement items commented out below. self.name = tool_name self.description = None #self.references = None self.vendor = tool_vendor self.version = None self.service_pack = None #self.tool_specific_data = None self.tool_hashes = None
class ToolInformation(entities.Entity): _binding = common_binding _binding_class = common_binding.ToolInformationType _namespace = 'http://cybox.mitre.org/common-2' id_ = fields.IdField("id") idref = fields.IdrefField("idref") name = fields.TypedField("Name") type_ = VocabField("Type", ToolType, multiple=True) description = fields.TypedField("Description", StructuredText) references = fields.TypedField("References", ToolReferences) vendor = fields.TypedField("Vendor") version = fields.TypedField("Version") service_pack = fields.TypedField("Service_Pack") tool_specific_data = fields.TypedField("Tool_Specific_Data", ToolSpecificData, factory=ToolSpecificDataFactory) tool_hashes = fields.TypedField("Tool_Hashes", HashList) tool_configuration = fields.TypedField("Tool_Configuration", ToolConfiguration) execution_environment = fields.TypedField("Execution_Environment", ExecutionEnvironment) errors = fields.TypedField("Errors", Errors) metadata = fields.TypedField("Metadata", Metadata, multiple=True) compensation_model = fields.TypedField("Compensation_Model", CompensationModel) def __init__(self, tool_name=None, tool_vendor=None): super(ToolInformation, self).__init__() self.name = tool_name self.vendor = tool_vendor
class MarkingStructure(stix.Entity): _binding = stix_data_marking_binding _binding_class = stix_data_marking_binding.MarkingStructureType _namespace = 'http://data-marking.mitre.org/Marking-1' _XSI_TYPE = None # overridden by subclasses id_ = fields.IdField("id") idref = fields.IdrefField("idref") marking_model_name = fields.TypedField("marking_model_name") marking_model_ref = fields.TypedField("marking_model_ref") def __init__(self): super(MarkingStructure, self).__init__() self.id_ = None self.idref = None self.marking_model_name = None self.marking_model_ref = None def to_dict(self): d = super(MarkingStructure, self).to_dict() if self._XSI_TYPE: d['xsi:type'] = self._XSI_TYPE return d @staticmethod def lookup_class(xsi_type): return stix.lookup_extension(xsi_type, default=MarkingStructure)
class Object(entities.Entity): """The CybOX Object element. Currently only supports the following data members: - id\_ - idref - properties - related_objects - domain specific object properties """ _binding = core_binding _binding_class = _binding.ObjectType _namespace = 'http://cybox.mitre.org/cybox-2' id_ = fields.IdField("id", postset_hook=_cache_object) idref = fields.IdrefField("idref") properties = fields.TypedField("Properties", ObjectProperties, factory=ObjectPropertiesFactory, postset_hook=_modify_properties_parent) related_objects = fields.TypedField("Related_Objects", "cybox.core.object.RelatedObjects") domain_specific_object_properties = fields.TypedField( "Domain_Specific_Object_Properties", "cybox.core.DomainSpecificObjectProperties", factory=ExternalTypeFactory) def __init__(self, properties=None, type_=None, id_=None, idref=None): super(Object, self).__init__() if properties: prefix = str(properties.__class__.__name__) else: prefix = "Object" self.id_ = id_ or idgen.create_id(prefix=prefix) self.idref = idref self.properties = properties self.related_objects = RelatedObjects() def __str__(self): if self.id_ is not None: return self.id_ elif self.idref is not None: return self.idref else: return super(Object, self).__repr__() def add_related(self, related, relationship, inline=True): if not isinstance(related, ObjectProperties): raise ValueError("Must be a ObjectProperties") r = RelatedObject(related, relationship=relationship, inline=inline) self.related_objects.append(r)
class _BaseStructuredCOA(stix.Entity): _namespace = "http://stix.mitre.org/CourseOfAction-1" _binding = coa_binding _binding_class = coa_binding.StructuredCOAType id_ = fields.IdField("id") idref = fields.IdrefField("idref") def __init__(self, id_=None, idref=None): super(_BaseStructuredCOA, self).__init__() self.id_ = id_ self.idref = idref def to_dict(self): d = super(_BaseStructuredCOA, self).to_dict() d['xsi:type'] = self._XSI_TYPE return d def to_obj(self, ns_info=None): obj = super(_BaseStructuredCOA, self).to_obj(ns_info=ns_info) obj.xsi_type = self._XSI_TYPE return obj
class Identity(stix.Entity): _binding = common_binding _namespace = 'http://stix.mitre.org/common-1' _binding_class = IdentityType id_ = fields.IdField("id") idref = fields.IdrefField("idref") name = fields.TypedField("Name") related_identities = fields.TypedField( "Related_Identities", type_="stix.common.identity.RelatedIdentities") def __init__(self, id_=None, idref=None, name=None, related_identities=None): super(Identity, self).__init__() self.id_ = id_ self.idref = idref self.name = name self.related_identities = related_identities
class AttackPattern(stix.Entity): _binding = ttp_binding _binding_class = _binding.AttackPatternType _namespace = "http://stix.mitre.org/TTP-1" id_ = fields.IdField("id") idref = fields.IdrefField("idref") title = fields.TypedField("Title") capec_id = fields.TypedField("capec_id") descriptions = fields.TypedField("Description", type_="stix.common.StructuredTextList") short_descriptions = fields.TypedField( "Short_Description", type_="stix.common.StructuredTextList") def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None): super(AttackPattern, self).__init__() self.id_ = id_ self.idref = idref self.title = title self.description = StructuredTextList(description) self.short_description = StructuredTextList(short_description) @property def description(self): """A single description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.descriptions is None: self.descriptions = StructuredTextList() return next(iter(self.descriptions), None) @description.setter def description(self, value): self.descriptions = value def add_description(self, description): """Adds a description to the ``descriptions`` collection. This is the same as calling "foo.descriptions.add(bar)". """ self.descriptions.add(description) @property def short_description(self): """A single short description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one short description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.short_descriptions is None: self.short_descriptions = StructuredTextList() return next(iter(self.short_descriptions), None) @short_description.setter def short_description(self, value): self.short_descriptions = value def add_short_description(self, description): """Adds a description to the ``short_descriptions`` collection. This is the same as calling "foo.short_descriptions.add(bar)". """ self.short_descriptions.add(description)
class Infrastructure(stix.Entity): _binding = ttp_binding _binding_class = _binding.InfrastructureType _namespace = "http://stix.mitre.org/TTP-1" id_ = fields.IdField("id") idref = fields.IdrefField("idref") title = fields.TypedField("Title") descriptions = fields.TypedField("Description", StructuredTextList) short_descriptions = fields.TypedField("Short_Description", StructuredTextList) types = fields.TypedField("Type", VocabString, multiple=True, key_name="types") observable_characterization = fields.TypedField( "Observable_Characterization", Observables) def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None): super(Infrastructure, self).__init__() self.id_ = id_ self.idref = idref self.title = title self.description = StructuredTextList(description) self.short_description = StructuredTextList(short_description) @property def description(self): """A single description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.descriptions is None: self.descriptions = StructuredTextList() return next(iter(self.descriptions), None) @description.setter def description(self, value): self.descriptions = StructuredTextList(value) def add_description(self, description): """Adds a description to the ``descriptions`` collection. This is the same as calling "foo.descriptions.add(bar)". """ self.descriptions.add(description) @property def short_description(self): """A single short description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one short description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.short_descriptions is None: self.short_descriptions = StructuredTextList() return next(iter(self.short_descriptions), None) @short_description.setter def short_description(self, value): self.short_descriptions = value def add_short_description(self, description): """Adds a description to the ``short_descriptions`` collection. This is the same as calling "foo.short_descriptions.add(bar)". """ self.short_descriptions.add(description) def add_type(self, type_): self.types.append(type_)
class BaseProperty(PatternFieldGroup, entities.Entity): __hash__ = entities.Entity.__hash__ # Most Properties are defined in the "common" binding, so we'll just set # that here. Some BaseProperty subclasses might have to override this. _binding = common_binding _binding_class = _binding.BaseObjectPropertyType _namespace = 'http://cybox.mitre.org/common-2' # If `True`, force the "datatype" attribute to be output. This is # necessary in some cases _force_datatype = False default_datatype = 'string' # BaseObjectProperty Group id_ = fields.IdField("id") idref = fields.IdrefField("idref") value = ListTypedField("valueOf_", key_name="value") datatype = fields.TypedField("datatype") appears_random = fields.TypedField("appears_random") is_obfuscated = fields.TypedField("is_obfuscated") obfuscation_algorithm_ref = fields.TypedField("obfuscation_algorithm_ref") is_defanged = fields.TypedField("is_defanged") defanging_algorithm_ref = fields.TypedField("defanging_algorithm_ref") refanging_transform_type = fields.TypedField("refanging_transform_type") refanging_transform = fields.TypedField("refanging_transform") observed_encoding = fields.TypedField("observed_encoding") def __init__(self, value=None): super(BaseProperty, self).__init__() self._force_datatype = False self.value = value self.datatype = self.default_datatype def __str__(self): return six.text_type(self.value) def __int__(self): return int(self.value) @property def serialized_value(self): return self.value @property def values(self): """Allow uniform access to `value` as a list. This allows code like the following to always work where `obj` is a CybOX entity and `prop` is any BaseProperty subclass: ``` for x in obj.prop.values(): do_something(x) ``` If `value` is None, this returns an empty list ([]) If `value` is a single non-list value, it returns a single-item list. If `value` is a list, `values` is identical to `value`. NOTE: This property cannot be set. Use the `value` setter for this. """ if self.value is None: return [] elif isinstance(self.value, list): return self.value else: return [self.value] def __eq__(self, other): # None-type checking if not other: return False # It is possible to compare a Property to a single value if # the Property defines only the "value" property. if not isinstance(other, BaseProperty) and self.is_plain(): return self.value == other return ( self.value == other.value and self.id_ == other.id_ and self.idref == other.idref and self.datatype == other.datatype and self.appears_random == other.appears_random and self.is_obfuscated == other.is_obfuscated and self.obfuscation_algorithm_ref == other.obfuscation_algorithm_ref and self.is_defanged == other.is_defanged and self.defanging_algorithm_ref == other.defanging_algorithm_ref and self.refanging_transform_type == other.refanging_transform_type and self.refanging_transform == other.refanging_transform and self.observed_encoding == other.observed_encoding and PatternFieldGroup._conditions_equal(self, other) and self.bit_mask == other.bit_mask and self.pattern_type == other.pattern_type and self.regex_syntax == other.regex_syntax and self.is_case_sensitive == other.is_case_sensitive and self.has_changed == other.has_changed and self.trend == other.trend ) def __ne__(self, other): return not self == other def is_plain(self): """Whether the Property can be represented as a single value. The `datatype` can be inferred by the particular BaseProperty subclass, so if `datatype` and `value` are the only non-None properties, the BaseProperty can be represented by a single value rather than a dictionary. This makes the JSON representation simpler without losing any data fidelity. """ return ( # ignore value self.id_ is None and self.idref is None and # ignore datatype self.appears_random is None and self.is_obfuscated is None and self.obfuscation_algorithm_ref is None and self.is_defanged is None and self.defanging_algorithm_ref is None and self.refanging_transform_type is None and self.refanging_transform is None and self.observed_encoding is None and super(BaseProperty, self).is_plain() ) def __nonzero__(self): return (not self.is_plain()) or (self.value is not None) __bool__ = __nonzero__ def _datatype_serialized_value(self): if self._force_datatype: return self.datatype elif self.datatype != self.default_datatype: return self.datatype else: return None def to_obj(self, ns_info=None): attr_obj = super(BaseProperty, self).to_obj(ns_info=ns_info) attr_obj.datatype = self._datatype_serialized_value() attr_obj.valueOf_ = normalize_to_xml(self.serialized_value, self.delimiter) return attr_obj def to_dict(self): if self.is_plain(): return self.serialized_value attr_dict = super(BaseProperty, self).to_dict() attr_dict.pop("datatype", None) if self._datatype_serialized_value(): attr_dict['datatype'] = self._datatype_serialized_value() if self.value is not None: attr_dict['value'] = self.serialized_value return attr_dict @classmethod def from_obj(cls, cls_obj): # Use the subclass this was called on to initialize the object if not cls_obj: return None # split delimited values now, before converting from bindings object to API object cls_obj.valueOf_ = denormalize_from_xml(cls_obj.valueOf_, cls_obj.delimiter) attr = super(BaseProperty, cls).from_obj(cls_obj) attr.datatype = cls_obj.datatype or cls.default_datatype return attr @classmethod def from_dict(cls, cls_dict): attr = super(BaseProperty, cls).from_dict(cls_dict) if isinstance(cls_dict, dict): attr.datatype = cls_dict.get('datatype', cls.default_datatype) return attr
class BaseCoreComponent(Entity): _ALL_VERSIONS = () _ID_PREFIX = None title = fields.TypedField("Title") id_ = fields.IdField("id") idref = fields.IdrefField("idref") descriptions = fields.TypedField( "Description", type_="stix.common.StructuredTextList", ) short_descriptions = fields.TypedField( "Short_Description", type_="stix.common.StructuredTextList") version = fields.TypedField("version", preset_hook=_validate_version) timestamp = fields.DateTimeField("timestamp") handling = fields.TypedField("Handling", type_="stix.data_marking.Marking") def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): from stix.common import StructuredTextList super(BaseCoreComponent, self).__init__() self.id_ = id_ or idgen.create_id(self._ID_PREFIX) self.idref = idref self.title = title self.descriptions = StructuredTextList(description) self.short_descriptions = StructuredTextList(short_description) if timestamp: self.timestamp = timestamp else: self.timestamp = utils.dates.now() if not idref else None @property def description(self): """A single description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ return next(iter(self.descriptions), None) @description.setter def description(self, value): self.descriptions = value def add_description(self, description): """Adds a description to the ``descriptions`` collection. This is the same as calling "foo.descriptions.add(bar)". """ self.descriptions.add(description) @property def short_description(self): """A single short description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one short description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ return next(iter(self.short_descriptions), None) @short_description.setter def short_description(self, value): self.short_descriptions = value def add_short_description(self, description): """Adds a description to the ``short_descriptions`` collection. This is the same as calling "foo.short_descriptions.add(bar)". """ self.short_descriptions.add(description)
class Observable(entities.Entity): """A single Observable. """ _binding = core_binding _binding_class = _binding.ObservableType _namespace = 'http://cybox.mitre.org/cybox-2' id_ = fields.IdField("id") idref = fields.IdrefField("idref") negate = fields.TypedField("negate") sighting_count = fields.TypedField("sighting_count") title = fields.TypedField("Title") description = fields.TypedField("Description", StructuredText) keywords = fields.TypedField("Keywords", Keywords) observable_source = fields.TypedField("Observable_Source", MeasureSource, multiple=True) object_ = fields.TypedField( "Object", Object, preset_hook=validate_object) # TODO: Add preset hook event = fields.TypedField("Event", Event, preset_hook=validate_event) observable_composition = fields.TypedField( "Observable_Composition", type_="cybox.core.ObservableComposition", preset_hook=validate_observable_composition) pattern_fidelity = fields.TypedField("Pattern_Fidelity", type_="cybox.core.PatternFidelity") def __init__(self, item=None, id_=None, idref=None, title=None, description=None): """Create an Observable out of 'item'. `item` can be any of: - an Object - an Event - an ObservableComposition - any subclass of ObjectProperties. In the first three cases, the appropriate property of the Observable will be set. In the last cases, an Object will be built automatically to ensure the correct hierarchy is created. """ super(Observable, self).__init__() self.id_ = id_ or idgen.create_id(prefix="Observable") self.idref = idref self.title = title self.description = description self.keywords = Keywords() if item is None: return elif isinstance(item, Object): self.object_ = item elif isinstance(item, ObservableComposition): self.observable_composition = item elif isinstance(item, Event): self.event = item elif isinstance(item, ObjectProperties): if item.parent: self.object_ = item.parent else: self.object_ = Object(item) else: msg = ("item must be an Object, Event, ObservableComposition, or " "subclass of ObjectProperties. Received an %s" % type(item)) raise TypeError(msg) def add_keyword(self, value): self.keywords.append(value)
class Report(stix.Entity): """A STIX Report Object. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. header: A Report :class:`.Header` object. campaigns: A collection of :class:`.Campaign` objects. course_of_action: A collection of :class:`.CourseOfAction` objects. exploit_targets: A collection of :class:`.ExploitTarget` objects. incidents: A collection of :class:`.Incident` objects. indicators: A collection of :class:`.Indicator` objects. threat_actors: A collection of :class:`.ThreatActor` objects. ttps: A collection of :class:`.TTP` objects. related_reports: A collection of :class:`.RelatedReport` objects. """ _binding = report_binding _binding_class = _binding.ReportType _namespace = 'http://stix.mitre.org/Report-1' _version = "1.0" id_ = fields.IdField("id") idref = fields.IdrefField("idref") timestamp = fields.TypedField("timestamp") version = fields.TypedField("version") header = fields.TypedField("Header", Header) campaigns = fields.TypedField("Campaigns", type_="stix.report.Campaigns") courses_of_action = fields.TypedField("Courses_Of_Action", type_="stix.report.CoursesOfAction") exploit_targets = fields.TypedField("Exploit_Targets", type_="stix.report.ExploitTargets") observables = fields.TypedField("Observables", Observables) indicators = fields.TypedField("Indicators", type_="stix.report.Indicators") incidents = fields.TypedField("Incidents", type_="stix.report.Incidents") threat_actors = fields.TypedField("Threat_Actors", type_="stix.report.ThreatActors") ttps = fields.TypedField("TTPs", type_="stix.core.ttps.TTPs") related_reports = fields.TypedField("Related_Reports", type_="stix.report.RelatedReports") def __init__(self, id_=None, idref=None, timestamp=None, header=None, courses_of_action=None, exploit_targets=None, indicators=None, observables=None, incidents=None, threat_actors=None, ttps=None, campaigns=None, related_reports=None): super(Report, self).__init__() self.id_ = id_ or idgen.create_id("Report") self.idref = idref self.version = self._version self.header = header self.campaigns = campaigns self.courses_of_action = courses_of_action self.exploit_targets = exploit_targets self.observables = observables self.indicators = indicators self.incidents = incidents self.threat_actors = threat_actors self.ttps = ttps self.related_reports = related_reports if timestamp: self.timestamp = timestamp else: self.timestamp = utils.dates.now() if not idref else None def add_indicator(self, indicator): """Adds an :class:`.Indicator` object to the :attr:`indicators` collection. """ if self.indicators is None: self.indicators = Indicators() self.indicators.append(indicator) def add_campaign(self, campaign): """Adds a :class:`Campaign` object to the :attr:`campaigns` collection. """ if self.campaigns is None: self.campaigns = Campaigns() self.campaigns.append(campaign) def add_observable(self, observable): """Adds an ``Observable`` object to the :attr:`observables` collection. If `observable` is not an ``Observable`` instance, an effort will be made to convert it to one. """ if not self.observables: self.observables = Observables(observables=observable) else: self.observables.add(observable) def add_incident(self, incident): """Adds an :class:`.Incident` object to the :attr:`incidents` collection. """ if self.incidents is None: self.incidents = Incidents() self.incidents.append(incident) def add_threat_actor(self, threat_actor): """Adds an :class:`.ThreatActor` object to the :attr:`threat_actors` collection. """ if self.threat_actors is None: self.threat_actors = ThreatActors() self.threat_actors.append(threat_actor) def add_course_of_action(self, course_of_action): """Adds an :class:`.CourseOfAction` object to the :attr:`courses_of_action` collection. """ if self.courses_of_action is None: self.courses_of_action = CoursesOfAction() self.courses_of_action.append(course_of_action) def add_exploit_target(self, exploit_target): """Adds an :class:`.ExploitTarget` object to the :attr:`exploit_targets` collection. """ if self.exploit_targets is None: self.exploit_targets = ExploitTargets() self.exploit_targets.append(exploit_target) def add_ttp(self, ttp): """Adds an :class:`.TTP` object to the :attr:`ttps` collection. """ if self.ttps is None: self.ttps = TTPs() self.ttps.append(ttp) def add_related_report(self, related_report): """Adds an :class:`.RelatedReport` object to the :attr:`related_reports` collection. """ if self.related_reports is None: self.related_reports = RelatedReports() self.related_reports.append(related_report) def add(self, entity): """Adds `entity` to a top-level collection. For example, if `entity` is an Indicator object, the `entity` will be added to the ``indicators`` top-level collection. """ if utils.is_cybox(entity): self.add_observable(entity) return tlo_adds = { Campaign: self.add_campaign, CourseOfAction: self.add_course_of_action, ExploitTarget: self.add_exploit_target, Incident: self.add_incident, Indicator: self.add_indicator, ThreatActor: self.add_threat_actor, TTP: self.add_ttp, Observable: self.add_observable, } try: add = tlo_adds[entity.__class__] add(entity) except KeyError: error = "Cannot add type '{0}' to a top-level collection" error = error.format(type(entity)) raise TypeError(error)
class Object(entities.Entity): """ The CybOX Object construct identifies and specifies the characteristics of a specific cyber-relevant object (e.g. a file, a registry key or a process). Currently only supports the following data members: - id\_ - idref - has_changed - description - properties - related_objects - domain_specific_object_properties Notes: By default ``cybox.core.object.Object`` will cache objects when instantiated. If your are experiencing memory issues in your environment, we encourage the use of ``cybox.utils.caches.cache_clear()`` in your script to prevent an Out of Memory error. Depending on your use case, it can be after serialization or if a certain threshold is met (e.g. %30 of memory consumed by cache mechanism). """ _binding = core_binding _binding_class = _binding.ObjectType _namespace = 'http://cybox.mitre.org/cybox-2' id_ = fields.IdField("id", postset_hook=_cache_object) idref = fields.IdrefField("idref") has_changed = fields.TypedField("has_changed") state = VocabField("State") description = fields.TypedField("Description", StructuredText) properties = fields.TypedField("Properties", ObjectProperties, factory=ObjectPropertiesFactory, postset_hook=_modify_properties_parent) domain_specific_object_properties = fields.TypedField( "Domain_Specific_Object_Properties", "cybox.core.object.DomainSpecificObjectProperties", factory=ExternalTypeFactory) related_objects = fields.TypedField("Related_Objects", "cybox.core.object.RelatedObjects") def __init__(self, properties=None, id_=None, idref=None): super(Object, self).__init__() if properties: prefix = str(properties.__class__.__name__) else: prefix = "Object" self.id_ = id_ or idgen.create_id(prefix=prefix) self.idref = idref self.properties = properties self.related_objects = RelatedObjects() def __str__(self): if self.id_ is not None: return self.id_ elif self.idref is not None: return self.idref else: return super(Object, self).__repr__() def add_related(self, related, relationship, inline=True): if not isinstance(related, ObjectProperties): raise ValueError("Must be a ObjectProperties") r = RelatedObject(related, relationship=relationship, inline=inline) self.related_objects.append(r)
class MalwareInstance(stix.Entity): _binding = ttp_binding _binding_class = _binding.MalwareInstanceType _namespace = "http://stix.mitre.org/TTP-1" _XSI_TYPE = None # defined by subclasses id_ = fields.IdField("id") idref = fields.IdrefField("idref") title = fields.TypedField("Title") descriptions = fields.TypedField("Description", type_="stix.common.StructuredTextList") short_descriptions = fields.TypedField( "Short_Description", type_="stix.common.StructuredTextList") names = vocabs.VocabField("Name", type_=VocabString, multiple=True, key_name="names") types = vocabs.VocabField("Type", type_=vocabs.MalwareType, multiple=True, key_name="types") def __init__(self, id_=None, idref=None, title=None, description=None, short_description=None): super(MalwareInstance, self).__init__() self.id_ = id_ self.idref = idref self.title = title self.description = StructuredTextList(description) self.short_description = StructuredTextList(short_description) @property def description(self): """A single description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.descriptions is None: self.descriptions = StructuredTextList() return next(iter(self.descriptions), None) @description.setter def description(self, value): self.descriptions = value def add_description(self, description): """Adds a description to the ``descriptions`` collection. This is the same as calling "foo.descriptions.add(bar)". """ self.descriptions.add(description) @property def short_description(self): """A single short description about the contents or purpose of this object. Default Value: ``None`` Note: If this object has more than one short description set, this will return the description with the lowest ordinality value. Returns: An instance of :class:`.StructuredText` """ if self.short_descriptions is None: self.short_descriptions = [] return next(iter(self.short_descriptions), None) @short_description.setter def short_description(self, value): self.short_descriptions = value def add_short_description(self, description): """Adds a description to the ``short_descriptions`` collection. This is the same as calling "foo.short_descriptions.add(bar)". """ self.short_descriptions.add(description) def add_name(self, name): self.names.append(name) def add_type(self, type_): self.types.append(type_) @staticmethod def lookup_class(xsi_type): if not xsi_type: raise ValueError("xsi:type is required") return stix.lookup_extension(xsi_type)
class StructuredText(stix.Entity): """Used for storing descriptive text elements. Attributes: id_: An id for the text element, typically used for controlled structure xpath selectors. value: The text value of this object. structuring_format: The format of the text. For example, ``html5``. """ _binding = stix_common_binding _binding_class = _binding.StructuredTextType _namespace = 'http://stix.mitre.org/common-1' id_ = fields.IdField("id") ordinality = fields.TypedField("ordinality") value = fields.TypedField("valueOf_", key_name="value") structuring_format = fields.TypedField("structuring_format") def __init__(self, value=None, ordinality=None): super(StructuredText, self).__init__() self.id_ = None self.value = value self.structuring_format = None self.ordinality = ordinality def is_plain(self): plain = ((not self.id_) and (not self.structuring_format) and (self.ordinality is None)) return plain def to_dict(self): """Converts this object into a dictionary representation. Note: If no properies or attributes are set other than ``value``, this will return a string. """ # Return a plain string if there is no format specified. if self.is_plain(): return self.value else: return super(StructuredText, self).to_dict() def __str__(self): """Returns a UTF-8 encoded string representation of the ``value``. """ if version_info < (3, ): return self.__unicode__().encode("utf-8") else: return self.__unicode__() def __unicode__(self): """Returns a ``unicode`` string representation of the ``value``. """ return text_type(self.value)
class STIXPackage(stix.Entity): """A STIX Package object. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref: **DEPRECATED** An identifier reference. If set this will unset the ``id_`` property. timestamp: **DEPRECATED** A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. header: A Report :class:`.Header` object. campaigns: A collection of :class:`.Campaign` objects. course_of_action: A collection of :class:`.CourseOfAction` objects. exploit_targets: A collection of :class:`.ExploitTarget` objects. incidents: A collection of :class:`.Incident` objects. indicators: A collection of :class:`.Indicator` objects. threat_actors: A collection of :class:`.ThreatActor` objects. ttps: A collection of :class:`.TTP` objects. related_packages: **DEPRECATED**. A collection of :class:`.RelatedPackage` objects. reports: A collection of :class:`.Report` objects. """ _binding = stix_core_binding _binding_class = _binding.STIXType _namespace = 'http://stix.mitre.org/stix-1' _version = "1.2" _ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1", "1.2") id_ = fields.IdField("id") idref = fields.IdrefField("idref", preset_hook=deprecated.field) version = fields.TypedField("version") timestamp = fields.DateTimeField("timestamp", preset_hook=deprecated.field) stix_header = fields.TypedField("STIX_Header", STIXHeader) campaigns = fields.TypedField("Campaigns", Campaigns) courses_of_action = fields.TypedField("Courses_Of_Action", CoursesOfAction) exploit_targets = fields.TypedField("Exploit_Targets", ExploitTargets) observables = fields.TypedField("Observables", Observables) indicators = fields.TypedField("Indicators", Indicators) incidents = fields.TypedField("Incidents", Incidents) threat_actors = fields.TypedField("Threat_Actors", ThreatActors) ttps = fields.TypedField("TTPs", TTPs) related_packages = fields.TypedField("Related_Packages", RelatedPackages) reports = fields.TypedField("Reports", Reports) def __init__(self, id_=None, idref=None, timestamp=None, stix_header=None, courses_of_action=None, exploit_targets=None, indicators=None, observables=None, incidents=None, threat_actors=None, ttps=None, campaigns=None, related_packages=None, reports=None): super(STIXPackage, self).__init__() self.id_ = id_ or idgen.create_id("Package") self.idref = idref self.version = STIXPackage._version self.stix_header = stix_header self.campaigns = campaigns or Campaigns() self.courses_of_action = courses_of_action or CoursesOfAction() self.exploit_targets = exploit_targets or ExploitTargets() self.observables = observables or Observables() self.indicators = indicators or Indicators() self.incidents = incidents or Incidents() self.threat_actors = threat_actors or ThreatActors() self.ttps = ttps or TTPs() self.related_packages = related_packages self.reports = reports or Reports() self.timestamp = timestamp def add_indicator(self, indicator): """Adds an :class:`.Indicator` object to the :attr:`indicators` collection. """ if self.indicators is None: self.indicators = Indicators() self.indicators.append(indicator) def add_campaign(self, campaign): """Adds a :class:`Campaign` object to the :attr:`campaigns` collection. """ if self.campaigns is None: self.campaigns = Campaigns() self.campaigns.append(campaign) def add_observable(self, observable): """Adds an ``Observable`` object to the :attr:`observables` collection. If `observable` is not an ``Observable`` instance, an effort will be made to convert it to one. """ if not self.observables: self.observables = Observables(observables=observable) else: self.observables.add(observable) def add_incident(self, incident): """Adds an :class:`.Incident` object to the :attr:`incidents` collection. """ if self.incidents is None: self.incidents = Incidents() self.incidents.append(incident) def add_threat_actor(self, threat_actor): """Adds an :class:`.ThreatActor` object to the :attr:`threat_actors` collection. """ if self.threat_actors is None: self.threat_actors = ThreatActors() self.threat_actors.append(threat_actor) def add_course_of_action(self, course_of_action): """Adds an :class:`.CourseOfAction` object to the :attr:`courses_of_action` collection. """ if self.courses_of_action is None: self.courses_of_action = CoursesOfAction() self.courses_of_action.append(course_of_action) def add_exploit_target(self, exploit_target): """Adds an :class:`.ExploitTarget` object to the :attr:`exploit_targets` collection. """ if self.exploit_targets is None: self.exploit_targets = ExploitTargets() self.exploit_targets.append(exploit_target) def add_ttp(self, ttp): """Adds an :class:`.TTP` object to the :attr:`ttps` collection. """ if self.ttps is None: self.ttps = TTPs() self.ttps.ttp.append(ttp) def add_report(self, report): """Adds a :class:`.Report` object to the :attr:`reports` collection. """ if self.reports is None: self.reports = Reports() self.reports.append(report) def add_related_package(self, related_package): """Adds a :class:`.RelatedPackage` object to the :attr:`related_packages` collection. """ if self.related_packages is None: self.related_packages = RelatedPackages() self.related_packages.append(related_package) def add(self, entity): """Adds `entity` to a top-level collection. For example, if `entity` is an Indicator object, the `entity` will be added to the ``indicators`` top-level collection. """ if utils.is_cybox(entity): self.add_observable(entity) return tlo_adds = { Campaign: self.add_campaign, CourseOfAction: self.add_course_of_action, ExploitTarget: self.add_exploit_target, Incident: self.add_incident, Indicator: self.add_indicator, ThreatActor: self.add_threat_actor, TTP: self.add_ttp, Report: self.add_report, Observable: self.add_observable, } try: add = tlo_adds[entity.__class__] add(entity) except KeyError: error = "Cannot add type '{0}' to a top-level collection" error = error.format(type(entity)) raise TypeError(error) @classmethod def from_xml(cls, xml_file, encoding=None): """Parses the `xml_file` file-like object and returns a :class:`STIXPackage` instance. Args: xml_file: A file, file-like object, etree._Element, or etree._ElementTree instance. encoding: The character encoding of the `xml_file` input. If ``None``, an attempt will be made to determine the input character encoding. Default is ``None``. Returns: An instance of :class:`STIXPackage`. """ entity_parser = parser.EntityParser() return entity_parser.parse_xml(xml_file, encoding=encoding)