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)
Пример #2
0
    def test_zeek_plugin_message_roundtrip(self):
        """
            Backend agnostic message passing screnario. Sends a single MISP
            Attribute via ZeroMQ to the threatbus MISP plugin, subscribes via
            broker to threatbus, and checks if the initially sent message got
            parsed and forwarded correctly as new Intelligence item.
        """
        misp_json_attribute = """{
            "Attribute": {
                "id": "15",
                "event_id": "1",
                "object_id": "0",
                "object_relation": null,
                "category": "Network activity",
                "type": "domain",
                "value1": "example.com",
                "value2": "",
                "to_ids": false,
                "uuid": "5e1f2787-fcfc-4718-a58a-00b4c0a82f06",
                "timestamp": "1579104545",
                "distribution": "5",
                "sharing_group_id": "0",
                "comment": "",
                "deleted": false,
                "disable_correlation": false,
                "value": "example.com",
                "Sighting": []
            },
            "Event": {
                "id": "1",
                "date": "2020-01-15",
                "info": "adsf",
                "uuid": "5e1ee79d-25c8-42bd-a386-0291c0a82f06",
                "published": false,
                "analysis": "0",
                "threat_level_id": "1",
                "org_id": "1",
                "orgc_id": "1",
                "distribution": "3",
                "sharing_group_id": "0",
                "Orgc": {
                    "id": "1",
                    "uuid": "5e1edc98-3984-4321-9003-018bfb195b64",
                    "name": "ORGNAME"
                }
            },
            "action": "edit"
        }"""

        # emulate a zeek subscriber for intel items
        result_q = queue.Queue()
        rec = threading.Thread(
            target=zeek_receiver.forward,
            args=(1, result_q, "tenzir/threatbus/intel"),
            daemon=False,
        )
        rec.start()

        zmq_sender.send(misp_json_attribute)

        # wait for threatbus to forward intel
        zeek_intel = result_q.get(block=True)
        result_q.task_done()
        result_q.join()
        rec.join()

        self.assertEqual(
            zeek_intel,
            [
                (
                    "Tenzir::intel",
                    None,
                    "15",
                    {"indicator": "example.com", "intel_type": "DOMAIN"},
                )
            ],
        )
Пример #3
0
    def test_intel_sighting_roundtrip(self):
        """
        Backend-agnostic roundtrip scenario, that starts a Zeek subprocess which
        activates the threatbus.zeek "app" script.
        The test sends an IoC with a malicious hostname via Threat Bus, using
        the ZMQ app plugin. Meanwhile, the Zeek subprocess reads a PCAP trace
        which contains exactly that malicious hostname from the IoC.
        If all goes well, Zeek subscribes to Threat Bus successfully, receives
        the IoC and hence reading the PCAP file results in a sighting. Zeek
        forwards that sighting to the Threat Bus Zeek plugin, where it is
        converted to a valid STIX-2 Sighting.
        The integration test subscribes a ZMQ receiver to the `stix2/sighting`
        topic and verifies all Zeek communication was handled correctly. I.e.,
        Zeek matched the IoC and reported the correct sighting.
        """
        # Start a ZMQ receiver that subscribes to the `stix2/sighting` topic and
        # forward exactly 1 item to a result queue
        result_q = queue.Queue()
        rec = threading.Thread(
            target=zmq_receiver.forward,
            args=(1, ["stix2/sighting"], result_q),
            daemon=True,
        )
        rec.start()

        # Spawn a Zeek subprocess that runs the `apps/zeek/threatbus.zeek`
        # script and reads a prepared PCAP trace that contains a network
        # connection to `example.com`
        zeek_process = RunZeek()
        if not zeek_process:
            self.fail("Error starting Zeek container.")

        # Let Zeek start up...
        time.sleep(1)

        # Send a new indicator (IoC) via the ZMQ test-util, which will be
        # forwarded to Zeek because Zeek subscribes to `stix2/indicator`
        ioc_id = "indicator--42d31a5b-2da0-4bdd-9823-1723a98fc2fb"
        ioc = Indicator(
            id=ioc_id,
            pattern_type="stix",
            pattern="[domain-name:value = 'example.com']",
        )
        zmq_sender.send("stix2/indicator",
                        ioc.serialize(),
                        port=13372,
                        bind=False)

        # Wait for Zeek to ingest the IoC into its Intel framework, read the
        # PCAP trace and report back the sighting
        raw_msg = result_q.get(timeout=10)
        sighting = parse(raw_msg, allow_custom=True)
        result_q.task_done()

        self.assertIsNotNone(sighting)
        self.assertEqual(sighting.sighting_of_ref, ioc_id)
        self.assertTrue(ThreatBusSTIX2Constants.X_THREATBUS_SIGHTING_CONTEXT.
                        value in sighting)
        self.assertEqual(sighting.x_threatbus_sighting_context,
                         {"noisy": False})

        rec.join()
        result_q.join()
        zeek_process.kill()
        self.assertTrue(StopZeek())