Exemplo n.º 1
0
 def _report_sighting(self, sighting: Sighting):
     """
     Reports a STIX-2 Sighting to OpenCTI, modeled as a
     `OpenCTI.stix_sighting_relation`.
     @param sighting The STIX-2 Sighting object to report
     """
     if type(sighting) is not Sighting:
         self.opencti_helper.log_error(
             f"Error reporting sighting from Threat Bus. Expected a STIX-2 Sighting: {sighting}"
         )
         return
     entity_id = self._get_threatbus_entity().get("id", None)
     resp = self.opencti_helper.api.stix_sighting_relationship.create(
         fromId=sighting.sighting_of_ref,
         toId=entity_id,
         createdBy=entity_id,
         first_seen=sighting.first_seen.astimezone().strftime(
             "%Y-%m-%dT%H:%M:%SZ") if sighting.get("first_seen") else None,
         last_seen=sighting.last_seen.astimezone().strftime(
             "%Y-%m-%dT%H:%M:%SZ") if sighting.get("last_seen") else None,
         confidence=50,
         externalReferences=[sighting.sighting_of_ref],
         count=1,
     )
     self.opencti_helper.log_info(f"Created sighting {resp}")
Exemplo n.º 2
0
async def transform_context(sighting: Sighting, transform_cmd: str) -> Sighting:
    """
    Transforms the context of a sighting using the command configured in
    `transform_context`
    @param sighting the sighting as it was reported by VAST
    @param transform_cmd The command to use to pipe sightings to. Treated
        as template string: occurrences of '%ioc' in the cmd string get replaced
        with the matched IoC.
    @return a copy of the original sighting with the x_threatbus_context field
        set and transformed accordingly
    """
    context = (
        sighting.x_threatbus_sighting_context
        if ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value
        in sighting.object_properties()
        else None
    )
    if not context:
        logger.error(
            f"Cannot invoke `transform_context` command because no context data is found in the sighting {sighting}"
        )
        return
    indicator = (
        sighting.x_threatbus_indicator
        if ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR.value
        in sighting.object_properties()
        else None
    )
    if indicator:
        _, ioc_value = split_object_path_and_value(indicator.pattern)
    else:
        # try to find the indicator value instead
        ioc_value = (
            sighting.x_threatbus_indicator_value
            if ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR_VALUE.value
            in sighting.object_properties()
            else None
        )
    if not ioc_value:
        logger.error(
            f"Cannot invoke `transform_context` command because no indicator value is found in the sighting {sighting}"
        )
        return
    transformed_context_raw = await invoke_cmd_for_context(
        transform_cmd, context, ioc_value
    )
    try:
        transformed_context = json.loads(transformed_context_raw)
        # recreate the sighting with the new transformed context
        ser = json.loads(sighting.serialize())
        ser[
            ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value
        ] = transformed_context
        return parse(json.dumps(ser), allow_custom=True)
    except Exception as e:
        logger.error(
            f"Cannot parse transformed sighting context (expecting JSON): {transformed_context_raw}",
            e,
        )
Exemplo n.º 3
0
def matcher_result_to_sighting(matcher_result: str) -> Union[Sighting, None]:
    """
    Maps a sighting from the VAST Matcher format to a STIX-2 Sighting.
    @param matcher_result The raw sighting from VAST
    @return a valid STIX-2 Sighting that references the IoC from the VAST
        matcher or None
    """
    if type(matcher_result) is not str:
        return None
    try:
        dct = json.loads(matcher_result)
        ts = dct.get("ts", None)
        if type(ts) is str:
            ts = dateutil_parser.parse(ts)
    except Exception:
        return None
    ref = dct.get("reference", "")
    context = dct.get("context", {})
    ioc_value = dct.get("value", "")
    # ref = threatbus__indicator--46b3f973-5c03-41fc-9efe-49598a267a35
    ref_len = len(threatbus_reference) + len("indicator--") + 36
    if not ts or not ref or not len(ref) == ref_len:
        return None
    ref = ref[len(threatbus_reference) :]
    context["source"] = "VAST"
    return Sighting(
        last_seen=ts,
        sighting_of_ref=ref,
        custom_properties={
            ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value: context,
            ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR_VALUE.value: ioc_value,
        },
    )
Exemplo n.º 4
0
def query_result_to_sighting(query_result: str,
                             indicator: Indicator) -> Union[Sighting, None]:
    """
    Creates a STIX-2 Sighting from a VAST query result and the STIX-2 indicator
    that the query result refers to.
    @param query_result The VAST query result to convert
    @param indicator The STIX-2 Indicator that the query result refers to
    @return a valid STIX-2 Sighting that references the given indicator or None
    """
    global logger
    if type(query_result) is not str or type(indicator) is not Indicator:
        return None
    try:
        context = json.loads(query_result)
        ts = context.get("ts", context.get("timestamp", None))
        if not ts:
            logger.error(f"Could not find timestamp")
            return None
        ts = dateutil_parser.parse(ts)
        return Sighting(
            last_seen=ts,
            sighting_of_ref=indicator.id,
            custom_properties={
                ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value:
                context,
                ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR.value:
                indicator,
                ThreatBusSTIX2Constants.X_THREATBUS_MATCH_TYPE.value:
                MatchType.RETRO,
            },
        )
    except Exception as e:
        logger.error(f"Could not parse result {query_result} as sighting: {e}")
        return None
Exemplo n.º 5
0
def query_result_to_sighting(
    query_result: str, indicator: Indicator
) -> Union[Sighting, None]:
    """
    Creates a STIX-2 Sighting from a VAST query result and the STIX-2 indicator
    that the query result refers to.
    @param query_result The VAST query result to convert
    @param indicator The STIX-2 Indicator that the query result refers to
    @return a valid STIX-2 Sighting that references the given indicator or None
    """
    if type(query_result) is not str or type(indicator) is not Indicator:
        return None
    try:
        context = json.loads(query_result)
        context["source"] = "VAST"
        ts = context.get("ts", context.get("timestamp", None))
        if not ts:
            return None
        ts = dateutil_parser.parse(ts)
        return Sighting(
            last_seen=ts,
            sighting_of_ref=indicator.id,
            custom_properties={
                ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value: context,
                ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR.value: indicator,
            },
        )
    except Exception:
        return None
Exemplo n.º 6
0
 def test_invalid_indicator_to_vast_query(self):
     self.assertIsNone(indicator_to_vast_query(None))
     self.assertIsNone(indicator_to_vast_query(42))
     self.assertIsNone(indicator_to_vast_query(True))
     self.assertIsNone(indicator_to_vast_query("hello"))
     self.assertIsNone(
         indicator_to_vast_query(
             Sighting(sighting_of_ref=self.indicator_id)))
Exemplo n.º 7
0
 def test_invalid_indicator_to_vast_matcher_ioc(self):
     self.assertIsNone(indicator_to_vast_matcher_ioc(None))
     self.assertIsNone(indicator_to_vast_matcher_ioc(42))
     self.assertIsNone(indicator_to_vast_matcher_ioc(True))
     self.assertIsNone(indicator_to_vast_matcher_ioc("hello"))
     self.assertIsNone(
         indicator_to_vast_matcher_ioc(
             Sighting(sighting_of_ref=self.indicator_id)))
    def test_zmq_app_plugin_message_roundtrip(self):
        """
        Backend-agnostic message passing scenario. Sends a fixed amount of
        messages via the threatbus ZeroMQ app plugin, subscribes to Threat Bus,
        and checks if the initially sent messages can be retrieved back.
        """
        result_q = queue.Queue()
        items = 2
        topics = ["stix2/indicator", "stix2/sighting"]
        rec = threading.Thread(target=zmq_receiver.forward,
                               args=(items, topics, result_q),
                               daemon=False)
        rec.start()
        ioc = Indicator(pattern_type="stix",
                        pattern="[ipv4-addr:value = '6.6.6.6']")
        zmq_sender.send(
            "stix2/indicator",
            ioc.serialize(),
            port=13372,
            bind=False,
        )
        sighting = Sighting(sighting_of_ref=ioc.id)
        zmq_sender.send(
            "stix2/sighting",
            sighting.serialize(),
            port=13372,
            bind=False,
        )
        time.sleep(1)
        self.assertEqual(result_q.qsize(), items)

        event = result_q.get(timeout=1)
        self.assertIsNotNone(event)
        self.assertEqual(parse(event), ioc)
        result_q.task_done()

        event = result_q.get(timeout=1)
        self.assertIsNotNone(event)
        self.assertEqual(parse(event), sighting)
        result_q.task_done()

        self.assertEqual(0, result_q.qsize())
        result_q.join()
        rec.join(timeout=1)
Exemplo n.º 9
0
    def setUp(self):
        self.ts = datetime.now().astimezone()
        self.ioc_id = "indicator--42d31a5b-2da0-4bdd-9823-1723a98fc2fb"
        self.ioc_value = "example.com"
        self.ioc = Indicator(
            id=self.ioc_id,
            pattern_type="stix",
            pattern=f"[domain-name:value = '{self.ioc_value}']",
        )

        self.sighting_context = {
            "ts": "2017-03-03T23:56:09.652643840",
            "uid": "CMeLkt11aTqwgN4FI9",
            "id.orig_h": "172.31.130.19",
            "id.orig_p": 43872,
            "id.resp_h": "172.31.129.17",
            "id.resp_p": 20004,
            "proto": "tcp",
            "service": None,
            "duration": 0.025249,
            "orig_bytes": 311,
            "resp_bytes": 999,
            "conn_state": "SF",
            "local_orig": None,
            "local_resp": None,
            "missed_bytes": 0,
            "history": "ShADadFf",
            "orig_pkts": 9,
            "orig_ip_bytes": 787,
            "resp_pkts": 7,
            "resp_ip_bytes": 1371,
            "tunnel_parents": [],
            "alert": {
                "signature": "VAST-RETRO Generic IoC match for: 172.31.129.17",
                "category": "Potentially Bad Traffic",
                "action": "allowed",
            },
            "event_type": "alert",
            "_extra": {
                "vast-ioc": "172.31.129.17"
            },
            "source": "VAST",
        }
        self.sighting = Sighting(sighting_of_ref=self.ioc_id)

        self.snapshot_id = "SNAPSHOT_UUID"
        self.snapshot = timedelta(days=42, hours=23, minutes=13, seconds=37)
        self.snapshot_request = SnapshotRequest(MessageType.SIGHTING,
                                                self.snapshot_id,
                                                self.snapshot)

        self.snapshot_envelope_indicator = SnapshotEnvelope(
            MessageType.INDICATOR, self.snapshot_id, self.ioc)
        self.snapshot_envelope_sighting = SnapshotEnvelope(
            MessageType.SIGHTING, self.snapshot_id, self.sighting)
Exemplo n.º 10
0
def post_stix_store(owner, sighting_data, observed_data_input):
    client = MongoClient("localhost", 27018)
    db = client['stix']
    stixCollection = db['stix']
    now = datetime.utcnow() - timedelta(days=random.randint(0, 30))
    search_observables = {}
    for key, value in observed_data_input.iteritems():
        search_observables['stix.objects.0.' + key] = value
    observable_data = stixCollection.find_one({"$and": [search_observables]})

    if (observable_data):
        observable_id = observable_data["_id"]
        observed_object = ObservedData(
            number_observed=observable_data["stix"]["number_observed"] + 1,
            id=observable_id,
            created_by_ref=observable_data["stix"]["created_by_ref"],
            first_observed=observable_data["stix"]["first_observed"],
            last_observed=now,
            objects={"0": observed_data_input})
        observed_data = {
            '_id': observed_object.id,
            '_v': 0,
            'stix': observed_object
        }
        observed_id = stixCollection.find_one_and_update(
            {'_id': observed_object.id}, {'$inc': {
                'stix.count': 1
            }}, {'stix.last_observed': now.strftime("%Y-%m-%dT%H:%M:%SZ")})
    else:
        observed_object = ObservedData(number_observed=1,
                                       created_by_ref=owner,
                                       first_observed=now,
                                       last_observed=now,
                                       objects={"0": observed_data_input})
        observed_data = {
            '_id': observed_object.id,
            '_v': 0,
            'stix': observed_object
        }
        observed_id = stixCollection.insert_one(observed_data).inserted_id

    sighting_object = Sighting(
        count=1,
        first_seen=now,
        last_seen=now,
        sighting_of_ref=sighting_data['indicator_id'],
        observed_data_refs=[observed_object.id],
        where_sighted_refs=sighting_data['where_sighted_refs'],
        created_by_ref=owner,
        custom_properties={"x_unfetter_asset": sighting_data['asset']})
    sighting = {'_id': sighting_object.id, '_v': 0, "stix": sighting_object}

    sighting_id = stixCollection.insert_one(sighting).inserted_id
Exemplo n.º 11
0
def matcher_result_to_sighting(matcher_result: str) -> Union[Sighting, None]:
    """
    Maps a sighting from the VAST Matcher format to a STIX-2 Sighting.
    @param matcher_result The raw sighting from VAST
    @return a valid STIX-2 Sighting that references the IoC from the VAST
        matcher or None
    """
    global logger
    if type(matcher_result) is not str:
        return None
    try:
        dct = json.loads(matcher_result)
        event = dct["event"]
        ts = event.get("ts", event.get("timestamp", None))
        if type(ts) is str:
            ts = dateutil_parser.parse(ts)
    except Exception as e:
        logger.error(f"exception: {e}")
        return None
    ref = dct["indicator"]["context"]
    ioc_value = dct["indicator"]["value"]
    # +36 for the uuid
    # +2 for the double quotes
    ref_len = len(THREATBUS_REFERENCE) + len("indicator--") + 36 + 2
    if not ts:
        logger.error("Missing event timestamp in matcher result")
        return None
    if ref is not None:
        if len(ref) != ref_len:
            logger.error(
                f"Unexpected length: got {len(ref)}, expected {ref_len}")
            return None
        ref = ref[len(THREATBUS_REFERENCE) + 1:-1]
    if ref is None:
        # That's the minimal syntactically valid UUIDv4, see RFC 4122 / 4.1.1.
        ref = f"note--00000000-0000-4000-8000-000000000000"
    context = event
    return Sighting(
        last_seen=ts,
        sighting_of_ref=ref,
        custom_properties={
            ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value:
            context,
            ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR_VALUE.value:
            ioc_value,
            ThreatBusSTIX2Constants.X_THREATBUS_MATCH_TYPE.value:
            MatchType.LIVE,
        },
    )
Exemplo n.º 12
0
 def test_invalid_indicator_inputs(self):
     self.assertIsNone(
         map_indicator_to_broker_event(None, None, self.logger))
     self.assertIsNone(map_indicator_to_broker_event(None, "", self.logger))
     self.assertIsNone(
         map_indicator_to_broker_event(None, self.module_namespace,
                                       self.logger))
     self.assertIsNone(
         map_indicator_to_broker_event(42, self.module_namespace,
                                       self.logger))
     self.assertIsNone(
         map_indicator_to_broker_event(object, self.module_namespace,
                                       self.logger))
     self.assertIsNone(
         map_indicator_to_broker_event(
             Sighting(sighting_of_ref=self.indicator_id),
             self.module_namespace,
             self.logger,
         ))
Exemplo n.º 13
0
def stix2_sighting_to_misp(sighting: Sighting):
    """
    Maps the STIX-2 sighting format to a MISP sighting.
    @param sighting A STIX-2 Sighting object
    @return the mapped MISP sighting object or None
    """
    if not sighting or type(sighting) != Sighting:
        return None

    misp_sighting = pymisp.MISPSighting()
    source = None
    if "x_threatbus_source" in sighting.object_properties():
        source = str(sighting.x_threatbus_source)
    misp_sighting.from_dict(
        id=misp_id(sighting.sighting_of_ref),
        source=source,
        type="0",  # true positive sighting: https://www.misp-standard.org/rfc/misp-standard-core.html#sighting
        timestamp=sighting.created,
    )
    return misp_sighting
Exemplo n.º 14
0
def stixer(vulns, path):
    for vuln in vulns:
        timestamp = datetime.now()
        vuln_name = vuln['name']
        vuln_description = vuln['description']
        if args.mitigations:
            mitigation_description = get_mitigation(vuln['name'])
        else:
            mitigation_description = ""
        snippet_android = vuln['code']
        coa_name = vuln_name + "_coa"
        file_path = PurePath(vuln['file'])
        target = f"{str(file_path)}:{vuln['line']}"

        coa = CourseOfAction(type="course-of-action",
                             name=coa_name,
                             description=mitigation_description,
                             x_actions=[{
                                 "mitigation_android":
                                 "No snippet avaliable"
                             }],
                             allow_custom=True)
        vuln = Vulnerability(type="vulnerability",
                             name=vuln_name,
                             description=vuln_description,
                             vulnerable_snippet=snippet_android,
                             allow_custom=True)
        mitigates = Relationship(coa, 'mitigates', vuln)

        observed_object = File(name=target)

        observed_data = ObservedData(first_observed=timestamp,
                                     last_observed=timestamp,
                                     number_observed=1,
                                     objects={0: observed_object})
        sight = Sighting(vuln, observed_data_refs=[observed_data])
        bundle = Bundle(coa, mitigates, vuln, sight, observed_data,
                        observed_object)
        with open(f"{path}/{vuln_name}.json", "w") as f:
            f.write(str(bundle) + "\n")
Exemplo n.º 15
0
def map_bundle_to_sightings(indicator: Indicator, observations: List[Dict]):
    """
    # Generate one STIX-2 Sighting per `observed-data` entry in the list of
    STIX objects
    @param indicator: the STIX-2 indicators that all observations refer to
    @param observations: a list of STIX-2 observations to map to Sightings
    @return iterator over Sighting objects
    """
    for obj in observations:
        if obj.get("type", None) != "observed-data":
            continue
        last = dateutil_parser.parse(
            obj.get("last_observed", str(datetime.now())))
        yield Sighting(
            last_seen=last,
            sighting_of_ref=indicator.id,
            custom_properties={
                ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value:
                obj,
                ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR.value: indicator,
            },
        )
Exemplo n.º 16
0
def post_stix_store(owner, analytic):

    client = MongoClient("cti-stix-store-repository", 27017)
    db = client['stix']
    stixCollection = db['stix']
    now = datetime.datetime.utcnow()
    print "********"
    print analytic.car_data
    sighting_object = Sighting(
        count=1,
        first_seen=now,
        last_seen=now,
        sighting_of_ref=analytic.car_data['indicator_id'],
        where_sighted_refs=[owner],
        created_by_ref=owner,

    )
    sighting = {
        '_id': sighting_object.id,
        '_v': 0,
        "stix": sighting_object
    }

    sighting_id = stixCollection.insert_one(sighting).inserted_id
Exemplo n.º 17
0
def map_broker_event_to_sighting(broker_data, module_namespace, logger):
    """
    Maps a Broker message, based on the event name, to a STIX-2 indicator or
    STIX-2 Sighting.
    @param broker_data The raw data that was received via broker
    @param module_namespace A Zeek namespace to accept events from
    """
    event = broker.zeek.Event(broker_data)
    name, args = event.name(), event.args()
    module_namespace = module_namespace + "::" if module_namespace else ""
    name = name[name.startswith(module_namespace) and len(module_namespace):]
    if name != "sighting" or len(args) != 3:
        if logger:
            logger.debug(f"Discarding Broker event with unknown type: {name}")
        return None
    # convert args to STIX-2 sighting
    (timestamp, ioc_id, context) = args
    return Sighting(
        sighting_of_ref=str(ioc_id),
        last_seen=timestamp,
        custom_properties={
            ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value: context
        },
    )
Exemplo n.º 18
0
    def setUp(self):
        self.created = datetime.now().astimezone()
        self.indicator_id = "indicator--df0f9a0e-c3b6-4f53-b0cf-5e9c454ee0cc"
        self.pattern = "[ipv4-addr:value = '6.6.6.6']"
        self.pattern_type = "stix2"
        self.operation = Operation.REMOVE
        self.indicator = Indicator(
            id=self.indicator_id,
            pattern=self.pattern,
            pattern_type=self.pattern_type,
            created=self.created,
            valid_from=self.created,
            modified=self.created,
        )

        self.sighting_source = "VAST"
        self.sighting_id = "sighting--df0f9a0e-c3b6-4f53-b0cf-5e9c454ee0cc"
        self.sighting_context = {
            "ts": "2017-03-03T23:56:09.652643840",
            "uid": "CMeLkt11aTqwgN4FI9",
            "id.orig_h": "172.31.130.19",
            "id.orig_p": 43872,
            "id.resp_h": "172.31.129.17",
            "id.resp_p": 20004,
            "proto": "tcp",
            "service": None,
            "duration": 0.025249,
            "orig_bytes": 311,
            "resp_bytes": 999,
            "conn_state": "SF",
            "local_orig": None,
            "local_resp": None,
            "missed_bytes": 0,
            "history": "ShADadFf",
            "orig_pkts": 9,
            "orig_ip_bytes": 787,
            "resp_pkts": 7,
            "resp_ip_bytes": 1371,
            "tunnel_parents": [],
            "alert": {
                "signature": "VAST-RETRO Generic IoC match for: 172.31.129.17",
                "category": "Potentially Bad Traffic",
                "action": "allowed",
            },
            "event_type": "alert",
            "_extra": {
                "vast-ioc": "172.31.129.17"
            },
        }
        self.sighting = Sighting(
            id=self.sighting_id,
            created=self.created,
            modified=self.created,
            sighting_of_ref=self.indicator_id,
            custom_properties={
                ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.value:
                self.sighting_context,
                ThreatBusSTIX2Constants.X_THREATBUS_INDICATOR.value:
                self.indicator,
                ThreatBusSTIX2Constants.X_THREATBUS_SOURCE.value:
                self.sighting_source,
            },
        )

        self.snapshot_id = "SNAPSHOT_UUID"
        self.snapshot = timedelta(days=42, hours=23, minutes=13, seconds=37)
        self.snapshot_request = SnapshotRequest(MessageType.SIGHTING,
                                                self.snapshot_id,
                                                self.snapshot)

        self.snapshot_envelope_indicator = SnapshotEnvelope(
            MessageType.INDICATOR, self.snapshot_id, self.indicator)
        self.snapshot_envelope_sighting = SnapshotEnvelope(
            MessageType.SIGHTING, self.snapshot_id, self.sighting)
Exemplo n.º 19
0
 def generate_case_bundle(self, case):
     markings = []
     if case["tlp"] == 0:
         markings.append(TLP_WHITE)
     if case["tlp"] == 1:
         markings.append(TLP_GREEN)
     if case["tlp"] == 2:
         markings.append(TLP_AMBER)
     if case["tlp"] == 3:
         markings.append(TLP_RED)
     if len(markings) == 0:
         markings.append(TLP_WHITE)
     bundle_objects = []
     incident = StixXOpenCTIIncident(
         id=OpenCTIStix2Utils.generate_random_stix_id("x-opencti-incident"),
         name=case["title"],
         description=case["description"],
         first_seen=datetime.utcfromtimestamp(
             int(case["createdAt"]) / 1000).strftime("%Y-%m-%dT%H:%M:%SZ"),
         last_seen=datetime.utcfromtimestamp(
             int(case["updatedAt"]) / 1000).strftime("%Y-%m-%dT%H:%M:%SZ"),
         object_marking_refs=markings,
         labels=case["tags"] if "tags" in case else [],
         created_by_ref=self.identity["standard_id"],
     )
     bundle_objects.append(incident)
     # Get observables
     observables = self.thehive_api.get_case_observables(
         case_id=case["id"]).json()
     for observable in observables:
         if observable["dataType"] == "hash":
             if len(observable["data"]) == 32:
                 data_type = "file_md5"
             elif len(observable["data"]) == 40:
                 data_type = "file_sha1"
             elif len(observable["data"]) == 64:
                 data_type = "file_sha256"
             else:
                 data_type = "unknown"
         else:
             data_type = observable["dataType"]
         observable_key = OBSERVABLES_MAPPING[data_type]
         if observable_key is not None:
             stix_observable = SimpleObservable(
                 id=OpenCTIStix2Utils.generate_random_stix_id(
                     "x-opencti-simple-observable"),
                 key=observable_key,
                 value=observable["data"],
                 description=observable["message"],
                 x_opencti_score=80 if observable["ioc"] else 50,
                 object_marking_refs=markings,
                 labels=observable["tags"] if "tags" in observable else [],
                 created_by_ref=self.identity["standard_id"],
                 x_opencti_create_indicator=observable["ioc"],
             )
             stix_observable_relation = Relationship(
                 id=OpenCTIStix2Utils.generate_random_stix_id(
                     "relationship"),
                 relationship_type="related-to",
                 created_by_ref=self.identity["standard_id"],
                 source_ref=stix_observable.id,
                 target_ref=incident.id,
                 object_marking_refs=markings,
             )
             bundle_objects.append(stix_observable)
             bundle_objects.append(stix_observable_relation)
             if observable["sighted"]:
                 fake_indicator_id = (
                     "indicator--c1034564-a9fb-429b-a1c1-c80116cc8e1e")
                 stix_sighting = Sighting(
                     id=OpenCTIStix2Utils.generate_random_stix_id(
                         "sighting"),
                     first_seen=datetime.utcfromtimestamp(
                         int(observable["startDate"] /
                             1000)).strftime("%Y-%m-%dT%H:%M:%SZ"),
                     last_seen=datetime.utcfromtimestamp(
                         int(observable["startDate"] / 1000 +
                             3600)).strftime("%Y-%m-%dT%H:%M:%SZ"),
                     where_sighted_refs=[self.identity["standard_id"]],
                     sighting_of_ref=fake_indicator_id,
                     custom_properties={
                         "x_opencti_sighting_of_ref": stix_observable.id
                     },
                 )
                 bundle_objects.append(stix_sighting)
     bundle = Bundle(objects=bundle_objects).serialize()
     return bundle
Exemplo n.º 20
0
import zmq
import time
from stix2 import Indicator, Sighting


def send(topic, msg, host="127.0.0.1", port=50000, bind=True):
    """Sends a single, user specified message"""
    socket = zmq.Context().socket(zmq.PUB)
    if bind is True:
        socket.bind(f"tcp://{host}:{port}")
        time.sleep(0.5)
    else:
        socket.connect(f"tcp://{host}:{port}")
        time.sleep(0.5)
    # print(f"send string: {topic} {msg}")
    socket.send_string(f"{topic} {msg}")
    time.sleep(0.5)


if __name__ == "__main__":
    indicator = Indicator(
        pattern="[domain-name:value = 'evil.com']", pattern_type="stix"
    )
    sighting = Sighting(
        sighting_of_ref="indicator--629a6400-8817-4bcb-aee7-8c74fc57482c",
        custom_properties={"x_threatbus_source": "VAST"},
    )
    send("stix2/indicator", indicator.serialize(), port=13372, bind=False)
    send("stix2/sighting", sighting.serialize(), port=13372, bind=False)
Exemplo n.º 21
0
 def setUp(self):
     self.raw_ts = 1579104545
     self.ts = datetime.fromtimestamp(self.raw_ts)
     self.domain_ioc = "example.com"
     self.ip_ioc = "example.com"
     self.pattern = f"[domain-name:value = '{self.domain_ioc}'] AND [ipv4-addr:value = '{self.ip_ioc}']"
     self.attr_uuid = "5e1f2787-fcfc-4718-a58a-00b4c0a82f06"
     self.indicator_id = f"indicator--{self.attr_uuid}"
     self.indicator = Indicator(
         id=self.indicator_id,
         created=self.ts,
         pattern_type="stix",
         pattern=self.pattern,
     )
     self.sighting = Sighting(created=self.ts, sighting_of_ref=self.indicator_id)
     self.valid_misp_attribute = {
         "id": self.id,
         "event_id": "1",
         "object_id": "0",
         "object_relation": None,
         "category": "Network activity",
         "type": "domain|ip",
         "value1": self.domain_ioc,
         "value2": self.ip_ioc,
         "to_ids": True,
         "uuid": self.attr_uuid,
         "timestamp": str(self.raw_ts),
         "distribution": "5",
         "sharing_group_id": "0",
         "comment": "",
         "deleted": False,
         "disable_correlation": False,
         "value": f"{self.domain_ioc}|{self.ip_ioc}",
         "Sighting": [],
         "Tag": [],
     }
     self.valid_misp_msg = json.loads(
         """{
     "Attribute": {
         "id": "1",
         "event_id": "1",
         "object_id": "0",
         "object_relation": null,
         "category": "Network activity",
         "type": "ip-src",
         "value1": "6.6.6.6",
         "value2": "",
         "to_ids": true,
         "uuid": "5f7b2284-bdd8-4ef4-b457-032ac0a82f02",
         "timestamp": "1601906335",
         "distribution": "5",
         "sharing_group_id": "0",
         "comment": "",
         "deleted": false,
         "disable_correlation": false,
         "first_seen": null,
         "last_seen": null,
         "value": "6.6.6.6",
         "Tag": [
         {
             "id": "3",
             "name": "baz",
             "colour": "#05ff00",
             "exportable": true
         },
         {
             "id": "1",
             "name": "foo",
             "colour": "#ff0000",
             "exportable": true
         }
         ],
         "Sighting": []
     },
     "Event": {
         "id": "1",
         "date": "2020-10-05",
         "info": "evil",
         "uuid": "5f7b2277-1ebc-4101-9152-032ac0a82f02",
         "published": false,
         "analysis": "0",
         "threat_level_id": "1",
         "org_id": "1",
         "orgc_id": "1",
         "distribution": "1",
         "sharing_group_id": "0",
         "Orgc": {
         "id": "1",
         "uuid": "5f7b21ea-52a4-49f0-87df-032ac0a82f02",
         "name": "ORGNAME"
         }
     },
     "action": "edit"
     }
     """
     )