def create_stix_hash_observable(namespace, indicator): """ Create STIX file observable. Args: namespace: The XML namespace. indicator: The Demisto File indicator. Returns: STIX File observable. """ id_ = f'{namespace}:observable-{uuid.uuid4()}' value = indicator.get('value', '') type_ = indicator.get('indicator_type', '') file_object = cybox.objects.file_object.File() file_object.add_hash(indicator) observable = Observable( title=f'{value}: {type_}', id_=id_, item=file_object ) return [observable]
def create_stix_email_observable(namespace: str, indicator: dict) -> List[Observable]: """ Create STIX Email observable. Args: namespace: The XML namespace. indicator: The Demisto Email indicator. Returns: STIX Email observable. """ category = cybox.objects.address_object.Address.CAT_EMAIL type_ = indicator.get('indicator_type', '') value = indicator.get('value', '') id_ = f'{namespace}:observable-{uuid.uuid4()}' email_object = cybox.objects.address_object.Address( address_value=indicator.get('value', ''), category=category ) observable = Observable( title=f'{type_}: {value}', id_=id_, item=email_object ) return [observable]
def create_stix_url_observable(namespace, indicator): """ Create STIX URL observable. Args: namespace: The XML namespace. indicator: The Demisto URL indicator. Returns: STIX URL observable. """ id_ = f'{namespace}:observable-{uuid.uuid4()}' value = indicator.get('value', '') uri_object = cybox.objects.uri_object.URI( value=value, type_=cybox.objects.uri_object.URI.TYPE_URL ) observable = Observable( title=f'URL: {value}', id_=id_, item=uri_object ) return [observable]
def create_stix_ip_observable(namespace: str, indicator: dict) -> List[Observable]: """ Create STIX IP observable. Args: namespace: The XML namespace . indicator: The Demisto IP indicator. Returns: STIX IP observable. """ category = cybox.objects.address_object.Address.CAT_IPV4 type_ = indicator.get('indicator_type', '') value = indicator.get('value', '') if type_ in [FeedIndicatorType.IPv6, FeedIndicatorType.IPv6CIDR]: category = cybox.objects.address_object.Address.CAT_IPV6 indicator_values = [value] if '-' in value: # looks like an IP Range, let's try to make it a CIDR a1, a2 = value.split('-', 1) if a1 == a2: # same IP indicator_values = [a1] else: # use netaddr builtin algo to summarize range into CIDR iprange = netaddr.IPRange(a1, a2) cidrs = iprange.cidrs() indicator_values = list(map(str, cidrs)) observables = [] for indicator_value in indicator_values: id_ = f'{namespace}:observable-{uuid.uuid4()}' address_object = cybox.objects.address_object.Address( address_value=indicator_value, category=category ) observable = Observable( title=f'{type_}: {indicator_value}', id_=id_, item=address_object ) observables.append(observable) return observables
def create_stix_domain_observable(namespace, indicator): """ Create STIX Domain observable. Args: namespace: The XML namespace. indicator: The Demisto Domain indicator. Returns: STIX Domain observable. """ id_ = f'{namespace}:observable-{uuid.uuid4()}' value = indicator.get('value', '') domain_object = cybox.objects.domain_name_object.DomainName() domain_object.value = value domain_object.type_ = 'FQDN' observable = Observable(title=f'FQDN: {value}', id_=id_, item=domain_object) return [observable]
def get_stix_indicator(indicator: dict) -> stix.core.STIXPackage: """ Convert a Demisto indicator to STIX. Args: indicator: The Demisto indicator. Returns: The STIX indicator as XML string. """ set_id_namespace(NAMESPACE_URI, NAMESPACE) type_ = indicator.get('indicator_type', '') type_mapper: dict = TYPE_MAPPING.get(type_, {}) value = indicator.get('value', '') source = indicator.get('sourceBrands', []) sources = ','.join(source) handling = None # Add TLP if available share_level = indicator.get('trafficlightprotocol', '').upper() if share_level and share_level in ['WHITE', 'GREEN', 'AMBER', 'RED']: marking_specification = stix.data_marking.MarkingSpecification() marking_specification.controlled_structure = "//node() | //@*" tlp = stix.extensions.marking.tlp.TLPMarkingStructure() tlp.color = share_level marking_specification.marking_structures.append(tlp) handling = stix.data_marking.Marking() handling.add_marking(marking_specification) header = None if handling is not None: header = stix.core.STIXHeader(handling=handling) # Create the STIX package package_id = f'{NAMESPACE}:observable-{uuid.uuid4()}' stix_package = stix.core.STIXPackage(id_=package_id, stix_header=header) # Get the STIX observables according to the indicator mapper observables = type_mapper['mapper'](NAMESPACE, indicator) # Create the STIX indicator for observable in observables: id_ = f'{NAMESPACE}:indicator-{uuid.uuid4()}' if type_ == 'URL': indicator_value = werkzeug.urls.iri_to_uri(value, safe_conversion=True) else: indicator_value = value stix_indicator = stix.indicator.indicator.Indicator( id_=id_, title=f'{type_}: {indicator_value}', description=f'{type_} indicator from {sources}', timestamp=datetime.utcnow().replace(tzinfo=pytz.utc)) # Confidence is mapped by the indicator score confidence = 'Low' indicator_score = indicator.get('score') if indicator_score is None: demisto.error(f'indicator without score: {value}') stix_indicator.confidence = "Unknown" else: score = int(indicator.get('score', 0)) if score < 2: pass elif score < 3: confidence = 'Medium' else: confidence = 'High' stix_indicator.confidence = confidence stix_indicator.add_indicator_type(type_mapper['indicator_type']) stix_indicator.add_observable(observable) stix_package.add_indicator(stix_indicator) return stix_package