587 lines
20 KiB
Python
587 lines
20 KiB
Python
"""STIX 2.0 Cyber Observable Objects
|
|
|
|
Embedded observable object types, such as Email MIME Component, which is
|
|
embedded in Email Message objects, inherit from _STIXBase instead of Observable
|
|
and do not have a '_type' attribute.
|
|
"""
|
|
|
|
from .base import _Extension, _Observable, _STIXBase
|
|
from .exceptions import AtLeastOnePropertyError
|
|
from .properties import (BinaryProperty, BooleanProperty, DictionaryProperty,
|
|
EmbeddedObjectProperty, EnumProperty,
|
|
ExtensionsProperty, FloatProperty, HashesProperty,
|
|
HexProperty, IntegerProperty, ListProperty,
|
|
ObjectReferenceProperty, StringProperty,
|
|
TimestampProperty, TypeProperty)
|
|
|
|
|
|
class Artifact(_Observable):
|
|
_type = 'artifact'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'mime_type': StringProperty(),
|
|
'payload_bin': BinaryProperty(),
|
|
'url': StringProperty(),
|
|
'hashes': HashesProperty(),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(Artifact, self)._check_object_constraints()
|
|
self._check_mutually_exclusive_properties(["payload_bin", "url"])
|
|
self._check_properties_dependency(["hashes"], ["url"])
|
|
|
|
|
|
class AutonomousSystem(_Observable):
|
|
_type = 'autonomous-system'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'number': IntegerProperty(),
|
|
'name': StringProperty(),
|
|
'rir': StringProperty(),
|
|
}
|
|
|
|
|
|
class Directory(_Observable):
|
|
_type = 'directory'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'path': StringProperty(required=True),
|
|
'path_enc': StringProperty(),
|
|
# these are not the created/modified timestamps of the object itself
|
|
'created': TimestampProperty(),
|
|
'modified': TimestampProperty(),
|
|
'accessed': TimestampProperty(),
|
|
'contains_refs': ListProperty(ObjectReferenceProperty(valid_types=['file', 'directory'])),
|
|
}
|
|
|
|
|
|
class DomainName(_Observable):
|
|
_type = 'domain-name'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
'resolves_to_refs': ListProperty(ObjectReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'domain-name'])),
|
|
}
|
|
|
|
|
|
class EmailAddress(_Observable):
|
|
_type = 'email-address'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
'display_name': StringProperty(),
|
|
'belongs_to_ref': ObjectReferenceProperty(valid_types='user-account'),
|
|
}
|
|
|
|
|
|
class EmailMIMEComponent(_STIXBase):
|
|
_properties = {
|
|
'body': StringProperty(),
|
|
'body_raw_ref': ObjectReferenceProperty(valid_types=['artifact', 'file']),
|
|
'content_type': StringProperty(),
|
|
'content_disposition': StringProperty(),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(EmailMIMEComponent, self)._check_object_constraints()
|
|
self._check_at_least_one_property(["body", "body_raw_ref"])
|
|
|
|
|
|
class EmailMessage(_Observable):
|
|
_type = 'email-message'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'is_multipart': BooleanProperty(required=True),
|
|
'date': TimestampProperty(),
|
|
'content_type': StringProperty(),
|
|
'from_ref': ObjectReferenceProperty(valid_types='email-addr'),
|
|
'sender_ref': ObjectReferenceProperty(valid_types='email-addr'),
|
|
'to_refs': ListProperty(ObjectReferenceProperty(valid_types='email-addr')),
|
|
'cc_refs': ListProperty(ObjectReferenceProperty(valid_types='email-addr')),
|
|
'bcc_refs': ListProperty(ObjectReferenceProperty(valid_types='email-addr')),
|
|
'subject': StringProperty(),
|
|
'received_lines': ListProperty(StringProperty),
|
|
'additional_header_fields': DictionaryProperty(),
|
|
'body': StringProperty(),
|
|
'body_multipart': ListProperty(EmbeddedObjectProperty(type=EmailMIMEComponent)),
|
|
'raw_email_ref': ObjectReferenceProperty(valid_types='artifact'),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(EmailMessage, self)._check_object_constraints()
|
|
self._check_properties_dependency(["is_multipart"], ["body_multipart"])
|
|
# self._dependency(["is_multipart"], ["body"], [False])
|
|
|
|
|
|
class ArchiveExt(_Extension):
|
|
_properties = {
|
|
'contains_refs': ListProperty(ObjectReferenceProperty(valid_types='file'), required=True),
|
|
'version': StringProperty(),
|
|
'comment': StringProperty(),
|
|
}
|
|
|
|
|
|
class AlternateDataStream(_STIXBase):
|
|
_properties = {
|
|
'name': StringProperty(required=True),
|
|
'hashes': HashesProperty(),
|
|
'size': IntegerProperty(),
|
|
}
|
|
|
|
|
|
class NTFSExt(_Extension):
|
|
_properties = {
|
|
'sid': StringProperty(),
|
|
'alternate_data_streams': ListProperty(EmbeddedObjectProperty(type=AlternateDataStream)),
|
|
}
|
|
|
|
|
|
class PDFExt(_Extension):
|
|
_properties = {
|
|
'version': StringProperty(),
|
|
'is_optimized': BooleanProperty(),
|
|
'document_info_dict': DictionaryProperty(),
|
|
'pdfid0': StringProperty(),
|
|
'pdfid1': StringProperty(),
|
|
}
|
|
|
|
|
|
class RasterImageExt(_Extension):
|
|
_properties = {
|
|
'image_height': IntegerProperty(),
|
|
'image_weight': IntegerProperty(),
|
|
'bits_per_pixel': IntegerProperty(),
|
|
'image_compression_algorithm': StringProperty(),
|
|
'exif_tags': DictionaryProperty(),
|
|
}
|
|
|
|
|
|
class WindowsPEOptionalHeaderType(_STIXBase):
|
|
_properties = {
|
|
'magic_hex': HexProperty(),
|
|
'major_linker_version': IntegerProperty(),
|
|
'minor_linker_version': IntegerProperty(),
|
|
'size_of_code': IntegerProperty(),
|
|
'size_of_initialized_data': IntegerProperty(),
|
|
'size_of_uninitialized_data': IntegerProperty(),
|
|
'address_of_entry_point': IntegerProperty(),
|
|
'base_of_code': IntegerProperty(),
|
|
'base_of_data': IntegerProperty(),
|
|
'image_base': IntegerProperty(),
|
|
'section_alignment': IntegerProperty(),
|
|
'file_alignment': IntegerProperty(),
|
|
'major_os_version': IntegerProperty(),
|
|
'minor_os_version': IntegerProperty(),
|
|
'major_image_version': IntegerProperty(),
|
|
'minor_image_version': IntegerProperty(),
|
|
'major_subsystem_version': IntegerProperty(),
|
|
'minor_subsystem_version': IntegerProperty(),
|
|
'win32_version_value_hex': HexProperty(),
|
|
'size_of_image': IntegerProperty(),
|
|
'size_of_headers': IntegerProperty(),
|
|
'checksum_hex': HexProperty(),
|
|
'subsystem_hex': HexProperty(),
|
|
'dll_characteristics_hex': HexProperty(),
|
|
'size_of_stack_reserve': IntegerProperty(),
|
|
'size_of_stack_commit': IntegerProperty(),
|
|
'size_of_heap_reserve': IntegerProperty(),
|
|
'size_of_heap_commit': IntegerProperty(),
|
|
'loader_flags_hex': HexProperty(),
|
|
'number_of_rva_and_sizes': IntegerProperty(),
|
|
'hashes': HashesProperty(),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(WindowsPEOptionalHeaderType, self)._check_object_constraints()
|
|
self._check_at_least_one_property()
|
|
|
|
|
|
class WindowsPESection(_STIXBase):
|
|
_properties = {
|
|
'name': StringProperty(required=True),
|
|
'size': IntegerProperty(),
|
|
'entropy': FloatProperty(),
|
|
'hashes': HashesProperty(),
|
|
}
|
|
|
|
|
|
class WindowsPEBinaryExt(_Extension):
|
|
_properties = {
|
|
'pe_type': StringProperty(required=True), # open_vocab
|
|
'imphash': StringProperty(),
|
|
'machine_hex': HexProperty(),
|
|
'number_of_sections': IntegerProperty(),
|
|
'time_date_stamp': TimestampProperty(),
|
|
'pointer_to_symbol_table_hex': HexProperty(),
|
|
'number_of_symbols': IntegerProperty(),
|
|
'size_of_optional_header': IntegerProperty(),
|
|
'characteristics_hex': HexProperty(),
|
|
'file_header_hashes': HashesProperty(),
|
|
'optional_header': EmbeddedObjectProperty(type=WindowsPEOptionalHeaderType),
|
|
'sections': ListProperty(EmbeddedObjectProperty(type=WindowsPESection)),
|
|
}
|
|
|
|
|
|
class File(_Observable):
|
|
_type = 'file'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'extensions': ExtensionsProperty(enclosing_type=_type),
|
|
'hashes': HashesProperty(),
|
|
'size': IntegerProperty(),
|
|
'name': StringProperty(),
|
|
'name_enc': StringProperty(),
|
|
'magic_number_hex': HexProperty(),
|
|
'mime_type': StringProperty(),
|
|
# these are not the created/modified timestamps of the object itself
|
|
'created': TimestampProperty(),
|
|
'modified': TimestampProperty(),
|
|
'accessed': TimestampProperty(),
|
|
'parent_directory_ref': ObjectReferenceProperty(valid_types='directory'),
|
|
'is_encrypted': BooleanProperty(),
|
|
'encryption_algorithm': StringProperty(),
|
|
'decryption_key': StringProperty(),
|
|
'contains_refs': ListProperty(ObjectReferenceProperty),
|
|
'content_ref': ObjectReferenceProperty(valid_types='artifact'),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(File, self)._check_object_constraints()
|
|
self._check_properties_dependency(["is_encrypted"], ["encryption_algorithm", "decryption_key"])
|
|
self._check_at_least_one_property(["hashes", "name"])
|
|
|
|
|
|
class IPv4Address(_Observable):
|
|
_type = 'ipv4-addr'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
'resolves_to_refs': ListProperty(ObjectReferenceProperty(valid_types='mac-addr')),
|
|
'belongs_to_refs': ListProperty(ObjectReferenceProperty(valid_types='autonomous-system')),
|
|
}
|
|
|
|
|
|
class IPv6Address(_Observable):
|
|
_type = 'ipv6-addr'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
'resolves_to_refs': ListProperty(ObjectReferenceProperty(valid_types='mac-addr')),
|
|
'belongs_to_refs': ListProperty(ObjectReferenceProperty(valid_types='autonomous-system')),
|
|
}
|
|
|
|
|
|
class MACAddress(_Observable):
|
|
_type = 'mac-addr'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
}
|
|
|
|
|
|
class Mutex(_Observable):
|
|
_type = 'mutex'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'name': StringProperty(),
|
|
}
|
|
|
|
|
|
class HTTPRequestExt(_Extension):
|
|
_properties = {
|
|
'request_method': StringProperty(required=True),
|
|
'request_value': StringProperty(required=True),
|
|
'request_version': StringProperty(),
|
|
'request_header': DictionaryProperty(),
|
|
'message_body_length': IntegerProperty(),
|
|
'message_body_data_ref': ObjectReferenceProperty(valid_types='artifact'),
|
|
}
|
|
|
|
|
|
class ICMPExt(_Extension):
|
|
_properties = {
|
|
'icmp_type_hex': HexProperty(required=True),
|
|
'icmp_code_hex': HexProperty(required=True),
|
|
}
|
|
|
|
|
|
class SocketExt(_Extension):
|
|
_properties = {
|
|
'address_family': EnumProperty([
|
|
"AF_UNSPEC",
|
|
"AF_INET",
|
|
"AF_IPX",
|
|
"AF_APPLETALK",
|
|
"AF_NETBIOS",
|
|
"AF_INET6",
|
|
"AF_IRDA",
|
|
"AF_BTH",
|
|
], required=True),
|
|
'is_blocking': BooleanProperty(),
|
|
'is_listening': BooleanProperty(),
|
|
'protocol_family': EnumProperty([
|
|
"PF_INET",
|
|
"PF_IPX",
|
|
"PF_APPLETALK",
|
|
"PF_INET6",
|
|
"PF_AX25",
|
|
"PF_NETROM"
|
|
]),
|
|
'options': DictionaryProperty(),
|
|
'socket_type': EnumProperty([
|
|
"SOCK_STREAM",
|
|
"SOCK_DGRAM",
|
|
"SOCK_RAW",
|
|
"SOCK_RDM",
|
|
"SOCK_SEQPACKET",
|
|
]),
|
|
}
|
|
|
|
|
|
class TCPExt(_Extension):
|
|
_properties = {
|
|
'src_flags_hex': HexProperty(),
|
|
'dst_flags_hex': HexProperty(),
|
|
}
|
|
|
|
|
|
class NetworkTraffic(_Observable):
|
|
_type = 'network-traffic'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'extensions': ExtensionsProperty(enclosing_type=_type),
|
|
'start': TimestampProperty(),
|
|
'end': TimestampProperty(),
|
|
'is_active': BooleanProperty(),
|
|
'src_ref': ObjectReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'mac-addr', 'domain-name']),
|
|
'dst_ref': ObjectReferenceProperty(valid_types=['ipv4-addr', 'ipv6-addr', 'mac-addr', 'domain-name']),
|
|
'src_port': IntegerProperty(),
|
|
'dst_port': IntegerProperty(),
|
|
'protocols': ListProperty(StringProperty, required=True),
|
|
'src_byte_count': IntegerProperty(),
|
|
'dst_byte_count': IntegerProperty(),
|
|
'src_packets': IntegerProperty(),
|
|
'dst_packets': IntegerProperty(),
|
|
'ipfix': DictionaryProperty(),
|
|
'src_payload_ref': ObjectReferenceProperty(valid_types='artifact'),
|
|
'dst_payload_ref': ObjectReferenceProperty(valid_types='artifact'),
|
|
'encapsulates_refs': ListProperty(ObjectReferenceProperty(valid_types='network-traffic')),
|
|
'encapsulates_by_ref': ObjectReferenceProperty(valid_types='network-traffic'),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
super(NetworkTraffic, self)._check_object_constraints()
|
|
self._check_at_least_one_property(["src_ref", "dst_ref"])
|
|
|
|
|
|
class WindowsProcessExt(_Extension):
|
|
_properties = {
|
|
'aslr_enabled': BooleanProperty(),
|
|
'dep_enabled': BooleanProperty(),
|
|
'priority': StringProperty(),
|
|
'owner_sid': StringProperty(),
|
|
'window_title': StringProperty(),
|
|
'startup_info': DictionaryProperty(),
|
|
}
|
|
|
|
|
|
class WindowsServiceExt(_Extension):
|
|
_properties = {
|
|
'service_name': StringProperty(required=True),
|
|
'descriptions': ListProperty(StringProperty),
|
|
'display_name': StringProperty(),
|
|
'group_name': StringProperty(),
|
|
'start_type': EnumProperty([
|
|
"SERVICE_AUTO_START",
|
|
"SERVICE_BOOT_START",
|
|
"SERVICE_DEMAND_START",
|
|
"SERVICE_DISABLED",
|
|
"SERVICE_SYSTEM_ALERT",
|
|
]),
|
|
'service_dll_refs': ListProperty(ObjectReferenceProperty(valid_types='file')),
|
|
'service_type': EnumProperty([
|
|
"SERVICE_KERNEL_DRIVER",
|
|
"SERVICE_FILE_SYSTEM_DRIVER",
|
|
"SERVICE_WIN32_OWN_PROCESS",
|
|
"SERVICE_WIN32_SHARE_PROCESS",
|
|
]),
|
|
'service_status': EnumProperty([
|
|
"SERVICE_CONTINUE_PENDING",
|
|
"SERVICE_PAUSE_PENDING",
|
|
"SERVICE_PAUSED",
|
|
"SERVICE_RUNNING",
|
|
"SERVICE_START_PENDING",
|
|
"SERVICE_STOP_PENDING",
|
|
"SERVICE_STOPPED",
|
|
]),
|
|
}
|
|
|
|
|
|
class Process(_Observable):
|
|
_type = 'process'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'extensions': ExtensionsProperty(enclosing_type=_type),
|
|
'is_hidden': BooleanProperty(),
|
|
'pid': IntegerProperty(),
|
|
'name': StringProperty(),
|
|
# this is not the created timestamps of the object itself
|
|
'created': TimestampProperty(),
|
|
'cwd': StringProperty(),
|
|
'arguments': ListProperty(StringProperty),
|
|
'command_line': StringProperty(),
|
|
'environment_variables': DictionaryProperty(),
|
|
'opened_connection_refs': ListProperty(ObjectReferenceProperty(valid_types='network-traffic')),
|
|
'creator_user_ref': ObjectReferenceProperty(valid_types='user-account'),
|
|
'binary_ref': ObjectReferenceProperty(valid_types='file'),
|
|
'parent_ref': ObjectReferenceProperty(valid_types='process'),
|
|
'child_refs': ListProperty(ObjectReferenceProperty('process')),
|
|
}
|
|
|
|
def _check_object_constraints(self):
|
|
# no need to check windows-service-ext, since it has a required property
|
|
super(Process, self)._check_object_constraints()
|
|
try:
|
|
self._check_at_least_one_property()
|
|
if hasattr(self, 'extensions') and "windows-process-ext" in self.extensions:
|
|
self.extensions["windows-process-ext"]._check_at_least_one_property()
|
|
except AtLeastOnePropertyError as enclosing_exc:
|
|
if not hasattr(self, 'extensions'):
|
|
raise enclosing_exc
|
|
else:
|
|
if "windows-process-ext" in self.extensions:
|
|
self.extensions["windows-process-ext"]._check_at_least_one_property()
|
|
|
|
|
|
class Software(_Observable):
|
|
_type = 'software'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'name': StringProperty(required=True),
|
|
'cpe': StringProperty(),
|
|
'languages': ListProperty(StringProperty),
|
|
'vendor': StringProperty(),
|
|
'version': StringProperty(),
|
|
}
|
|
|
|
|
|
class URL(_Observable):
|
|
_type = 'url'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'value': StringProperty(required=True),
|
|
}
|
|
|
|
|
|
class UNIXAccountExt(_Extension):
|
|
_properties = {
|
|
'gid': IntegerProperty(),
|
|
'groups': ListProperty(StringProperty),
|
|
'home_dir': StringProperty(),
|
|
'shell': StringProperty(),
|
|
}
|
|
|
|
|
|
class UserAccount(_Observable):
|
|
_type = 'user-account'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'extensions': ExtensionsProperty(enclosing_type=_type),
|
|
'user_id': StringProperty(required=True),
|
|
'account_login': StringProperty(),
|
|
'account_type': StringProperty(), # open vocab
|
|
'display_name': StringProperty(),
|
|
'is_service_account': BooleanProperty(),
|
|
'is_privileged': BooleanProperty(),
|
|
'can_escalate_privs': BooleanProperty(),
|
|
'is_disabled': BooleanProperty(),
|
|
'account_created': TimestampProperty(),
|
|
'account_expires': TimestampProperty(),
|
|
'password_last_changed': TimestampProperty(),
|
|
'account_first_login': TimestampProperty(),
|
|
'account_last_login': TimestampProperty(),
|
|
}
|
|
|
|
|
|
class WindowsRegistryValueType(_STIXBase):
|
|
_type = 'windows-registry-value-type'
|
|
_properties = {
|
|
'name': StringProperty(required=True),
|
|
'data': StringProperty(),
|
|
'data_type': EnumProperty([
|
|
'REG_NONE',
|
|
'REG_SZ',
|
|
'REG_EXPAND_SZ',
|
|
'REG_BINARY',
|
|
'REG_DWORD',
|
|
'REG_DWORD_BIG_ENDIAN',
|
|
'REG_LINK',
|
|
'REG_MULTI_SZ',
|
|
'REG_RESOURCE_LIST',
|
|
'REG_FULL_RESOURCE_DESCRIPTION',
|
|
'REG_RESOURCE_REQUIREMENTS_LIST',
|
|
'REG_QWORD',
|
|
'REG_INVALID_TYPE',
|
|
]),
|
|
}
|
|
|
|
|
|
class WindowsRegistryKey(_Observable):
|
|
_type = 'windows-registry-key'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'key': StringProperty(required=True),
|
|
'values': ListProperty(EmbeddedObjectProperty(type=WindowsRegistryValueType)),
|
|
# this is not the modified timestamps of the object itself
|
|
'modified': TimestampProperty(),
|
|
'creator_user_ref': ObjectReferenceProperty(valid_types='user-account'),
|
|
'number_of_subkeys': IntegerProperty(),
|
|
}
|
|
|
|
@property
|
|
def values(self):
|
|
# Needed because 'values' is a property on collections.Mapping objects
|
|
return self._inner['values']
|
|
|
|
|
|
class X509V3ExtenstionsType(_STIXBase):
|
|
_type = 'x509-v3-extensions-type'
|
|
_properties = {
|
|
'basic_constraints': StringProperty(),
|
|
'name_constraints': StringProperty(),
|
|
'policy_constraints': StringProperty(),
|
|
'key_usage': StringProperty(),
|
|
'extended_key_usage': StringProperty(),
|
|
'subject_key_identifier': StringProperty(),
|
|
'authority_key_identifier': StringProperty(),
|
|
'subject_alternative_name': StringProperty(),
|
|
'issuer_alternative_name': StringProperty(),
|
|
'subject_directory_attributes': StringProperty(),
|
|
'crl_distribution_points': StringProperty(),
|
|
'inhibit_any_policy': StringProperty(),
|
|
'private_key_usage_period_not_before': TimestampProperty(),
|
|
'private_key_usage_period_not_after': TimestampProperty(),
|
|
'certificate_policies': StringProperty(),
|
|
'policy_mappings': StringProperty(),
|
|
}
|
|
|
|
|
|
class X509Certificate(_Observable):
|
|
_type = 'x509-certificate'
|
|
_properties = {
|
|
'type': TypeProperty(_type),
|
|
'is_self_signed': BooleanProperty(),
|
|
'hashes': HashesProperty(),
|
|
'version': StringProperty(),
|
|
'serial_number': StringProperty(),
|
|
'signature_algorithm': StringProperty(),
|
|
'issuer': StringProperty(),
|
|
'validity_not_before': TimestampProperty(),
|
|
'validity_not_after': TimestampProperty(),
|
|
'subject': StringProperty(),
|
|
'subject_public_key_algorithm': StringProperty(),
|
|
'subject_public_key_modulus': StringProperty(),
|
|
'subject_public_key_exponent': IntegerProperty(),
|
|
'x509_v3_extensions': EmbeddedObjectProperty(type=X509V3ExtenstionsType),
|
|
}
|