def convert_tool(tool20): tool1x = ToolInformation() if "name" in tool20: tool1x.title = tool20["name"] if "description" in tool20: tool1x.description = tool20["description"] if "tool_version" in tool20: tool1x.version = tool20["tool_version"] if "labels" in tool20: warn( "labels not representable in a STIX 1.x ToolInformation. Found in %s", 502, tool20["id"]) # bug in python_stix prevents using next line of code # tool1x.type_ = convert_open_vocabs_to_controlled_vocabs(tool20["labels"], TOOL_LABELS_MAP) ttp = TTP(id_=convert_id20(tool20["id"]), timestamp=text_type(tool20["modified"])) if not ttp.resources: ttp.resources = Resource() if not ttp.resources.tools: ttp.resources.tools = Tools() ttp.resources.tools.append(tool1x) if "kill_chain_phases" in tool20: process_kill_chain_phases(tool20["kill_chain_phases"], ttp) if "object_marking_refs" in tool20: for m_id in tool20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(ttp, ms, descendants=True) if "granular_markings" in tool20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, tool20["id"]) record_id_object_mapping(tool20["id"], ttp) return ttp
def convert_vulnerability(v20): v1x = Vulnerability() if "name" in v20: v1x.title = v20["name"] if "description" in v20: v1x.add_description(v20["description"]) if "labels" in v20: add_missing_list_property_to_description(v1x, "labels", v20["labels"]) v1x.cve_id = extract_external_id("cve", v20["external_references"]) et = ExploitTarget(id_=convert_id20(v20["id"]), timestamp=text_type(v20["modified"])) et.add_vulnerability(v1x) if "kill_chain_phases" in v20: process_kill_chain_phases(v20["kill_chain_phases"], et) if "object_marking_refs" in v20: for m_id in v20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(et, ms, descendants=True) if "granular_markings" in v20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, v20["id"]) record_id_object_mapping(v20["id"], et) return et
def convert_malware(malware20): malware1x = MalwareInstance() if "name" in malware20: malware1x.add_name(malware20["name"]) if "description" in malware20: malware1x.add_description(malware20["description"]) types = convert_open_vocabs_to_controlled_vocabs(malware20["labels"], MALWARE_LABELS_MAP) for t in types: malware1x.add_type(t) ttp = TTP(id_=convert_id20(malware20["id"]), timestamp=text_type(malware20["modified"])) ttp.behavior = Behavior() ttp.behavior.add_malware_instance(malware1x) if "kill_chain_phases" in malware20: process_kill_chain_phases(malware20["kill_chain_phases"], ttp) if "object_marking_refs" in malware20: for m_id in malware20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(ttp, ms, descendants=True) if "granular_markings" in malware20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, malware20["id"]) record_id_object_mapping(malware20["id"], ttp) return ttp
def convert_coa(coa20): coa1x = CourseOfAction(id_=convert_id20(coa20["id"]), timestamp=text_type(coa20["modified"])) if "name" in coa20: coa1x.title = coa20["name"] if "description" in coa20: coa1x.add_description(coa20["description"]) if "labels" in coa20: coa_types = convert_open_vocabs_to_controlled_vocabs( coa20["labels"], COA_LABEL_MAP) coa1x.type_ = coa_types[0] for l in coa_types[1:]: warn( "%s in STIX 2.0 has multiple %s, only one is allowed in STIX 1.x. Using first in list - %s omitted", 401, "labels", l) if "object_marking_refs" in coa20: for m_id in coa20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(coa1x, ms, descendants=True) if "granular_markings" in coa20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, coa20["id"]) record_id_object_mapping(coa20["id"], coa1x) return coa1x
def convert_indicator(indicator20): indicator1x = Indicator(id_=convert_id20(indicator20["id"]), timestamp=text_type(indicator20["modified"])) if "name" in indicator20: indicator1x.title = indicator20["name"] if "description" in indicator20: indicator1x.add_description(indicator20["description"]) indicator1x.indicator_types = convert_open_vocabs_to_controlled_vocabs( indicator20["labels"], INDICATOR_LABEL_MAP) indicator1x.add_valid_time_position( convert_to_valid_time( text_type(indicator20["valid_from"]), text_type(indicator20["valid_until"]) if "valid_until" in indicator20 else None)) indicator1x.add_observable( create_pattern_object( indicator20["pattern"]).toSTIX1x(id20=indicator20["id"])) if "kill_chain_phases" in indicator20: process_kill_chain_phases(indicator20["kill_chain_phases"], indicator1x) if "object_marking_refs" in indicator20: for m_id in indicator20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(indicator1x, ms, descendants=True) if "granular_markings" in indicator20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, indicator20["id"]) record_id_object_mapping(indicator20["id"], indicator1x) return indicator1x
def convert_campaign(c20): c1x = Campaign(id_=convert_id20(c20["id"]), timestamp=text_type(c20["modified"])) if "name" in c20: c1x.title = c20["name"] if "description" in c20: c1x.add_description(c20["description"]) if "labels" in c20: for l in c20["labels"]: add_missing_property_to_description(c1x, "label", l) names = Names() if "aliases" in c20: for a in c20["aliases"]: names.name.append(VocabString(a)) if names: c1x.names = names if "first_seen" in c20: add_missing_property_to_description(c1x, "first_seen", text_type(c20["first_seen"])) if "last_seen" in c20: add_missing_property_to_description(c1x, "last_seen", text_type(c20["last_seen"])) if "objective" in c20: c1x.intended_effects = [Statement(description=c20["objective"])] if "object_marking_refs" in c20: for m_id in c20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(c1x, ms, descendants=True) if "granular_markings" in c20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, c20["id"]) record_id_object_mapping(c20["id"], c1x) return c1x
def convert_attack_pattern(ap20): ap1x = AttackPattern() if "name" in ap20: ap1x.title = ap20["name"] if "description" in ap20: ap1x.add_description(ap20["description"]) if "labels" in ap20: for l in ap20["labels"]: add_missing_property_to_description(ap1x, "label", l) if "external_references" in ap20: ap1x.capec_id = extract_external_id("capec", ap20["external_references"]) ttp = TTP(id_=convert_id20(ap20["id"]), timestamp=text_type(ap20["modified"])) ttp.behavior = Behavior() ttp.behavior.add_attack_pattern(ap1x) if "kill_chain_phases" in ap20: process_kill_chain_phases(ap20["kill_chain_phases"], ttp) if "object_marking_refs" in ap20: for m_id in ap20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(ttp, ms, descendants=True) if "granular_markings" in ap20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, ap20["id"]) # if "kill_chain_phases" in ap20: # process_kill_chain_phases(ap20["kill_chain_phases"], ttp) record_id_object_mapping(ap20["id"], ttp) return ttp
def convert_identity(ident20): if ("sectors" in ident20 or "contact_information" in ident20 or "labels" in ident20 or "identity_class" in ident20 or "description" in ident20): ident1x = CIQIdentity3_0Instance() id1x = convert_id20(ident20["id"]) ident1x.id_ = id1x if ident20["identity_class"] != "organization": ident1x.name = ident20["name"] if "labels" in ident20: ident1x.roles = ident20["labels"] if ("sectors" in ident20 or "contact_information" in ident20 or "identity_class" in ident20 or "description" in ident20): ident1x.specification = STIXCIQIdentity3_0() if ident20["identity_class"] == "organization": party_name = PartyName() party_name.add_organisation_name(text_type(ident20["name"])) ident1x.specification.party_name = party_name if "sectors" in ident20: first = True for s in ident20["sectors"]: if first: ident1x.specification.organisation_info = \ OrganisationInfo(text_type(convert_open_vocabs_to_controlled_vocabs(s, SECTORS_MAP, False)[0])) first = False else: warn( "%s in STIX 2.0 has multiple %s, only one is allowed in STIX 1.x. Using first in list - %s omitted", 401, "Identity", "sectors", s) # Identity in 1.x has no description property, use free-text-lines if "identity_class" in ident20: add_missing_property_to_free_text_lines( ident1x.specification, "identity_class", ident20["identity_class"]) # Because there is format defined in the specification for this property, it is difficult to # determine how to convert the information probably found within it to the CIQ fields, so it will be put # in the free_text_lines if "contact_information" in ident20: add_missing_property_to_free_text_lines( ident1x.specification, "contact_information", ident20["contact_information"]) if "description" in ident20: add_missing_property_to_free_text_lines( ident1x.specification, "description", ident20["description"]) else: ident1x = Identity(id_=convert_id20(ident20["id"]), name=ident20["name"]) if "object_marking_refs" in ident20: for m_id in ident20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(ident1x, ms, descendants=True) if "granular_markings" in ident20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, ident20["id"]) return ident1x
def convert_marking_definition(marking20): definition = marking20["definition"] marking_spec = MarkingSpecification() if marking20["definition_type"] == "statement": tou = TermsOfUseMarkingStructure(terms_of_use=definition["statement"]) tou.id_ = convert_id20(marking20["id"]) marking_spec.marking_structures.append(tou) elif marking20["definition_type"] == "tlp": tlp = TLPMarkingStructure(color=definition["tlp"]) tlp.id_ = convert_id20(marking20["id"]) marking_spec.marking_structures.append(tlp) elif marking20["definition_type"] == "ais": identity20_tuple = _EXPLICIT_OBJECT_USED[marking20["created_by_ref"]] color = definition["tlp"].upper() if definition["is_proprietary"] == "true": proprietary = IsProprietary() consent = "EVERYONE" else: proprietary = NotProprietary() consent = definition["consent"].upper() proprietary.ais_consent = AISConsentType(consent=consent) proprietary.tlp_marking = TLPMarkingType(color=color) ais_marking = AISMarkingStructure() ais_marking.id_ = convert_id20(marking20["id"]) if isinstance(proprietary, IsProprietary): ais_marking.is_proprietary = proprietary else: ais_marking.not_proprietary = proprietary marking_spec.controlled_structure = "//node() | //@*" marking_spec.marking_structures.append(ais_marking) marking_spec.information_source = create_information_source( identity20_tuple) # Remove marking to CIQ identity. Special case for AIS. for mark_spec in CONTAINER.get_markings(identity20_tuple[0]): mark_struct = mark_spec.marking_structures[0] if mark_struct.idref and mark_struct.idref == ais_marking.id_: CONTAINER.remove_marking(identity20_tuple[0], mark_spec, True) record_id_object_mapping(marking20["id"], marking_spec.marking_structures[0]) if "object_marking_refs" in marking20: for m_id in marking20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(marking_spec, ms, descendants=True) if "granular_markings" in marking20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, marking20["id"]) return marking_spec
def convert_report(r20): r1x = Report(id_=convert_id20(r20["id"]), timestamp=text_type(r20["modified"])) r1x.header = Header() if "name" in r20: r1x.header.title = r20["name"] if "description" in r20: r1x.header.add_description(r20["description"]) intents = convert_open_vocabs_to_controlled_vocabs(r20["labels"], REPORT_LABELS_MAP) for i in intents: r1x.header.add_intent(i) if "published" in r20: add_missing_property_to_description(r1x.header, "published", r20["published"]) for ref in r20["object_refs"]: ref_type = get_type_from_id(ref) ref1x = convert_id20(ref) if ref_type == "attack-pattern": r1x.add_ttp(TTP(idref=ref1x)) elif ref_type == "campaign": r1x.add_campaign(Campaign(idref=ref1x)) elif ref_type == 'course-of-action': r1x.add_course_of_action(CourseOfAction(idref=ref1x)) elif ref_type == "indicator": r1x.add_indicator(Indicator(idref=ref1x)) elif ref_type == "observed-data": r1x.add_observable(Observable(idref=ref1x)) elif ref_type == "malware": r1x.add_ttp(TTP(idref=ref1x)) elif ref_type == "threat-actor": r1x.add_threat_actor(ThreatActor(idref=ref1x)) elif ref_type == "tool": r1x.add_ttp(TTP(idref=ref1x)) elif ref_type == "vulnerability": r1x.add_exploit_target(ExploitTarget(idref=ref1x)) elif ref_type == "identity" or ref_type == "relationship": warn("%s in %s is not explicitly a member of a STIX 1.x report", 703, ref, r20["id"]) elif ref_type == "intrusion-set": warn("%s in %s cannot be represented in STIX 1.x", 612, ref, r20["id"]) else: warn("ref type %s in %s is not known", 0, ref_type, r20["id"]) if "object_marking_refs" in r20: for m_id in r20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(r1x, ms, descendants=True) if "granular_markings" in r20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, r20["id"]) return r1x
def convert_observed_data(od20): o1x = Observable(id_=convert_id20(od20["id"])) if "object_marking_refs" in od20: for m_id in od20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(o1x, ms, descendants=True) if "granular_markings" in od20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, od20["id"]) # observable-data has no description o1x.object_ = convert_cyber_observables(od20["objects"], od20["id"]) return o1x
def convert_threat_actor(ta20): ta1x = ThreatActor(id_=convert_id20(ta20["id"]), timestamp=text_type(ta20["modified"])) ta1x.title = ta20["name"] types = convert_open_vocabs_to_controlled_vocabs(ta20["labels"], THREAT_ACTOR_LABEL_MAP) for t in types: ta1x.add_type(t) if "description" in ta20: ta1x.add_description(ta20["description"]) if "aliases" in ta20: add_missing_list_property_to_description(ta1x, "aliases", ta20["aliases"]) if "roles" in ta20: add_missing_list_property_to_description(ta1x, "roles", ta20["roles"]) if "goals" in ta20: for g in ta20["goals"]: ta1x.add_intended_effect(g) if "sophistication" in ta20: sophistications = convert_open_vocabs_to_controlled_vocabs( [ta20["sophistication"]], THREAT_ACTOR_SOPHISTICATION_MAP) for s in sophistications: ta1x.add_sophistication(s) if "resource_level" in ta20: add_missing_list_property_to_description(ta1x, "resource_level", ta20["resource_level"]) all_motivations = [] if "primary_motivation" in ta20: all_motivations = [ta20["primary_motivation"]] if "secondary_motivation" in ta20: all_motivations.extend(ta20["secondary_motivation"]) if "personal_motivation" in ta20: all_motivations.extend(ta20["personal_motivation"]) motivations = convert_open_vocabs_to_controlled_vocabs( all_motivations, ATTACK_MOTIVATION_MAP) for m in motivations: ta1x.add_motivation(m) if "object_marking_refs" in ta20: for m_id in ta20["object_marking_refs"]: ms = create_marking_specification(m_id) if ms: CONTAINER.add_marking(ta1x, ms, descendants=True) if "granular_markings" in ta20: error( "Granular Markings present in '%s' are not supported by stix2slider", 604, ta20["id"]) record_id_object_mapping(ta20["id"], ta1x) return ta1x
def convert_cyber_observable(c_o_object, obs20_id): type1x = determine_1x_object_type(c_o_object) if type1x: obj1x = type1x() else: error("Unable to determine STIX 1.x type for %s", 603, obs20_id) type_name20 = c_o_object["type"] if type_name20 == "artifact": convert_artifact_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "autonomous-system": convert_autonomous_system_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "directory": convert_directory_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "domain-name": convert_domain_name_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "email-message": convert_email_message_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "file": convert_file_c_o(c_o_object, obj1x, obs20_id) elif type_name20 in ['ipv4-addr', 'ipv6-addr', 'mac-addr', 'email-addr']: # TODO: email_address have display_name property convert_addr_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "mutex": obj1x.name = c_o_object["name"] obj1x.named = True elif type_name20 == "network-traffic": convert_network_traffic_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "process": convert_process_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == 'software': convert_software_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "url": obj1x.value = c_o_object["value"] obj1x.type_ = URI.TYPE_URL elif type_name20 == "user-account": convert_user_account_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "windows-registry-key": convert_windows_registry_key_c_o(c_o_object, obj1x, obs20_id) elif type_name20 == "x509-certificate": convert_x509_certificate_c_o(c_o_object, obj1x, obs20_id) return obj1x
def convert_bundle(bundle_obj): global _ID_OBJECT_MAPPING global _EXPLICIT_OBJECT_USED global _ID_NAMESPACE global _VICTIM_TARGET_TTPS global _KILL_CHAINS global CONTAINER _ID_OBJECT_MAPPING = {} _EXPLICIT_OBJECT_USED = {} _VICTIM_TARGET_TTPS = [] _KILL_CHAINS = {} if get_option_value("use_namespace"): option_value = get_option_value("use_namespace").split(" ") _ID_NAMESPACE = option_value[0] set_default_namespace(*option_value) CONTAINER = stixmarx.new() pkg = CONTAINER.package pkg.id_ = convert_id20(bundle_obj["id"]) for identity in (v for v in bundle_obj["objects"] if v["type"] == "identity"): debug("Found '%s'", 0, identity["id"]) i1x = convert_identity(identity) record_id_object_mapping(identity["id"], i1x, used=False) for marking_definition in (v for v in bundle_obj["objects"] if v["type"] == "marking-definition"): debug("Found '%s'", 0, marking_definition["id"]) m1x = convert_marking_definition(marking_definition) if not pkg.stix_header: pkg.stix_header = STIXHeader(handling=Marking()) pkg.stix_header.handling.add_marking(m1x) for o in bundle_obj["objects"]: if o["type"] == "attack-pattern": pkg.add_ttp(convert_attack_pattern(o)) elif o["type"] == "campaign": pkg.add_campaign(convert_campaign(o)) elif o["type"] == 'course-of-action': pkg.add_course_of_action(convert_coa(o)) elif o["type"] == "indicator": pkg.add_indicator(convert_indicator(o)) elif o["type"] == "intrusion-set": error( "Cannot convert STIX 2.0 content that contains intrusion-sets", 524) return None elif o["type"] == "malware": pkg.add_ttp(convert_malware(o)) elif o["type"] == "observed-data": pkg.add_observable(convert_observed_data(o)) elif o["type"] == "report": pkg.add_report(convert_report(o)) elif o["type"] == "threat-actor": pkg.add_threat_actor(convert_threat_actor(o)) elif o["type"] == "tool": pkg.add_ttp(convert_tool(o)) elif o["type"] == "vulnerability": pkg.add_exploit_target(convert_vulnerability(o)) # second passes for o in bundle_obj["objects"]: if o["type"] == "relationship": process_relationships(o) for o in bundle_obj["objects"]: if "created_by_ref" in o: process_created_by_ref(o) if "external_references" in o: create_references(o) for o in bundle_obj["objects"]: if o["type"] == "sighting": process_sighting(o) for k, v in _KILL_CHAINS.items(): pkg.ttps.kill_chains.append(v["kill_chain"]) CONTAINER.flush() CONTAINER = None return pkg