Exemplo n.º 1
0
 def getMISPData(self, since=None):
   # Connect to your MISP API 
   misp = PyMISP(self.url, self.key, True, 'json')
   since = since if since else "5d"
   if since.lower() == "all": since = "" 
   misp_last = misp.download_last(since)
   # Verify output
   if 'message' in misp_last.keys():
     if misp_last['message'].lower().startswith('no matches'):
       return [] # No output
     elif misp_last['message'].startswith('Authentication failed.'):
       raise Exception("[-] MISP Authentication failed")
   if not 'response' in misp_last:
     raise Exception("[-] Error occured while fetching MISP data")
   return misp_last['response']
Exemplo n.º 2
0
 def onDatabaseUpdate(self):
   lastUpdate = db.p_readSetting(self.collectionName, "last_update")
   now = datetime.utcnow().replace(tzinfo = pytz.utc)
   if lastUpdate:
     last  = dateutil.parser.parse(lastUpdate)
     delta = now - last
     since = "%sm"%math.ceil(delta.total_seconds()/60)
   else:
     since = ""
   if self.url and self.key:
     try:
       # Misp interface
       misp = PyMISP(self.url, self.key, True, 'json')
     except:
       return "[-] Failed to connect to MISP. Wrong URL?"
     try:
       # Fetch data
       misp_last = misp.download_last(since)
       # Check data
       if 'message' in misp_last.keys():
         if misp_last['message'].lower().startswith('no matches'):       return "[+] MISP collection updated (0 updates)"
         elif misp_last['message'].startswith('Authentication failed.'): return "[-] MISP Authentication failed"
       if not 'response' in misp_last:   print(misp_last);               return "[-] Error occured while fetching MISP data"
       # Nothing wrong so far, so let's continue
       bulk =[]
       for entry in progressbar(misp_last['response']):
         # Get info
         attrs=entry['Event']['Attribute']
         CVEs=   [x['value'] for x in attrs if x['type'] == 'vulnerability']
         if len(CVEs) == 0: continue
         threats=    [x['value'] for x in attrs if x['category'] == 'Attribution'       and x['type'] == 'threat-actor']
         tags   =    [x['value'] for x in attrs if x['category'] == 'Other'             and x['type'] == 'text']
         tags.extend([x['value'] for x in attrs if x['category'] == 'External analysis' and x['type'] == 'text'])
         # Add info to each CVE
         for cve in CVEs:
           item={'id':cve}
           if len(threats) !=0: item['threats'] = threats
           if len(tags)    !=0: item['tags'] = tags
           if len(item.keys())>1: bulk.append(item) # Avoid empty collections
       db.p_bulkUpdate(self.collectionName, "id", bulk)
       #update database info after successful program-run
       db.p_writeSetting(self.collectionName, "last_update", now.strftime("%a, %d %h %Y %H:%M:%S %Z"))
       return "[+] MISP collection updated (%s updates)"%len(bulk)
     except Exception as e: print(e);print(e);return "[-] Something went wrong..."
   else:     return "[-] MISP credentials not specified"
Exemplo n.º 3
0
    def getLastMispAttributes(self, mispName: str, url: str, apiKey: str,
                              last: int) -> dict:
        '''
        Receive events from MISP instance, grab all the indicators
        from fetched events

        :param url: MISP instance URL
        :param key: MISP API token
        :param last: Fetch only last event, e.g. 1d or 5d
        '''

        logger.logEvent().info(
            "MISP integration started - trying to get last events...")

        startTime = datetime.now()

        MISP = PyMISP(url, apiKey, False, 'json')
        events = MISP.download_last(last)

        if events:
            if 'response' in events:
                iocs = self.__mispEventsProcess(events['response'])

                endTime = datetime.now()
                delta = endTime - startTime

                logger.logEvent().info(
                    'MISP integration finished. Obtained {0} IoCs from `{1}` in {2} sec {3} msec'
                    .format(
                        iocs['totalIocs'],
                        mispName,
                        delta.seconds,
                        delta.microseconds,
                    ), )
            else:
                logger.logEvent().info(
                    'MISP integration finished. No results for that time period.'
                )

            return iocs
Exemplo n.º 4
0
class MISPReceiver():

    hash_iocs = {}
    filename_iocs = {}
    c2_iocs = {}
    yara_rules = {}

    debugon = False

    # Output
    siem_mode = False
    separator = ";"
    use_headers = False
    use_filename_regex = True

    def __init__(self, misp_key, misp_url, misp_verify_cert, siem_mode=False, debugon=False):
        self.misp = PyMISP(misp_url, misp_key, misp_verify_cert, 'json')
        self.debugon = debugon
        if siem_mode:
            self.siem_mode = True
            self.separator = ","
            self.use_headers = True
            self.use_filename_regex = False

    def get_iocs_last(self, last):

        # Retrieve events from MISP
        result = self.misp.download_last(last)
        self.events = result['response']

        # Process each element (without related eevents)
        for event_element in self.events:
            event = event_element["Event"]

            # Info for Comment
            info = event['info']
            uuid = event['uuid']
            comment = "{0} - UUID: {1}".format(info.encode('unicode_escape'), uuid)

            # Event data
            for attribute in event['Attribute']:

                # Skip iocs that are not meant for ioc detection
                if attribute['to_ids'] == False:
                    continue

                # Value
                value = attribute['value']

                # Non split type
                if '|' not in attribute['type']:
                    self.add_ioc(attribute['type'], value, comment, uuid, info)
                # Split type
                else:
                    # Prepare values
                    type1, type2 = attribute['type'].split('|')
                    value1, value2 = value.split('|')
                    # self.add_ioc(type1, value1, comment)
                    self.add_ioc(type2, value2, comment, uuid, info)

    def add_ioc(self, ioc_type, value, comment, uuid, info):
        # Cleanup value
        value = value.encode('unicode_escape')
        # Debug
        if self.debugon:
            print "{0} = {1}".format(ioc_type, value)
        # C2s
        if ioc_type in ('hostname', 'ip-dst', 'domain'):
            if value == '127.0.0.1':
                return
            self.c2_iocs[value] = comment
        # Hash
        if ioc_type in ('md5', 'sha1', 'sha256'):
            # No empty files
            if value == 'd41d8cd98f00b204e9800998ecf8427e' or \
                            value == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' or \
                            value == 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855':
                return
            self.hash_iocs[value] = comment
        # Filenames
        if ioc_type in ('filename', 'filepath'):
            # Add prefix to filenames
            if not re.search(r'^([a-zA-Z]:|%)', value):
                if not self.siem_mode:
                    value = "\\\\{0}".format(value)
            if self.use_filename_regex:
                self.filename_iocs[my_escape(value)] = comment
            else:
                self.filename_iocs[value.decode('string_escape')] = comment
        # Yara
        if ioc_type in ('yara'):
            self.add_yara_rule(value, uuid, info)

    def add_yara_rule(self, yara_rule, uuid, info):
        identifier = generate_identifier(info)
        self.yara_rules[identifier] = ur'%s' % repair_yara_rule(yara_rule.decode('string_escape'), uuid)

    def write_iocs(self, output_path, output_path_yara):
        # Write C2 IOCs
        self.write_file(os.path.join(output_path, "misp-c2-iocs.txt"), self.c2_iocs, "c2")
        # Write Filename IOCs
        self.write_file(os.path.join(output_path, "misp-filename-iocs.txt"), self.filename_iocs, "filename")
        # Write Hash IOCs
        self.write_file(os.path.join(output_path, "misp-hash-iocs.txt"), self.hash_iocs, "hash")
        # Yara
        if len(self.yara_rules) > 0:
            # Create dir if not exists
            if not os.path.exists(output_path_yara):
                os.makedirs(output_path_yara)
            # Loop through rules (keys are identifiers used for file names)
            for yara_rule in self.yara_rules:
                output_rule_filename = os.path.join(output_path_yara, "%s.yar" % yara_rule)
                self.write_yara_rule(output_rule_filename, self.yara_rules[yara_rule])
            print "{0} YARA rules written to directory {1}".format(len(self.yara_rules), output_path_yara)

    def write_file(self, ioc_file, iocs, ioc_type):
        with open(ioc_file, 'w') as file:
            if self.use_headers:
                file.write("{0}{1}description\n".format(ioc_type, self.separator))
            for ioc in iocs:
                file.write("{0}{2}{1}\n".format(ioc,iocs[ioc],self.separator))
        print "{0} IOCs written to file {1}".format(len(iocs), ioc_file)

    def write_yara_rule(self, yara_file, yara_rule):
        # Write the YARA rule
        with io.open(yara_file, 'wb') as fh:
            fh.write(ur'%s' % yara_rule)
Exemplo n.º 5
0
class MISPReceiver():

    hash_iocs = {}
    filename_iocs = {}
    c2_iocs = {}
    yara_rules = {}

    debugon = False

    # Output
    siem_mode = False
    separator = ";"
    use_headers = False
    use_filename_regex = True

    def __init__(self, misp_key, misp_url, misp_verify_cert, siem_mode=False, debugon=False):
        self.misp = PyMISP(misp_url, misp_key, misp_verify_cert, 'json')
        self.debugon = debugon
        if siem_mode:
            self.siem_mode = True
            self.separator = ","
            self.use_headers = True
            self.use_filename_regex = False

    def get_iocs_last(self, last):

        # Retrieve events from MISP
        result = self.misp.download_last(last)
        self.events = result['response']

        # Process each element (without related eevents)
        for event_element in self.events:
            event = event_element["Event"]

            # Info for Comment
            info = event['info']
            uuid = event['uuid']
            comment = "{0} - UUID: {1}".format(info.encode('unicode_escape'), uuid)

            # Event data
            for attribute in event['Attribute']:

                # Skip iocs that are not meant for ioc detection
                if attribute['to_ids'] == False:
                    continue

                # Value
                value = attribute['value']

                # Non split type
                if '|' not in attribute['type']:
                    self.add_ioc(attribute['type'], value, comment, uuid, info)
                # Split type
                else:
                    # Prepare values
                    type1, type2 = attribute['type'].split('|')
                    value1, value2 = value.split('|')
                    # self.add_ioc(type1, value1, comment)
                    self.add_ioc(type2, value2, comment, uuid, info)

    def add_ioc(self, ioc_type, value, comment, uuid, info):
        # Cleanup value
        value = value.encode('unicode_escape')
        # Debug
        if self.debugon:
            print "{0} = {1}".format(ioc_type, value)
        # C2s
        if ioc_type in ('hostname', 'ip-dst', 'domain'):
            if value == '127.0.0.1':
                return
            self.c2_iocs[value] = comment
        # Hash
        if ioc_type in ('md5', 'sha1', 'sha256'):
            # No empty files
            if value == 'd41d8cd98f00b204e9800998ecf8427e' or \
                            value == 'da39a3ee5e6b4b0d3255bfef95601890afd80709' or \
                            value == 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855':
                return
            self.hash_iocs[value] = comment
        # Filenames
        if ioc_type in ('filename', 'filepath'):
            # Add prefix to filenames
            if not re.search(r'^([a-zA-Z]:|%)', value):
                if not self.siem_mode:
                    value = "\\\\{0}".format(value)
            if self.use_filename_regex:
                self.filename_iocs[my_escape(value)] = comment
            else:
                self.filename_iocs[value.decode('string_escape')] = comment
        # Yara
        if ioc_type in ('yara'):
            self.add_yara_rule(value, uuid, info)

    def add_yara_rule(self, yara_rule, uuid, info):
        identifier = generate_identifier(info)
        self.yara_rules[identifier] = ur'%s' % repair_yara_rule(yara_rule.decode('string_escape'), uuid)

    def write_iocs(self, output_path, output_path_yara):
        # Write C2 IOCs
        self.write_file(os.path.join(output_path, "misp-c2-iocs.txt"), self.c2_iocs, "c2")
        # Write Filename IOCs
        self.write_file(os.path.join(output_path, "misp-filename-iocs.txt"), self.filename_iocs, "filename")
        # Write Hash IOCs
        self.write_file(os.path.join(output_path, "misp-hash-iocs.txt"), self.hash_iocs, "hash")
        # Yara
        if len(self.yara_rules) > 0:
            # Create dir if not exists
            if not os.path.exists(output_path_yara):
                os.makedirs(output_path_yara)
            # Loop through rules (keys are identifiers used for file names)
            for yara_rule in self.yara_rules:
                output_rule_filename = os.path.join(output_path_yara, "%s.yar" % yara_rule)
                self.write_yara_rule(output_rule_filename, self.yara_rules[yara_rule])
            print "{0} YARA rules written to directory {1}".format(len(self.yara_rules), output_path_yara)

    def write_file(self, ioc_file, iocs, ioc_type):
        with open(ioc_file, 'w') as file:
            if self.use_headers:
                file.write("{0}{1}description\n".format(ioc_type, self.separator))
            for ioc in iocs:
                file.write("{0}{2}{1}\n".format(ioc,iocs[ioc],self.separator))
        print "{0} IOCs written to file {1}".format(len(iocs), ioc_file)

    def write_yara_rule(self, yara_file, yara_rule):
        # Write the YARA rule
        with io.open(yara_file, 'wb') as fh:
            fh.write(ur'%s' % yara_rule)
Exemplo n.º 6
0
class MispCollector(CollectorWithStateMixin, BaseCollector):

    output_queue = [
        {
            'exchange': 'raw',
            'exchange_type': 'topic',
        },
        {
            'exchange': 'sample',
            'exchange_type': 'topic',
        },
    ]

    type = 'stream'
    content_type = "application/json"
    config_required = ("source",
                       "misp_url",
                       "misp_key",
                       "cache_dir",
                       "days_for_first_run")

    # a list of sample details' keys included in a message's headers
    sample_message_headers = [
        'category',
        'comment',
        'uuid',
        'event_id',
        'timestamp',
        'to_ids',
        'value',
        'distribution',
        'type',
        'id',
    ]
    # part of the MISP URL to the attributes' files
    default_sample_path = '/attributes/downloadAttachment/download/'

    allowed_tlp_vals = (
        'red',
        'amber',
        'green',
        'white',
    )
    min_tlp_key_name = 'minimum_tlp'

    def __new__(cls, **kwargs):
        self = super(MispCollector, cls).__new__(cls, **kwargs)
        MispCollector.config_group = self.cmdline_args.n6config_section_name
        return self

    def __init__(self, **kwargs):
        super(MispCollector, self).__init__(**kwargs)
        self._now = datetime.now().replace(microsecond=0)
        self._state = self._load_state_or_get_default()
        self._last_events_publishing_datetime = self._state['events_publishing_datetime']
        self._last_samples_publishing_datetime = self._state['samples_publishing_datetime']
        if self._last_samples_publishing_datetime < self._last_events_publishing_datetime:
            self._overdue_samples_to_publish = True
        else:
            self._overdue_samples_to_publish = False
        self._establish_connection()
        self._publishing_samples = False
        self._callback_timeout = int(self.config.get('callback_timeout', 1))
        self._misp_events = None
        self._misp_raw_events = None
        self._output_components = None
        self._samples = None
        self._possible_attribute_types = ['malware-sample']
        sample_path = self.config.get('sample_path', self.default_sample_path)
        self._attributes_url = urljoin(self.config['misp_url'], sample_path)

    # initial methods
    def run(self):
        try:
            self._misp_events = self.get_output_components()
        except NoNewEventsException:
            self._state['events_publishing_datetime'] = self._now
            self.save_state(self._state)
            if self._overdue_samples_to_publish:
                LOGGER.info('No new events, but there are overdue malware samples to publish.')
                super(MispCollector, self).run()
            else:
                LOGGER.info('No new events nor malware samples, closing the collector.')
                self._set_samples_state_to_completed()
        else:
            super(MispCollector, self).run()

    def _load_state_or_get_default(self):
        state = self.load_state()
        if not state or not isinstance(state, MutableMapping):
            _days = int(self.config['days_for_first_run'])
            initial_datetime = self._now - timedelta(days=_days)
            return dict(
                events_publishing_datetime=initial_datetime,
                samples_publishing_datetime=initial_datetime,
                last_published_samples=[],
            )
        else:
            assert state['samples_publishing_datetime'] <= state['events_publishing_datetime'], (
                "Datetime of the last publishing of samples has to be equal or smaller "
                "than a datetime of publishing of the events.")
        return state

    def _set_samples_state_to_completed(self):
        """
        Set the state of publishing of malware samples, as if
        it is completed. Set the datetime to the current time
        and date and clear the list of published samples.
        """
        self._state['samples_publishing_datetime'] = self._now
        del self._state['last_published_samples'][:]
        self.save_state(self._state)

    def _convert_datetime_to_timestamp(self, datetime_):
        dif_time = (self._now - datetime_).total_seconds()/60+15
        return '{:.0f}m'.format(dif_time)

    def get_arg_parser(self):
        arg_parser = super(MispCollector, self).get_arg_parser()
        arg_parser.add_argument(
            'n6config_section_name',
            help='the config section name specific to the chosen MISP collector, e.g.: misp_circl')
        return arg_parser

    def _establish_connection(self):
        misp_url = self.config['misp_url']
        misp_key = self.config['misp_key']
        misp_verifycert = self.get_misp_verifycert()
        self.misp = PyMISP(url=misp_url, key=misp_key, ssl=misp_verifycert)

    # scheduling and publishing methods
    @exiting_on_exception
    def start_publishing(self):
        """
        Schedule publishing of MISP events or downloading of
        the overdue samples.
        """
        if self._misp_events:
            self._schedule(self._do_publish_events)
        else:
            self._schedule(self._prepare_and_schedule_samples_publishing)

    def _prepare_request_headers(self):
        return {'content-type': 'application/zip',
                'Accept': 'application/json',
                'Authorization': self.config['misp_key'],
                'User-Agent': 'PyMISP {} - Python {}.{}.{}'.format(pymisp_version,
                                                                   *sys.version_info)}

    def _schedule(self, meth):
        """
        Add a callback method to the IOLoop timer.

        Args:
            `meth`:
                method passed as a callback for Pika's connection
                add_timeout() method.
        """
        if self._closing:
            LOGGER.warning(
                'Collector %r is being closed so %r will *not* be scheduled', self, meth)
            return
        self._connection.add_timeout(self._callback_timeout, exiting_on_exception(meth))

    def _next_download(self):
        """
        If available, take details about the next malware sample
        and try to download it.

        Raises:
            `SampleDownloadFailure` exception if a sample could not
            be downloaded.
        """
        try:
            self._current_sample = self._samples.popleft()
        except IndexError:
            # an empty list of the last published samples indicates,
            # that all of the samples have been published
            self._set_samples_state_to_completed()
            self.inner_stop()
        else:
            try:
                self._output_components = self.get_output_components()
            except SampleDownloadFailure:
                LOGGER.warning("Cannot download sample with ID: %s.", self._current_sample['id'])
                self._schedule(self._next_download)
            else:
                self._schedule(self._do_publish)

    def _do_publish_events(self):
        """
        Publish MISP events, save the state. Extract details about
        malware samples and proceed to prepare malware samples
        downloading and publishing.
        """
        self.publish_output(*self._misp_events)
        # update a state of the MISP events publishing
        self._state['events_publishing_datetime'] = self._now
        self.save_state(self._state)
        self._schedule(self._prepare_and_schedule_samples_publishing)

    def _do_publish(self):
        """Publish a malware sample through the 'sample' exchange."""
        self.publish_output(*self._output_components, exchange=self.output_queue[1]['exchange'])
        self._output_components = None
        self._state['last_published_samples'].append(int(self._current_sample['id']))
        self.save_state(self._state)
        self._schedule(self._next_download)

    def _prepare_and_schedule_samples_publishing(self):
        """
        Check, whether the 'sample' exchange was declared. Set proper
        flags and attributes.
        """
        sample_exchange = self.output_queue[1]['exchange']
        if sample_exchange in self._declared_output_exchanges:
            # an output queue may be declared here
            try:
                self._samples = deque(self._get_samples_details())
            except NoNewEventsException:
                if self._overdue_samples_to_publish:
                    LOGGER.warning('Datetime of the last publishing of malware samples '
                                   'indicated, that there are overdue samples to publish '
                                   'since the datetime. Although, there are no events and '
                                   'no associated malware samples to download from '
                                   'the saved datetime.')
                else:
                    LOGGER.info('There are no malware samples associated with downloaded events.')
                self._set_samples_state_to_completed()
                self.inner_stop()
            else:
                if self._samples:
                    self._set_attributes_for_samples()
                    self._schedule(self._next_download)
                else:
                    LOGGER.info('No malware samples to publish since: %s',
                                self._state['samples_publishing_datetime'])
                    self._set_samples_state_to_completed()
                    self.inner_stop()
        else:
            LOGGER.error("Exchange '%s' was not declared. Not publishing malware samples.",
                         sample_exchange)
            self.inner_stop()

    # methods determining properties and attributes
    def get_source_channel(self, **kwargs):
        return 'misp'

    def get_output_prop_kwargs(self, *args, **kwargs):
        """
        Method extended in order to include the minimal TLP value
        for an event, inside message's headers, if it was set
        in a config, and malware sample's details, if it is currently
        being published.

        Returns:
            A dict containing message's properties, with minimal
            TLP value or malware sample's additional details.
        """
        properties = super(MispCollector, self).get_output_prop_kwargs(*args, **kwargs)
        min_tlp = self._get_min_tlp()
        if min_tlp:
            properties['headers'].setdefault('meta', dict())[self.min_tlp_key_name] = min_tlp
        if self._publishing_samples:
            properties['headers'].setdefault('meta', dict()).setdefault('misp', dict()).update(
                self._get_sample_headers())
        return properties

    def _get_sample_headers(self):
        """
        Extract the relevant keys from malware sample's details.

        Returns:
            A dict with a relevant data about a sample.
        """
        return {key: self._current_sample[key] for
                key in self.sample_message_headers if key in self._current_sample}

    def _set_attributes_for_samples(self):
        self._publishing_samples = True
        self.type = 'file'

    # downloading methods
    def get_output_data_body(self, source, **processed_data):
        """
        Overridden method fetches MISP events or a malware
        sample's binary data, if the flag is set.
        """
        if not self._publishing_samples:
            return self._get_misp_events(self._state['events_publishing_datetime'])
        sample_id = self._current_sample['id']
        sample_url = urljoin(self._attributes_url, sample_id)
        return self._download_sample(sample_url)

    def _download_sample(self, url):
        """
        Try to download a malware sample from an URL during
        the established timeout.

        Args:
            `url`:
                The URL to the current malware sample.

        Returns:
            A binary data of the sample.

        Raises:
            A `SampleDownloadFailure` if the sample does not exists,
            or it could not be downloaded.
        """
        headers = self._prepare_request_headers()
        timeout = int(self.config['download_timeout'])
        retry_sleep_time = int(self.config['retry_sleep_time'])
        duration = 0
        start_time = datetime.utcnow()
        while duration < timeout:
            response = requests.get(url, headers=headers)
            if response.status_code == 404:
                LOGGER.warning('The URL: %s does not provide a malware sample (status code: 404).',
                               url)
                raise SampleDownloadFailure
            if response.status_code == 200 and response.content:
                break
            LOGGER.info("Failure downloading URL: %s. Status code: %s. Retrying in: %s seconds.",
                        url,
                        response.status_code,
                        retry_sleep_time)
            time.sleep(retry_sleep_time)
            duration = (datetime.utcnow() - start_time).seconds
        else:
            LOGGER.warning("Timeout exceeded, failure downloading URL: %s.", url)
            raise SampleDownloadFailure
        LOGGER.debug('Downloaded a sample from the URL: %s.', url)
        return response.content

    def _get_misp_events(self, initial_datetime):
        """
        Download the events since the established datetime.

        Returns:
            Downloaded events, serialized to a JSON.

        Raises:
            A 'NoNewEventsException' if the source does not provide
            new events.
        """
        initial_timestamp = self._convert_datetime_to_timestamp(initial_datetime)
        data = self.misp.download_last(initial_timestamp).get('response')
        if data:
            self._misp_raw_events = data
            return json.dumps(data)
        raise NoNewEventsException

    # helper methods
    def _get_samples_details(self):
        """
        Get the details of the attributes with a type corresponding
        to the malware samples.

        Args:
            `misp_raw_events` (list):
                A list of the events, before serialization.

        Yields:
            Details of a single malware sample.
        """
        if self._overdue_samples_to_publish:
            self._misp_raw_events = None
            self._get_misp_events(self._state['samples_publishing_datetime'])
            LOGGER.info('Preparing to fetch and publish malware samples, including the overdue '
                        'samples since: %s.', self._state['samples_publishing_datetime'])
        else:
            LOGGER.debug('Preparing to fetch and publish the new malware samples since: %s',
                         self._state['samples_publishing_datetime'])
        raw_events = self._misp_raw_events
        attribute_lists = (x['Event']['Attribute'] for x in raw_events)
        for attr_list in attribute_lists:
            for attr in attr_list:
                if attr['type'] in self._possible_attribute_types and 'id' in attr:
                    if (not self._state['last_published_samples'] or
                            (self._state['last_published_samples'] and
                                int(attr['id']) not in self._state['last_published_samples'])):
                        yield attr

    def get_misp_verifycert(self):
        misp_verifycert = self.config.get('misp_verifycert')
        if not misp_verifycert or misp_verifycert.lower() not in ('false', 'f', 'no', 'n', 'off',
                                                                  '0'):
            return True
        else:
            return False

    def _get_min_tlp(self):
        """
        Get the minimal TLP value for the publishing events
        from a config, if it was set.

        Returns:
            A verified and normalized TLP value.
        """
        min_tlp = self.config.get(self.min_tlp_key_name)
        if min_tlp:
            min_tlp_normalized = min_tlp.lower()
            if min_tlp_normalized in self.allowed_tlp_vals:
                return min_tlp_normalized
            LOGGER.warning("Invalid minimal TLP value: '%s'.", min_tlp)
        return None
Exemplo n.º 7
0
else:
    since = ""

# Misp interface
misp_url, misp_key = conf.getMISPCredentials()
if not misp_url:
    print("MISP credentials not specified")
    sys.exit(1)
try:
    misp = PyMISP(misp_url, misp_key, True, 'json')
except:
    print("Failed to connect to MISP. Wrong URL?")
    sys.exit(1)

# Fetch data
misp_last = misp.download_last(since)

# Check data
if 'message' in misp_last.keys():
    if misp_last['message'] == 'No matches':
        sys.exit(0)
    elif misp_last['message'].startswith('Authentication failed.'):
        print("MISP Authentication failed")
        sys.exit(1)
if not 'response' in misp_last:
    print("Error occured while fetching MISP data")
    sys.exit(1)

bulk = []
for entry in progressbar(misp_last['response']):
    # Get info
Exemplo n.º 8
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pymisp import PyMISP
import json

misp_url = "your_dedimisp_url_here"
misp_key = "your_key_here"

if __name__ == '__main__':
    misp = PyMISP(misp_url, misp_key, True, "json")
    event = misp.download_last('1d')
    print(json.dumps(event))
Exemplo n.º 9
0
        help=
        'The parameter can be either set to "last" or "searchall". If the parameter is not valid, "last" will be the default setting.'
    )
    parser.add_argument(
        "-a",
        "--argument",
        required=True,
        help=
        'if function is "last", time can be defined in days, hours, minutes (for example 5d or 12h or 30m). Otherwise, this argument is the string to search'
    )

    args = parser.parse_args()

    misp = PyMISP(misp_url, misp_key, misp_verifycert, 'json')

    if args.function == "searchall":
        result = misp.search_all(args.argument)
    else:
        result = misp.download_last(args.argument)

    if 'response' in result:
        events = tools.eventsListBuildFromArray(result)
        attributes = tools.attributesListBuild(events)
        temp = tools.getNbAttributePerEventCategoryType(attributes)
        temp = temp.groupby(level=['category', 'type']).sum()
        pygal_tools.createTreemap(temp, 'Attributes Distribution',
                                  'attribute_treemap.svg',
                                  'attribute_table.html')
    else:
        print('There is no event answering the research criteria')
Exemplo n.º 10
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pymisp import PyMISP
from keys import misp_url, misp_key, misp_verifycert
import argparse
import tools


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Take a sample of events (based on last.py of searchall.py) and create a treemap epresenting the distribution of attributes in this sample.')
    parser.add_argument("-f", "--function", required=True, help='The parameter can be either set to "last" or "searchall". If the parameter is not valid, "last" will be the default setting.')
    parser.add_argument("-a", "--argument", required=True, help='if function is "last", time can be defined in days, hours, minutes (for example 5d or 12h or 30m). Otherwise, this argument is the string to search')

    args = parser.parse_args()

    misp = PyMISP(misp_url, misp_key, misp_verifycert, 'json')

    if args.function == "searchall":
        result = misp.search_all(args.argument)
    else:
        result = misp.download_last(args.argument)

    events = tools.eventsListBuildFromArray(result)
    attributes = tools.attributesListBuild(events)
    temp = tools.getNbAttributePerEventCategoryType(attributes)
    temp = temp.groupby(level=['category', 'type']).sum()
    tools.createTreemap(temp, 'Attributes Distribution', 'attribute_treemap.svg', 'attribute_table.html')
Exemplo n.º 11
0
    elif args.period == "m":
        if args.accuracy == "d":
            split = 28
            size = 1
        else:
            split = 4
            size = 7
        last = '28d'
        title = 'Tags repartition over the last 28 days'
    else:
        split = 7
        size = 1
        last = '7d'
        title = 'Tags repartition over the last 7 days'

    result = misp.download_last(last)
    events = tools.eventsListBuildFromArray(result)
    result = []
    dates = []
    enddate = tools.getToday()
    colourDict = {}
    faketag = False

    for i in range(split):
        begindate = tools.getNDaysBefore(enddate, size)
        dates.append(str(enddate.date()))
        eventstemp = tools.selectInRange(events, begin=begindate, end=enddate)
        if eventstemp is not None:
            tags = tools.tagsListBuild(eventstemp)
            if tags is not None:
                tools.createDictTagsColour(colourDict, tags)
Exemplo n.º 12
0
    since = "%sm"%math.ceil(delta.total_seconds()/60)
else: since=""

# Misp interface
misp_url, misp_key = conf.getMISPCredentials()
if not misp_url:
    print("MISP credentials not specified")
    sys.exit(1)
try:
    misp = PyMISP(misp_url, misp_key, True, 'json')
except:
    print("Failed to connect to MISP. Wrong URL?")
    sys.exit(1)

# Fetch data
misp_last = misp.download_last(since)

# Check data
if 'message' in misp_last.keys():
    if misp_last['message'] == 'No matches':
        sys.exit(0)
    elif misp_last['message'].startswith('Authentication failed.'):
        print("MISP Authentication failed")
        sys.exit(1)
if not 'response' in misp_last:
    print("Error occured while fetching MISP data")
    sys.exit(1)

bulk =[]
for entry in progressbar(misp_last['response']):
    # Get info