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
Beispiel #13
0
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