def test_multiple_qualifiers():
    exp_and = stix2.AndBooleanExpression([
        stix2.EqualityComparisonExpression(
            "network-traffic:dst_ref.type",
            "domain-name",
        ),
        stix2.EqualityComparisonExpression(
            "network-traffic:dst_ref.value",
            "example.com",
        ),
    ])
    exp_ob = stix2.ObservationExpression(exp_and)
    qual_rep = stix2.RepeatQualifier(5)
    qual_within = stix2.WithinQualifier(stix2.IntegerConstant(1800))
    exp = stix2.QualifiedObservationExpression(
        stix2.QualifiedObservationExpression(exp_ob, qual_rep), qual_within)
    assert str(
        exp
    ) == "[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS"  # noqa
Exemplo n.º 2
0
    def process_reports(self, reports):
        if reports is None:
            printer.error("No results")
            return

        for report in reports:
            name = report["name"]
            id = report["id"]
            stix2_objects = []
            stix2_object_refs = []

            # FFS AV, consistency!
            if 'tlp' in report:
                tlp_id = REF_TLPS[report['tlp'].upper()]
            elif 'TLP' in report:
                tlp_id = REF_TLPS[report['TLP'].upper()]
            else:
                tlp_id = REF_TLPS['WHITE']

            sectors = report['industries']
            if sectors:
                unmatched_sectors = []
                added_sector = False

                for sector in [html.unescape(x.upper()) for x in sectors]:
                    sector_name = None
                    sector_id = None

                    if sector in SECTOR_MAPPINGS:
                        # sector_ids.append(self.octi_sectors[SECTOR_MAPPINGS[sector]])
                        sector_name = SECTOR_MAPPINGS[sector]
                        try:
                            sector_id = self.octi_sectors[
                                SECTOR_MAPPINGS[sector]]
                        except Exception as e:
                            printer.error(e)
                            continue
                    else:
                        printer.debug(f"Looking for sector {sector}")
                        match = difflib.get_close_matches(
                            sector, self.octi_sectors.keys(), 1)
                        if not len(match):
                            printer.error(
                                f"Unable to determine a matching sector for {sector}"
                            )
                            unmatched_sectors.append(sector)
                            continue
                        # sector_ids.append(self.octi_sectors[match[0]])
                        sector_name = match[0]
                        sector_id = self.octi_sectors[match[0]]

                    if sector_name is not None:
                        s = stix2.Identity(id=sector_id,
                                           name=sector_name,
                                           identity_class='class',
                                           custom_properties={
                                               'x_opencti_identity_type':
                                               'sector'
                                           })
                        printer.debug(f"Adding sector {sector_name}")
                        stix2_objects.append(s)
                        stix2_object_refs.append(s)
                        added_sector = True

                if not added_sector:
                    printer.warn("Adding 'UNKNOWN' placeholder sector")
                    s = stix2.Identity(id=self.octi_sectors["UNKNOWN"],
                                       name="Unknown",
                                       identity_class='class',
                                       custom_properties={
                                           'x_opencti_identity_type': 'sector'
                                       })
                    stix2_objects.append(s)
                    stix2_object_refs.append(s)

                description = report['description']
                if len(unmatched_sectors):
                    description = description + "\n\n###\nUnable to find a match for the following sectors, " \
                                                "please review manually:\n - " + '\n - '.join(unmatched_sectors)

                printer.info(f"Generating STIX2 for {name} ({id})")

                author = stix2.Identity(name=report['author_name'],
                                        identity_class='organization')
                stix2_objects.append(author)

                adversary = None
                if report['adversary']:
                    printer.debug("Adding adversary {}".format(
                        report['adversary']))
                    adversary = stix2.IntrusionSet(name=report['adversary'])
                    stix2_object_refs.append(adversary)
                    stix2_objects.append(adversary)

                if report['targeted_countries']:
                    for country in report['targeted_countries']:
                        printer.debug(f"Adding country {country}")
                        c = stix2.Identity(name=country,
                                           identity_class='organization',
                                           custom_properties={
                                               'x_opencti_identity_type':
                                               'country'
                                           })
                        stix2_objects.append(c)
                        stix2_object_refs.append(c)

                external_refs = []
                for eref in report['references']:
                    external_refs.append(
                        stix2.ExternalReference(source_name=tldextract.extract(
                            eref).registered_domain,
                                                url=eref))

                indicators = report["indicators"]
                if indicators:
                    for indicator in indicators:
                        resolved_type = self.resolve_type(
                            indicator["type"].lower())
                        if resolved_type != None and indicator["is_active"]:

                            observable_type = resolved_type
                            observable_value = indicator["indicator"]
                            pattern_type = 'stix'

                            try:
                                if observable_type in PATTERNTYPES:
                                    pattern_type = observable_type
                                elif observable_type not in OPENCTISTIX2:
                                    printer.info("Not in stix2 dict")
                                else:
                                    if 'transform' in OPENCTISTIX2[
                                            observable_type]:
                                        if OPENCTISTIX2[observable_type][
                                                'transform'][
                                                    'operation'] == 'remove_string':
                                            observable_value = observable_value.replace(
                                                OPENCTISTIX2[observable_type]
                                                ['transform']['value'], '')
                                    lhs = stix2.ObjectPath(
                                        OPENCTISTIX2[observable_type]['type'],
                                        OPENCTISTIX2[observable_type]['path'])
                                    observable_value = stix2.ObservationExpression(
                                        stix2.EqualityComparisonExpression(
                                            lhs, observable_value))
                            except Exception as e:
                                printer.error(e)
                                printer.info(
                                    "Could not determine suitable pattern")

                            try:

                                indicator_obj = stix2.Indicator(
                                    name=indicator["indicator"],
                                    description=indicator["description"],
                                    pattern=str(observable_value),
                                    valid_from=indicator["created"],
                                    labels=['malicious-activity'],
                                    created_by_ref=author,
                                    object_marking_refs=[tlp_id],
                                    custom_properties={
                                        'x_opencti_observable_type':
                                        resolved_type,
                                        'x_opencti_observable_value':
                                        indicator["indicator"],
                                        'x_opencti_pattern_type':
                                        pattern_type
                                    })
                                stix2_object_refs.append(indicator_obj)
                                stix2_objects.append(indicator_obj)
                            except Exception as e:
                                printer.error(e)
                                printer.info("Couldn't fetch indicator")

                else:
                    printer.error("No indicators")

                report = stix2.Report(name=name,
                                      description=description,
                                      created_by_ref=author,
                                      labels=['threat-report'],
                                      published=report['created'],
                                      created=report['created'],
                                      modified=report['modified'],
                                      object_refs=stix2_object_refs,
                                      object_marking_refs=[tlp_id],
                                      external_references=external_refs)
                stix2_objects.append(report)
                bundle = stix2.Bundle(stix2_objects).serialize()
                if not self.dryrun:
                    self.opencti_connector_helper.send_stix2_bundle(
                        bundle, None, True, False)
                    printer.info("Sending to OpenCTI")
                #printer.debug(str(bundle))

            else:
                printer.debug(f"No sectors, disregarding '{name}'")
Exemplo n.º 3
0
def test_greater_than_python_constant():
    exp1 = stix2.GreaterThanComparisonExpression("file:extensions.'windows-pebinary-ext'.sections[*].entropy", 7.0)
    exp = stix2.ObservationExpression(exp1)
    assert str(exp) == "[file:extensions.'windows-pebinary-ext'.sections[*].entropy > 7.0]"
Exemplo n.º 4
0
def test_set_op():
    exp = stix2.ObservationExpression(stix2.IsSubsetComparisonExpression("network-traffic:dst_ref.value",
                                                                         "2001:0db8:dead:beef:0000:0000:0000:0000/64"))
    assert str(exp) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
Exemplo n.º 5
0
def test_greater_than():
    exp1 = stix2.GreaterThanComparisonExpression("file:extensions.windows-pebinary-ext.sections[*].entropy",
                                                 stix2.FloatConstant(7.0))
    exp = stix2.ObservationExpression(exp1)
    assert str(exp) == "[file:extensions.windows-pebinary-ext.sections[*].entropy > 7.0]"
    def __generate_observation_expression(self, size):
        """
        Generate a random complex observation expression, which may consist of
        sub-expressions and qualifiers.

        :param size: The size of the desired observation expression, in terms of
            the number of simple comparison expressions it must contain
        :return: The observation expression AST
        """
        assert size > 0

        # The generation strategy is similar to that for comparison expressions
        # (see __generate_complex_comparison_expression()).  It is generated in
        # two parts of random size; one side is constructed as a sub-expression.

        if size == 1:
            obs_expr = stix2.ObservationExpression(
                self.__generate_complex_comparison_expression(1))

        else:
            lsize = random.randint(0, size)
            rsize = size - lsize

            if random.random() < 0.5:
                # Parenthesize right case
                obs_exprs = [
                    stix2.ObservationExpression(
                        self.__generate_complex_comparison_expression(sz))
                    for sz in _rand_series(lsize)
                ]

                if rsize > 0:
                    obs_exprs.append(
                        stix2.ParentheticalExpression(
                            self.__generate_observation_expression(rsize)))

            else:
                # Parenthesize left case
                if lsize == 0:
                    obs_exprs = []
                else:
                    obs_exprs = [
                        stix2.ParentheticalExpression(
                            self.__generate_observation_expression(lsize))
                    ]

                obs_exprs.extend(
                    stix2.ObservationExpression(
                        self.__generate_complex_comparison_expression(sz))
                    for sz in _rand_series(rsize))

            ast_class = random.choice(
                (stix2.AndObservationExpression, stix2.OrObservationExpression,
                 stix2.FollowedByObservationExpression))

            obs_expr = ast_class(obs_exprs)

        if random.random() < self.__config.probability_qualifier:
            qualifier = self.__generate_random_qualifier()
            obs_expr = stix2.QualifiedObservationExpression(
                obs_expr, qualifier)

        return obs_expr