Example #1
0
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)
Example #2
0
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)
Example #3
0
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
Example #4
0
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
Example #5
0
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
Example #6
0
class Location(entities.Entity):
    _binding = common_binding
    _binding_class = common_binding.LocationType
    _namespace = 'http://cybox.mitre.org/common-2'
    _XSI_TYPE = None  # overridden by subclasses

    id_ = fields.IdrefField("id")
    idref = fields.IdrefField("idref")
    name = fields.TypedField("Name")

    def to_dict(self):
        d = super(Location, self).to_dict()

        if self._XSI_TYPE:
            d["xsi:type"] = self._XSI_TYPE

        return d
Example #7
0
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)
Example #8
0
class RelatedPackageRef(GenericRelationship):
    _namespace = "http://stix.mitre.org/common-1"
    _binding = common_binding
    _binding_class = common_binding.RelatedPackageRefType

    idref = fields.IdrefField("idref")
    timestamp = fields.DateTimeField("timestamp")

    def __init__(self, idref=None, timestamp=None, confidence=None,
                 information_source=None, relationship=None):

        super(RelatedPackageRef, self).__init__(
            confidence=confidence,
            information_source=information_source,
            relationship=relationship
        )

        self.idref = idref
        self.timestamp = timestamp
Example #9
0
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
Example #10
0
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 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)
Example #12
0
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)
Example #13
0
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_)
Example #14
0
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)
Example #15
0
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)
Example #16
0
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
Example #17
0
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)
Example #18
0
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)
Example #19
0
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)