Esempio n. 1
0
    def fetch_and_send(self):
        timestamp = int(time.time())
        now = datetime.utcfromtimestamp(timestamp)
        friendly_name = "Cyber Threat Coalition run @ " + now.strftime(
            "%Y-%m-%d %H:%M:%S"
        )
        work_id = self.helper.api.work.initiate_work(
            self.helper.connect_id, friendly_name
        )
        bundle_objects = list()

        # create an identity for the coalition team
        organization = stix2.Identity(
            id=OpenCTIStix2Utils.generate_random_stix_id("identity"),
            name="Cyber Threat Coalition Team",
            identity_class="organization",
            description="Team of Experts collecting and sharing pandemic related "
            "cyber threat intelligence during the COVID-19 crisis time",
        )

        # add organization in bundle
        bundle_objects.append(organization)
        report_object_refs = list()

        for collection in ["domain", "ip", "url", "hash"]:
            # fetch backlist
            url = self.cyber_threat_coalition_base_url + "/" + str(collection) + ".txt"
            response = requests.get(url=url)
            if response.status_code != 200:
                raise Exception(
                    "Unable to fetch {0} blacklist, server returned status: {1}",
                    collection,
                    response.status_code,
                )
            pattern_type = "stix"
            labels = ["COVID-19", "malicious-activity"]
            # parse content
            for data in response.iter_lines(decode_unicode=True):
                observable_type = None
                observable_resolver = None
                if data and not data.startswith("#"):
                    if collection == "domain":
                        observable_resolver = "Domain-Name"
                        observable_type = "Domain-Name"
                    elif collection == "ip":
                        observable_resolver = "IPv4-Addr"
                        observable_type = "IPv4-Addr"
                    elif collection == "url":
                        observable_resolver = "Url"
                        observable_type = "Url"
                        data = urllib.parse.quote(data, "/:")
                    elif collection == "hash":
                        observable_resolver = self.get_hash_type()
                        observable_type = "File"
                    indicator = None
                    if observable_resolver is None or observable_type is None:
                        return
                    if self.cyber_threat_coalition_create_indicators:
                        indicator = stix2.Indicator(
                            id=OpenCTIStix2Utils.generate_random_stix_id("indicator"),
                            name=data,
                            pattern_type=pattern_type,
                            pattern=self._INDICATOR_PATTERN[observable_resolver].format(
                                data
                            ),
                            labels=labels,
                            created_by_ref=organization,
                            object_marking_refs=[stix2.TLP_WHITE],
                            custom_properties={
                                "x_opencti_main_observable_type": observable_type,
                            },
                        )
                        bundle_objects.append(indicator)
                        report_object_refs.append(indicator["id"])
                    if self.cyber_threat_coalition_create_observables:
                        observable = SimpleObservable(
                            id=OpenCTIStix2Utils.generate_random_stix_id(
                                "x-opencti-simple-observable"
                            ),
                            key=observable_type
                            + "."
                            + ".".join(self._OBSERVABLE_PATH[observable_resolver]),
                            value=data,
                            labels=labels,
                            created_by_ref=organization,
                            object_marking_refs=[stix2.TLP_WHITE],
                        )
                        bundle_objects.append(observable)
                        report_object_refs.append(observable["id"])
                        if indicator is not None:
                            relationship = stix2.Relationship(
                                id=OpenCTIStix2Utils.generate_random_stix_id(
                                    "relationship"
                                ),
                                relationship_type="based-on",
                                created_by_ref=organization,
                                source_ref=indicator.id,
                                target_ref=observable.id,
                            )
                            bundle_objects.append(relationship)
                            report_object_refs.append(relationship["id"])

        # create a global threat report
        report_uuid = "report--552b3ae6-8522-409d-8b72-a739bc1926aa"
        report_external_reference = stix2.ExternalReference(
            source_name="Cyber Threat Coalition",
            url="https://www.cyberthreatcoalition.org",
            external_id="COVID19-CTC",
        )
        if report_object_refs:
            stix_report = stix2.Report(
                id=report_uuid,
                name="COVID-19 Cyber Threat Coalition (CTC) BlackList",
                type="report",
                description="This report represents the whole COVID-19 CTC blacklist.",
                published=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
                created_by_ref=organization,
                object_marking_refs=[stix2.TLP_WHITE],
                labels=labels,
                external_references=[report_external_reference],
                object_refs=report_object_refs,
            )
            # add report in bundle
            bundle_objects.append(stix_report)

        # create stix bundle
        bundle = stix2.Bundle(objects=bundle_objects)

        # send data
        self.helper.send_stix2_bundle(
            bundle=bundle.serialize(), update=self.update_existing_data, work_id=work_id
        )
        return work_id
    def run(self):
        self.helper.log_info("Fetching data CYBERCRIME-TRACKER.NET...")
        tlp = self.helper.api.marking_definition.read(
            filters=[
                {"key": "definition", "values": "TLP:{}".format(self.connector_tlp)}
            ]
        )
        while True:
            try:
                # Get the current timestamp and check
                timestamp = int(time.time())
                current_state = self.helper.get_state()

                if current_state is not None and "last_run" in current_state:
                    last_run = current_state["last_run"]
                    self.helper.log_info(
                        "Connector last run: {}".format(
                            datetime.datetime.utcfromtimestamp(last_run).strftime(
                                "%Y-%m-%d %H:%M:%S"
                            )
                        )
                    )
                else:
                    last_run = None
                    self.helper.log_info("Connector has never run")

                # Run if it is the first time or we are past the interval

                if last_run is None or ((timestamp - last_run) > self.interval):
                    self.helper.log_info("Connector will run!")
                    now = datetime.datetime.utcfromtimestamp(timestamp)
                    friendly_name = "MITRE run @ " + now.strftime("%Y-%m-%d %H:%M:%S")
                    work_id = self.helper.api.work.initiate_work(
                        self.helper.connect_id, friendly_name
                    )

                    # Get Feed Content
                    feed = feedparser.parse(self.feed_url)

                    self.helper.log_info(
                        "Found: {} entries.".format(len(feed["entries"]))
                    )

                    self.feed_summary = {
                        "Source": feed["feed"]["title"],
                        "Date": self._time_to_datetime(
                            feed["feed"]["published_parsed"]
                        ),
                        "Details": feed["feed"]["subtitle"],
                        "Link": feed["feed"]["link"],
                    }

                    # Create the bundle
                    bundle_objects = list()

                    organization = stix2.Identity(
                        id=OpenCTIStix2Utils.generate_random_stix_id("identity"),
                        name="CYBERCRIME-TRACKER.NET",
                        identity_class="organization",
                        description="Tracker collecting and sharing daily updates of C2 IPs/Urls. http://cybercrime-tracker.net",
                    )
                    bundle_objects.append(organization)
                    for entry in feed["entries"]:
                        parsed_entry = self.parse_feed_entry(entry)
                        external_reference = stix2.ExternalReference(
                            source_name="{}".format(self.feed_summary["Source"]),
                            url=parsed_entry["ext_link"],
                        )
                        indicator_pattern = self.gen_indicator_pattern(parsed_entry)
                        malware = stix2.Malware(
                            id=OpenCTIStix2Utils.generate_random_stix_id("malware"),
                            is_family=True,
                            name=parsed_entry["type"],
                            description="{} malware.".format(parsed_entry["type"]),
                        )
                        bundle_objects.append(malware)
                        indicator = None
                        if self.create_indicators:
                            indicator = stix2.Indicator(
                                id=OpenCTIStix2Utils.generate_random_stix_id(
                                    "indicator"
                                ),
                                name=parsed_entry["url"],
                                description="C2 URL for: {}".format(
                                    parsed_entry["type"]
                                ),
                                labels=["C2 Server"],
                                pattern_type="stix",
                                pattern=indicator_pattern,
                                valid_from=parsed_entry["date"],
                                created=parsed_entry["date"],
                                modified=parsed_entry["date"],
                                created_by_ref=organization.id,
                                object_marking_refs=[tlp["standard_id"]],
                                external_references=[external_reference],
                                custom_properties={
                                    "x_opencti_main_observable_type": "Url"
                                },
                            )
                            bundle_objects.append(indicator)
                            relation = stix2.Relationship(
                                id=OpenCTIStix2Utils.generate_random_stix_id(
                                    "relationship"
                                ),
                                source_ref=indicator.id,
                                target_ref=malware.id,
                                relationship_type="indicates",
                                start_time=self._time_to_datetime(
                                    entry["published_parsed"]
                                ),
                                stop_time=self._time_to_datetime(
                                    entry["published_parsed"]
                                )
                                + datetime.timedelta(0, 3),
                                description="URLs associated to: "
                                + parsed_entry["type"],
                                confidence=self.confidence_level,
                                created_by_ref=organization.id,
                                object_marking_refs=[tlp["standard_id"]],
                                created=parsed_entry["date"],
                                modified=parsed_entry["date"],
                                external_references=[external_reference],
                            )
                            bundle_objects.append(relation)
                        if self.create_observables:
                            observable_url = SimpleObservable(
                                id=OpenCTIStix2Utils.generate_random_stix_id(
                                    "x-opencti-simple-observable"
                                ),
                                key="Url.value",
                                labels=["C2 Server"],
                                value=parsed_entry["url"],
                                created_by_ref=organization.id,
                                object_marking_refs=[tlp["standard_id"]],
                                external_references=[external_reference],
                            )
                            bundle_objects.append(observable_url)
                            observable_ip = SimpleObservable(
                                id=OpenCTIStix2Utils.generate_random_stix_id(
                                    "x-opencti-simple-observable"
                                ),
                                key="IPv4-Addr.value",
                                labels=["C2 Server"],
                                value=parsed_entry["ip"],
                                created_by_ref=organization.id,
                                object_marking_refs=[tlp["standard_id"]],
                                external_references=[external_reference],
                            )
                            bundle_objects.append(observable_ip)
                            observable_domain = None
                            if "domain" in parsed_entry.keys():
                                observable_domain = SimpleObservable(
                                    id=OpenCTIStix2Utils.generate_random_stix_id(
                                        "x-opencti-simple-observable"
                                    ),
                                    key="Domain-Name.value",
                                    labels=["C2 Server"],
                                    value=parsed_entry["domain"],
                                    created_by_ref=organization.id,
                                    object_marking_refs=[tlp["standard_id"]],
                                    external_references=[external_reference],
                                )
                                bundle_objects.append(observable_domain)

                            if indicator is not None:
                                relationship_1 = stix2.Relationship(
                                    id=OpenCTIStix2Utils.generate_random_stix_id(
                                        "relationship"
                                    ),
                                    relationship_type="based-on",
                                    created_by_ref=organization.id,
                                    source_ref=indicator.id,
                                    target_ref=observable_url.id,
                                )
                                bundle_objects.append(relationship_1)
                                relationship_2 = stix2.Relationship(
                                    id=OpenCTIStix2Utils.generate_random_stix_id(
                                        "relationship"
                                    ),
                                    relationship_type="based-on",
                                    created_by_ref=organization.id,
                                    source_ref=indicator.id,
                                    target_ref=observable_ip.id,
                                )
                                bundle_objects.append(relationship_2)
                                if observable_domain is not None:
                                    relationship_3 = stix2.Relationship(
                                        id=OpenCTIStix2Utils.generate_random_stix_id(
                                            "relationship"
                                        ),
                                        relationship_type="based-on",
                                        created_by_ref=organization.id,
                                        source_ref=indicator.id,
                                        target_ref=observable_domain.id,
                                    )
                                    bundle_objects.append(relationship_3)

                    # create stix bundle
                    bundle = stix2.Bundle(objects=bundle_objects)
                    # send data
                    self.helper.send_stix2_bundle(
                        bundle=bundle.serialize(),
                        update=self.update_existing_data,
                        work_id=work_id,
                    )

                    # Store the current timestamp as a last run
                    message = (
                        "Connector successfully run,  storing last_run as: {}".format(
                            str(timestamp)
                        )
                    )
                    self.helper.log_info(message)
                    self.helper.set_state({"last_run": timestamp})
                    self.helper.api.work.to_processed(work_id, message)
                    self.helper.log_info(
                        "Last_run stored, next run in: {} seconds.".format(
                            str(round(self.interval, 2))
                        )
                    )
                    time.sleep(60)
                else:
                    new_interval = self.interval - (timestamp - last_run)
                    self.helper.log_info(
                        "Connector will not run. \
                            Next run in: {} seconds.".format(
                            str(round(new_interval, 2))
                        )
                    )
                    time.sleep(60)

            except (KeyboardInterrupt, SystemExit):
                self.helper.log_info("Connector stop")
                exit(0)
            except Exception as e:
                self.helper.log_error(str(e))
                time.sleep(60)