Example #1
0
    def add_misp_tag(self, tag_name, tag_color) -> Optional[dict]:
        """
        Create a new tag in MISP
        :param tag_name: Name of the new tag
        :param tag_color: Color of the new tag
        :return: Server response if succesful, else None
        """
        LOGGER.debug(f'Creating a {tag_name} tag in MISP')

        if not self.verify_tls:
            urllib3.disable_warnings()
        response = requests.post(f'{self.protocol}://{self.host}/tags/add',
                                 json={
                                     'name': tag_name,
                                     'colour': tag_color
                                 },
                                 headers={
                                     'Authorization': self.token,
                                     'Accept': 'application/json'
                                 },
                                 timeout=10,
                                 verify=self.verify_tls)
        try:
            response.raise_for_status()
            return response.json()
        except requests.HTTPError:
            LOGGER.critical(
                f'Creating MISP Tag responded with status code:{response.status_code}'
            )
            return None
Example #2
0
    def add_misp_tag_to_event(self, event_id, tag_id):
        """
        Add MISP tag to MISP event
        :param event_id:
        :param tag_id:
        :return:
        """
        LOGGER.debug('Adding DDoSCH tag to the event')

        if not self.verify_tls:
            urllib3.disable_warnings()
        response = requests.post(
            f'{self.protocol}://{self.host}/events/addTag/{event_id}/{tag_id}',
            headers={
                'Authorization': self.token,
                'Accept': 'application/json'
            },
            timeout=10,
            verify=self.verify_tls)
        LOGGER.debug(f'status: {response.status_code}')

        try:
            response.raise_for_status()
            return response.json()
        except requests.HTTPError:
            LOGGER.critical(
                f'Creating MISP Tag responded with status code:{response.status_code}'
            )
            return None
Example #3
0
    def search_misp_events(self, misp_filter: dict = None) -> Optional[dict]:
        """
        Search for MISP events
        :param misp_filter: fields by which to filter retrieved MISP events
        :return: MISP events if found, else None
        """
        LOGGER.debug(f'Searching MISP events with filter: {misp_filter}')

        if not self.verify_tls:
            urllib3.disable_warnings()

        response = requests.post(f'{self.protocol}://{self.host}/events/index',
                                 json=misp_filter or dict(),
                                 headers={
                                     'Authorization': self.token,
                                     'Accept': 'application/json'
                                 },
                                 timeout=10,
                                 verify=self.verify_tls)

        try:
            response.raise_for_status()
            return response.json()
        except requests.HTTPError:
            LOGGER.critical(
                f'Retrieving MISP events responded with status code:{response.status_code}'
            )
            return None
Example #4
0
    def pauseRunner(self):
        if self.dut.task_runner.b_started:
            self.dut.pauseRunner()
            self.actionRun.setEnabled(True)
            self.actionPause.setDisabled(True)

            #self.self.dut.task_runner.b_started = False
            #self.dut.task_runner.scenario_level_pause = True
            LOGGER.critical("Pause task runner")
Example #5
0
    def __init__(self, host: str, token: str, protocol: str, verify_tls: bool):
        self.host = host
        self.token = token
        self.protocol = protocol
        self.verify_tls = verify_tls
        self.misp: ExpandedPyMISP

        try:
            self.misp = ExpandedPyMISP(f'{self.protocol}://{self.host}',
                                       self.token,
                                       ssl=self.verify_tls,
                                       tool='dissector')
        except PyMISPError:
            LOGGER.critical(
                f'Could not connect to MISP instance at "{self.protocol}://{self.host}".'
            )
            self.misp = None
Example #6
0
    def upload_to_misp(self, misp_instance: MispInstance) -> int:
        """
        Upload fingerprint to a MISP instance
        :param misp_instance: MISP instance to which to upload the fingerprint
        :return: HTTP response code
        """
        LOGGER.info(f'Uploading fingerprint to MISP: {misp_instance.host}')

        fingerprint_json = self.as_dict(anonymous=not self.show_target)

        misp_filter = {
            'minimal': True,
            'tag': 'DDoSCH',
            'eventinfo': self.checksum,
        }

        LOGGER.debug(
            f'Checking if fingerprint {self.checksum} is already present in the MISP'
        )
        try:
            misp_events = misp_instance.search_misp_events(misp_filter)
        except requests.exceptions.SSLError:
            LOGGER.critical(
                f'SSL Certificate verification of the server {misp_instance.host} failed. '
                f'To ignore the certificate pass the --noverify flag.')
            LOGGER.info('Fingerprint NOT uploaded.')
            return 500

        if misp_events:
            LOGGER.critical(
                'The fingerprint already exists in this MISP instance.')
            LOGGER.info('Fingerprint NOT uploaded.')
            return 500

        misp_instance.add_misp_fingerprint(fingerprint_json)

        return 201
Example #7
0
def infer_target(attack: Attack) -> IPNetwork:
    """
    Infer the target IP address(es) of this attack.
    If the target is a subnet, this method will homogenize the IP adresses in the attack to the first address in the
    subnet.
    :param attack: Attack object of which to determine the target IP address or network
    :return: Target IP address as an IPNetwork
    """
    LOGGER.debug("Inferring attack target.")
    targets: list[IPAddress] = get_outliers(attack.data,
                                            column='destination_address',
                                            fraction_for_outlier=0.5,
                                            use_zscore=False)
    if len(targets) > 0:
        return IPNetwork(targets[0])

    LOGGER.info('No clear target IP address could be inferred.')
    # Ask the user if the most common destination address (most packets received) is the target
    packets_per_ip = attack.data.groupby(
        'destination_address').nr_packets.sum().sort_values(ascending=False)
    most_traffic_address, nr_packets = list(packets_per_ip.items())[0]
    use_most_common = input(
        f'The most common destination address is {most_traffic_address} '
        f'({round(nr_packets / packets_per_ip.sum() * 100, 1)}% of captured packets), '
        f'is this the target? y/n: ')
    if use_most_common.lower().strip() in ['y', 'yes']:
        return IPNetwork(most_traffic_address)

    LOGGER.info(
        'You can pass a target IP address with the --target flag. '
        'Alternatively, Dissector can look for a target subnet (IPv4/24 or IPv6/64) in case of a carpet '
        'bombing attack.')
    keep_going = input('Continue looking for a target subnet? y/n: ')
    if keep_going.lower().strip() not in ['y', 'yes']:
        LOGGER.info('Aborting.')
        sys.exit()

    # Check for the most targeted IP addresses the fraction of destination IPs that is in their /24 or /64 subnet
    best_network, fraction_ips_in_network = None, 0
    for target in packets_per_ip.keys()[:25]:
        network = IPNetwork(f'{target}/{"24" if target.version == 4 else "64"}'
                            )  # /24 (IPv4) or /64 (IPv6) subnet
        frac = packets_per_ip[[
            x for x in packets_per_ip.keys() if x in network
        ]].sum() / packets_per_ip.sum()
        if frac > fraction_ips_in_network:
            best_network, fraction_ips_in_network = network, frac

    if fraction_ips_in_network > 0.7:
        LOGGER.debug(
            f'Found an IP subnet that comprises a large fraction of the flows\' destination IPs '
            f'({round(fraction_ips_in_network, 2)}).')
    else:
        LOGGER.critical(
            'Could not infer a clear target IP address from the data. You can explicitly identify the '
            'target with the --target flag.')
        use_target = input(
            f'The most prominent destination IP network is {best_network}, with '
            f'{round(fraction_ips_in_network * 100, 1)}% of packets. '
            f'Is this the target of this attack? y/n: ')
        if use_target.lower() not in ['y', 'yes']:
            sys.exit(-1)

    return best_network
Example #8
0
    def upload_to_ddosdb(self,
                         host: str,
                         token: str,
                         protocol: str = 'https',
                         noverify: bool = False) -> int:
        """
        Upload fingerprint to a DDoS-DB instance
        :param host: hostname of the DDoS-DB instance, without schema (like db.example.com)
        :param token: DDoS-DB Authorization Token
        :param protocol: Protocol to use (http or https)
        :param noverify: (bool) ignore invalid TLS certificate
        :return: HTTP response code
        """
        LOGGER.info(f'Uploading fingerprint to DDoS-DB: {host}...')

        fp_json = json.dumps(self.as_dict(anonymous=not self.show_target))
        headers = {'Authorization': f'Token {token}'}

        try:
            try:
                if noverify:
                    urllib3.disable_warnings()
                r = requests.post(f'{protocol}://{host}/api/fingerprint/',
                                  json=fp_json,
                                  headers=headers,
                                  verify=not noverify)
            except requests.exceptions.SSLError:
                LOGGER.critical(
                    f'SSL Certificate verification of the server {host} failed. To ignore the certificate '
                    f'pass the --noverify flag.')
                LOGGER.info('Fingerprint NOT uploaded to DDoS-DB')
                return 500
        except requests.exceptions.RequestException as e:
            LOGGER.critical(
                'Cannot connect to the DDoS-DB server to upload fingerprint')
            LOGGER.debug(e)
            return 500

        if r.status_code == 403:
            LOGGER.critical(
                'Invalid DDoS-DB credentials or no permission to upload fingerprints.'
            )
        elif r.status_code == 413:
            LOGGER.critical(
                'Fingerprint is too large to upload to this DDoS-DB instance.')
        elif r.status_code == 201:
            LOGGER.info(
                f'Upload success! URL: https://{host}/details?key={self.checksum}'
            )
        else:
            LOGGER.critical('DDoS-DB Internal Server Error.')
            LOGGER.critical('Error Code: {}'.format(r.status_code))
        return r.status_code