Example #1
0
def export_to_misp(user_details, report,indicators):
    misp_url = user_details.get('misp_url')
    misp_key = user_details.get('misp_api_key')
    misp_verifycert = True
    misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)

    event = MISPEvent()
    event.info = report.title
    event = misp.add_event(event, pythonify=True)
    print(event)
    created = json.loads(event.to_json())
    event_id = created.get('id')
    report_id = report.id
    
    for indicator in indicators:
        indicator_value = indicator[1]
        if indicator[2] == 'IP':
            indicator_type = "ip-dst"
        elif indicator[2] == 'Domain':
            indicator_type = 'domain'
        elif indicator[2] == 'Email':
            indicator_type = 'email-src'
        elif indicator[2] == 'CVE':
            indicator_value = indicator[1].replace('_', '-')
            indicator_type = 'vulnerability'
        elif indicator[2] == 'MD5 Hash':
            indicator_type = 'md5'
        elif indicator[2] == 'SHA256 Hash':
            indicator_type = 'sha256'
        elif indicator[2] == 'URL':
            indicator_type = 'url'
        try:
            misp.add_attribute(event_id,{'type':indicator_type,'value':indicator_value},pythonify=True)
        except:
            pass
Example #2
0
class Mail2MISP():
    def __init__(self,
                 misp_url,
                 misp_key,
                 verifycert,
                 config,
                 offline=False,
                 urlsonly=False):
        self.offline = offline
        if not self.offline:
            self.misp = ExpandedPyMISP(misp_url,
                                       misp_key,
                                       verifycert,
                                       debug=config.debug)
        self.config = config
        self.urlsonly = urlsonly
        if not hasattr(self.config, 'enable_dns'):
            setattr(self.config, 'enable_dns', True)
        if self.urlsonly is False:
            setattr(self.config, 'enable_dns', False)
        self.debug = self.config.debug
        self.config_from_email_body = {}
        # Init Faup
        self.f = Faup()
        self.sightings_to_add = []

    def load_email(self, pseudofile):
        self.pseudofile = pseudofile
        self.original_mail = message_from_bytes(self.pseudofile.getvalue(),
                                                policy=policy.default)
        self.subject = self.original_mail.get('Subject')
        try:
            self.sender = self.original_mail.get('From')
        except:
            self.sender = "<unknown sender>"

        # Remove words from subject
        for removeword in self.config.removelist:
            self.subject = re.sub(removeword, "", self.subject).strip()

        # Initialize the MISP event
        self.misp_event = MISPEvent()
        self.misp_event.info = f'{self.config.email_subject_prefix} - {self.subject}'
        self.misp_event.distribution = self.config.default_distribution
        self.misp_event.threat_level_id = self.config.default_threat_level
        self.misp_event.analysis = self.config.default_analysis

    def sighting(self, value, source):
        if self.offline:
            raise Exception('The script is running in offline mode, ')
        '''Add a sighting'''
        s = MISPSighting()
        s.from_dict(value=value, source=source)
        self.misp.add_sighting(s)

    def _find_inline_forward(self):
        '''Does the body contains a forwarded email?'''
        for identifier in self.config.forward_identifiers:
            if identifier in self.clean_email_body:
                self.clean_email_body, fw_email = self.clean_email_body.split(
                    identifier)
                return self.forwarded_email(
                    pseudofile=BytesIO(fw_email.encode()))

    def _find_attached_forward(self):
        forwarded_emails = []
        for attachment in self.original_mail.iter_attachments():
            attachment_content = attachment.get_content()
            # Search for email forwarded as attachment
            # I could have more than one, attaching everything.
            if isinstance(attachment_content, message.EmailMessage):
                forwarded_emails.append(
                    self.forwarded_email(
                        pseudofile=BytesIO(attachment_content.as_bytes())))
            else:
                if isinstance(attachment_content, str):
                    attachment_content = attachment_content.encode()
                filename = attachment.get_filename()
                if not filename:
                    filename = 'missing_filename'
                if self.config_from_email_body.get(
                        'attachment'
                ) == self.config.m2m_benign_attachment_keyword:
                    # Attach sane file
                    self.misp_event.add_attribute(
                        'attachment',
                        value=filename,
                        data=BytesIO(attachment_content))
                else:
                    f_object, main_object, sections = make_binary_objects(
                        pseudofile=BytesIO(attachment_content),
                        filename=filename,
                        standalone=False)
                    self.misp_event.add_object(f_object)
                    if main_object:
                        self.misp_event.add_object(main_object)
                        [
                            self.misp_event.add_object(section)
                            for section in sections
                        ]
        return forwarded_emails

    def email_from_spamtrap(self):
        '''The email comes from a spamtrap and should be attached as-is.'''
        raw_body = self.original_mail.get_body(preferencelist=('html',
                                                               'plain'))
        if raw_body:
            self.clean_email_body = html.unescape(
                raw_body.get_payload(decode=True).decode(
                    'utf8', 'surrogateescape'))
        else:
            self.clean_email_body = ''
        return self.forwarded_email(self.pseudofile)

    def forwarded_email(self, pseudofile: BytesIO):
        '''Extracts all possible indicators out of an email and create a MISP event out of it.
        * Gets all relevant Headers
        * Attach the body
        * Create MISP file objects (uses lief if possible)
        * Set all references
        '''
        email_object = EMailObject(pseudofile=pseudofile,
                                   attach_original_mail=True,
                                   standalone=False)
        if email_object.attachments:
            # Create file objects for the attachments
            for attachment_name, attachment in email_object.attachments:
                if not attachment_name:
                    attachment_name = 'NameMissing.txt'
                if self.config_from_email_body.get(
                        'attachment'
                ) == self.config.m2m_benign_attachment_keyword:
                    a = self.misp_event.add_attribute('attachment',
                                                      value=attachment_name,
                                                      data=attachment)
                    email_object.add_reference(a.uuid, 'related-to',
                                               'Email attachment')
                else:
                    f_object, main_object, sections = make_binary_objects(
                        pseudofile=attachment,
                        filename=attachment_name,
                        standalone=False)
                    if self.config.vt_key:
                        try:
                            vt_object = VTReportObject(
                                self.config.vt_key,
                                f_object.get_attributes_by_relation(
                                    'sha256')[0].value,
                                standalone=False)
                            self.misp_event.add_object(vt_object)
                            f_object.add_reference(vt_object.uuid,
                                                   'analysed-with')
                        except InvalidMISPObject as e:
                            print(e)
                            pass
                    self.misp_event.add_object(f_object)
                    if main_object:
                        self.misp_event.add_object(main_object)
                        for section in sections:
                            self.misp_event.add_object(section)
                    email_object.add_reference(f_object.uuid, 'related-to',
                                               'Email attachment')
        self.process_body_iocs(email_object)
        if self.config.spamtrap or self.config.attach_original_mail or self.config_from_email_body.get(
                'attach_original_mail'):
            self.misp_event.add_object(email_object)
        return email_object

    def process_email_body(self):
        mail_as_bytes = self.original_mail.get_body(
            preferencelist=('html', 'plain')).get_payload(decode=True)
        if mail_as_bytes:
            self.clean_email_body = html.unescape(
                mail_as_bytes.decode('utf8', 'surrogateescape'))
            # Check if there are config lines in the body & convert them to a python dictionary:
            #   <config.body_config_prefix>:<key>:<value> => {<key>: <value>}
            self.config_from_email_body = {
                k.strip(): v.strip()
                for k, v in re.findall(
                    f'{self.config.body_config_prefix}:(.*):(.*)',
                    self.clean_email_body)
            }
            if self.config_from_email_body:
                # ... remove the config lines from the body
                self.clean_email_body = re.sub(
                    rf'^{self.config.body_config_prefix}.*\n?',
                    '',
                    html.unescape(
                        self.original_mail.get_body(
                            preferencelist=('html', 'plain')).get_payload(
                                decode=True).decode('utf8',
                                                    'surrogateescape')),
                    flags=re.MULTILINE)
            # Check if autopublish key is present and valid
            if self.config_from_email_body.get(
                    'm2mkey') == self.config.m2m_key:
                if self.config_from_email_body.get('distribution') is not None:
                    self.misp_event.distribution = self.config_from_email_body.get(
                        'distribution')
                if self.config_from_email_body.get('threat_level') is not None:
                    self.misp_event.threat_level_id = self.config_from_email_body.get(
                        'threat_level')
                if self.config_from_email_body.get('analysis') is not None:
                    self.misp_event.analysis = self.config_from_email_body.get(
                        'analysis')
                if self.config_from_email_body.get('publish'):
                    self.misp_event.publish()

            self._find_inline_forward()
        else:
            self.clean_email_body = ''
        self._find_attached_forward()

    def process_body_iocs(self, email_object=None):
        if email_object:
            body = html.unescape(
                email_object.email.get_body(
                    preferencelist=('html',
                                    'plain')).get_payload(decode=True).decode(
                                        'utf8', 'surrogateescape'))
        else:
            body = self.clean_email_body

        # Cleanup body content
        # Depending on the source of the mail, there is some cleanup to do. Ignore lines in body of message
        for ignoreline in self.config.ignorelist:
            body = re.sub(rf'^{ignoreline}.*\n?', '', body, flags=re.MULTILINE)

        # Remove everything after the stopword from the body
        body = body.split(self.config.stopword, 1)[0]

        # Add tags to the event if keywords are found in the mail
        for tag in self.config.tlptags:
            for alternativetag in self.config.tlptags[tag]:
                if alternativetag in body.lower():
                    self.misp_event.add_tag(tag)

        # Prepare extraction of IOCs
        # Refang email data
        body = refang(body)

        # Extract and add hashes
        contains_hash = False
        for h in set(re.findall(hashmarker.MD5_REGEX, body)):
            contains_hash = True
            attribute = self.misp_event.add_attribute(
                'md5', h, enforceWarninglist=self.config.enforcewarninglist)
            if email_object:
                email_object.add_reference(attribute.uuid, 'contains')
            if self.config.sighting:
                self.sightings_to_add.append((h, self.config.sighting_source))
        for h in set(re.findall(hashmarker.SHA1_REGEX, body)):
            contains_hash = True
            attribute = self.misp_event.add_attribute(
                'sha1', h, enforceWarninglist=self.config.enforcewarninglist)
            if email_object:
                email_object.add_reference(attribute.uuid, 'contains')
            if self.config.sighting:
                self.sightings_to_add.append((h, self.config.sighting_source))
        for h in set(re.findall(hashmarker.SHA256_REGEX, body)):
            contains_hash = True
            attribute = self.misp_event.add_attribute(
                'sha256', h, enforceWarninglist=self.config.enforcewarninglist)
            if email_object:
                email_object.add_reference(attribute.uuid, 'contains')
            if self.config.sighting:
                self.sightings_to_add.append((h, self.config.sighting_source))

        if contains_hash:
            [
                self.misp_event.add_tag(tag)
                for tag in self.config.hash_only_tags
            ]

        # # Extract network IOCs
        urllist = []
        urllist += re.findall(urlmarker.WEB_URL_REGEX, body)
        urllist += re.findall(urlmarker.IP_REGEX, body)
        if self.debug:
            syslog.syslog(str(urllist))

        hostname_processed = []

        # Add IOCs and expanded information to MISP
        for entry in set(urllist):
            ids_flag = True
            self.f.decode(entry)

            domainname = self.f.get_domain()
            if domainname in self.config.excludelist:
                # Ignore the entry
                continue

            hostname = self.f.get_host()

            scheme = self.f.get_scheme()
            if scheme:
                scheme = scheme

            resource_path = self.f.get_resource_path()
            if resource_path:
                resource_path = resource_path

            if self.debug:
                syslog.syslog(domainname)

            if domainname in self.config.internallist and self.urlsonly is False:  # Add link to internal reference unless in urlsonly mode
                attribute = self.misp_event.add_attribute(
                    'link',
                    entry,
                    category='Internal reference',
                    to_ids=False,
                    enforceWarninglist=False)
                if email_object:
                    email_object.add_reference(attribute.uuid, 'contains')
            elif domainname in self.config.externallist or self.urlsonly is False:  # External analysis
                attribute = self.misp_event.add_attribute(
                    'link',
                    entry,
                    category='External analysis',
                    to_ids=False,
                    enforceWarninglist=False)
                if email_object:
                    email_object.add_reference(attribute.uuid, 'contains')
            elif domainname in self.config.externallist or self.urlsonly:  # External analysis
                if self.urlsonly:
                    comment = self.subject + " (from: " + self.sender + ")"
                else:
                    comment = ""
                attribute = self.misp.add_attribute(
                    self.urlsonly, {
                        "type": 'link',
                        "value": entry,
                        "category": 'External analysis',
                        "to_ids": False,
                        "comment": comment
                    })
                for tag in self.config.tlptags:
                    for alternativetag in self.config.tlptags[tag]:
                        if alternativetag in self.subject.lower():
                            self.misp.tag(attribute["uuid"], tag)
                            new_subject = comment.replace(alternativetag, '')
                            self.misp.change_comment(attribute["uuid"],
                                                     new_subject)

            else:  # The URL is probably an indicator.
                comment = ""
                if (domainname in self.config.noidsflaglist) or (
                        hostname in self.config.noidsflaglist):
                    ids_flag = False
                    comment = "Known host (mostly for connectivity test or IP lookup)"
                if self.debug:
                    syslog.syslog(str(entry))

                if scheme:
                    if is_ip(hostname):
                        attribute = self.misp_event.add_attribute(
                            'url',
                            entry,
                            to_ids=False,
                            enforceWarninglist=self.config.enforcewarninglist)
                        if email_object:
                            email_object.add_reference(attribute.uuid,
                                                       'contains')
                    else:
                        if resource_path:  # URL has path, ignore warning list
                            attribute = self.misp_event.add_attribute(
                                'url',
                                entry,
                                to_ids=ids_flag,
                                enforceWarninglist=False,
                                comment=comment)
                            if email_object:
                                email_object.add_reference(
                                    attribute.uuid, 'contains')
                        else:  # URL has no path
                            attribute = self.misp_event.add_attribute(
                                'url',
                                entry,
                                to_ids=ids_flag,
                                enforceWarninglist=self.config.
                                enforcewarninglist,
                                comment=comment)
                            if email_object:
                                email_object.add_reference(
                                    attribute.uuid, 'contains')
                    if self.config.sighting:
                        self.sightings_to_add.append(
                            (entry, self.config.sighting_source))

                if hostname in hostname_processed:
                    # Hostname already processed.
                    continue

                hostname_processed.append(hostname)
                if self.config.sighting:
                    self.sightings_to_add.append(
                        (hostname, self.config.sighting_source))

                if self.debug:
                    syslog.syslog(hostname)

                comment = ''
                port = self.f.get_port()
                if port:
                    port = port
                    comment = f'on port: {port}'

                if is_ip(hostname):
                    attribute = self.misp_event.add_attribute(
                        'ip-dst',
                        hostname,
                        to_ids=ids_flag,
                        enforceWarninglist=self.config.enforcewarninglist,
                        comment=comment)
                    if email_object:
                        email_object.add_reference(attribute.uuid, 'contains')
                else:
                    related_ips = []
                    if HAS_DNS and self.config.enable_dns:
                        try:
                            syslog.syslog(hostname)
                            for rdata in dns.resolver.query(hostname, 'A'):
                                if self.debug:
                                    syslog.syslog(str(rdata))
                                related_ips.append(rdata.to_text())
                        except Exception as e:
                            if self.debug:
                                syslog.syslog(str(e))

                    if related_ips:
                        hip = MISPObject(name='ip-port')
                        hip.add_attribute(
                            'hostname',
                            value=hostname,
                            to_ids=ids_flag,
                            enforceWarninglist=self.config.enforcewarninglist,
                            comment=comment)
                        for ip in set(related_ips):
                            hip.add_attribute('ip',
                                              type='ip-dst',
                                              value=ip,
                                              to_ids=False,
                                              enforceWarninglist=self.config.
                                              enforcewarninglist)
                        self.misp_event.add_object(hip)
                        if email_object:
                            email_object.add_reference(hip.uuid, 'contains')
                    else:
                        if self.urlsonly is False:
                            attribute = self.misp_event.add_attribute(
                                'hostname',
                                value=hostname,
                                to_ids=ids_flag,
                                enforceWarninglist=self.config.
                                enforcewarninglist,
                                comment=comment)
                        if email_object:
                            email_object.add_reference(attribute.uuid,
                                                       'contains')

    def add_event(self):
        '''Add event on the remote MISP instance.'''

        # Add additional tags depending on others
        tags = []
        for tag in [t.name for t in self.misp_event.tags]:
            if self.config.dependingtags.get(tag):
                tags += self.config.dependingtags.get(tag)

        # Add additional tags according to configuration
        for malware in self.config.malwaretags:
            if malware.lower() in self.subject.lower():
                tags += self.config.malwaretags.get(malware)
        if tags:
            [self.misp_event.add_tag(tag) for tag in tags]

        has_tlp_tag = False
        for tag in [t.name for t in self.misp_event.tags]:
            if tag.lower().startswith('tlp'):
                has_tlp_tag = True
        if not has_tlp_tag:
            self.misp_event.add_tag(self.config.tlptag_default)

        if self.offline:
            return self.misp_event.to_json()
        event = self.misp.add_event(self.misp_event, pythonify=True)
        if self.config.sighting:
            for value, source in self.sightings_to_add:
                self.sighting(value, source)
        return event
Example #3
0
class EDRMISP():
    def __init__(self):
        self.misp = ExpandedPyMISP(misp_url, misp_key, misp_verify)
        self.tags = self.misp.tags()
        self.attributes = []
        self.found = False

        if args.region == 'EU':
            self.edr = 'https://api.soc.eu-central-1.mcafee.com'
        elif args.region == 'US':
            self.edr = 'https://api.soc.mcafee.com'
        elif args.region == 'SY':
            self.edr = 'https://soc.ap-southeast-2.mcafee.com'

        self.verify = True
        self.session = requests.Session()

        user = args.user
        pw = args.password
        self.creds = (user, pw)

    def edr_auth(self):
        r = self.session.get(self.edr + '/identity/v1/login', auth=self.creds)
        res = r.json()

        if r.status_code == 200:
            token = res['AuthorizationToken']
            self.headers = {'Authorization': 'Bearer {}'.format(token)}
            print('AUTHENTICATION: Successfully authenticated.')
        else:
            print('ERROR: Something went wrong during the authentication')
            sys.exit()

    def edr_search(self, hash):
        payload = {
            "projections": [{
                "name": "HostInfo",
                "outputs": ["hostname", "ip_address"]
            }, {
                "name": "Files",
                "outputs": ["name", "md5", "status", "full_name"]
            }],
            "condition": {
                "or": [{
                    "and": [{
                        "name": "Files",
                        "output": "md5",
                        "op": "EQUALS",
                        "value": str(hash)
                    }]
                }]
            }
        }

        res = self.session.post(self.edr + '/active-response/api/v1/searches',
                                headers=self.headers,
                                json=payload)
        if res.status_code == 200:
            queryId = res.json()['id']
            print('SEARCH: MVISION EDR search got started successfully')
        else:
            print('ERROR: Could not find the query ID.')
            sys.exit()

        return queryId

    def edr_status(self, queryId):
        status = False
        res = self.session.get(
            self.edr +
            '/active-response/api/v1/searches/{}/status'.format(str(queryId)),
            headers=self.headers)
        if res.status_code == 200:
            if res.json()['status'] == 'FINISHED':
                status = True
            else:
                print('STATUS: Search still in process. Status: {}'.format(
                    res.json()['status']))
        return status

    def edr_result(self, queryId, eventid, attr_id, attr_uuid):
        hostnames = []
        res = self.session.get(
            self.edr +
            '/active-response/api/v1/searches/{}/results'.format(str(queryId)),
            headers=self.headers)
        if res.status_code == 200:
            if res.json()['items'] != []:
                total = res.json()['totalItems']
                print('SUCCESS: Found {0} Host(s) with this hash.'.format(
                    str(total)))

                for item in res.json()['items']:
                    hostname = item['output']['HostInfo|hostname']
                    ip = item['output']['HostInfo|ip_address']
                    status = item['output']['Files|status']
                    full_name = item['output']['Files|full_name']
                    md5 = item['output']['Files|md5']
                    finding = 'Hostname: {0} | IP: {1} | Status: {2} | Location: {3} | MD5: {4}'\
                        .format(hostname, ip, status, full_name, md5)
                    hostnames.append(hostname)

                    self.found = True
                    self.add_sighting(attr_id, hostname)
                    self.add_attribute(eventid, finding)

                self.update_attribute(attr_id, hostnames, attr_uuid)
            else:
                print('SUCCESS: No System found containing files with hash.')
        else:
            print('ERROR: Something went wrong to retrieve the results.')
            sys.exit()

    def edr_run_search(self, eventid, hash, attr_id, attr_uuid):
        self.edr_auth()
        queryid = self.edr_search(hash)
        while self.edr_status(queryid) is False:
            time.sleep(10)
        self.edr_result(queryid, eventid, attr_id, attr_uuid)

    def add_attribute(self, eventid, finding):
        attr = {"value": finding, "type": "target-machine"}
        self.misp.add_attribute(eventid, attr)

    def update_attribute(self, attr_id, comment, attr_uuid):
        data = {"comment": str(comment)}
        self.misp.update_attribute(data, attr_id)
        self.misp.tag(attr_uuid, misp_ntag)

    def add_sighting(self, attr_id, hostname):
        sight = {
            "values": "MVISION EDR",
            "id": attr_id,
            "source": "Target: {0}".format(hostname)
        }
        self.misp.add_sighting(sight)

    def main(self):
        try:
            events = self.misp.search(tags=misp_tag)
            if events:
                for event in events:
                    eventid = str(event['Event']['id'])
                    for attributes in event['Event']['Attribute']:
                        if attributes['type'] == 'md5':
                            print(
                                'STATUS: Found MD5 {0} in Event {1}. Trying to lookup Endpoint with MVISION EDR.'
                                .format(str(attributes['value']), eventid))

                            self.edr_run_search(eventid, attributes['value'],
                                                attributes['id'],
                                                attributes['uuid'])

                    for objects in event['Event']['Object']:
                        for attributes in objects['Attribute']:
                            if attributes['type'] == 'md5':
                                print(
                                    'STATUS: Found MD5 {0} in Event {1}. Trying to lookup Endpoint with MVISION EDR.'
                                    .format(str(attributes['value']), eventid))
                                self.edr_run_search(eventid,
                                                    attributes['value'],
                                                    attributes['id'],
                                                    attributes['uuid'])

                    self.misp.untag(event['Event']['uuid'], misp_tag)

                    if self.found is True:
                        self.misp.tag(event['Event']['uuid'], misp_ntag)

        except Exception as error:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            print(
                'ERROR: Error in {location}.{funct_name}() - line {line_no} : {error}'
                .format(location=__name__,
                        funct_name=sys._getframe().f_code.co_name,
                        line_no=exc_tb.tb_lineno,
                        error=str(error)))
Example #4
0
	def print_match(self, fpath, page, name, match, flag, sheet=''):
		#Read misp API key, address and cert value from misp_keys.ini
		config = ConfigParser()
		config.read(os.path.join(iocp.get_basedir(), 'data/misp_keys.ini'))

		misp = ExpandedPyMISP(config.get('misp', 'misp_url'), config.get('misp', 'misp_key'), False)
		data = {
			'path' : fpath,
			'file' : os.path.basename(fpath),
			'page' : page,
			'type' : name,
			'match': match
		}

		data_type = data['type']
		data_match = data['match']
		event_id = g_misp_event


		if data_type == 'URL':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'url','value': data_match})

		elif data_type == 'IP':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'ip-src','value': data_match})

		elif data_type == 'Email':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'email-src','value': data_match})

		elif data_type == 'MD5':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'md5','value': data_match})

		elif data_type == 'SHA1':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'sha1','value': data_match})

		elif data_type == 'SHA256':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'sha256','value': data_match})

		elif data_type == 'CVE':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'vulnerability','value': data_match})

		elif data_type == 'Registry':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'regkey','value': data_match})

		elif data_type == 'Filename':
			print("Importing to MISP ioc %s" %(data_match))
			misp.add_attribute(event_id,{'type': 'filename','value': data_match})

		else:
			print("Data type: %s not supported by the script" %(data_type))
Example #5
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pymisp import ExpandedPyMISP
from keys import misp_url, misp_key, misp_verifycert
import argparse

# For python2 & 3 compat, a bit dirty, but it seems to be the least bad one
try:
    input = raw_input
except NameError:
    pass


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Add an attribute to an event')
    parser.add_argument("-e", "--event", help="The id, uuid or json of the event to update.")
    parser.add_argument("-t", "--type", help="The type of the added attribute")
    parser.add_argument("-v", "--value", help="The value of the attribute")
    args = parser.parse_args()

    misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)

    event = misp.add_attribute(args.event, {'type': args.type, 'value': args.value}, pythonify=True)
    print(event)
Example #6
0
class EDRMISP():

    def __init__(self):
        self.config = DxlClientConfig.create_dxl_config_from_file(dxl_config)
        self.misp = ExpandedPyMISP(misp_url, misp_key, misp_verify)
        self.tags = self.misp.tags()
        self.attributes = []
        self.found = False

    def add_attribute(self, eventid, finding):
        attr = {
            "value": finding,
            "type": "target-machine"
        }
        self.misp.add_attribute(eventid, attr)

    def update_attribute(self, attr_id, comment, attr_uuid):
        data = {
            "comment": str(comment)
        }
        self.misp.update_attribute(data, attr_id)
        self.misp.tag(attr_uuid, misp_ntag)

    def add_sighting(self, attr_id, hostname):
        sight = {
            "values": "MVISION EDR",
            "id": attr_id,
            "source": "Target: {0}".format(hostname)
        }
        self.misp.add_sighting(sight)

    def edr_search(self, eventid, hash, attr_id, attr_uuid):
        hostnames = []

        with DxlClient(self.config) as client:
            client.connect()
            marclient = MarClient(client)

            results_context = \
                marclient.search(
                    projections=[{
                        "name": "HostInfo",
                        "outputs": ["hostname", "ip_address"]
                    }, {
                        "name": "Files",
                        "outputs": ["name", "md5", "status", "full_name"]
                    }],
                    conditions={
                        "or": [{
                            "and": [{
                                "name": "Files",
                                "output": "md5",
                                "op": "EQUALS",
                                "value": hash
                            }]
                        }]
                    }
                )

            if results_context.has_results:
                results = results_context.get_results()
                total = results['totalItems']
                print('SUCCESS: Found {0} Host(s) with hash {1}.'.format(str(total), hash))

                for item in results['items']:
                    hostname = item['output']['HostInfo|hostname']
                    ip = item['output']['HostInfo|ip_address']
                    status = item['output']['Files|status']
                    full_name = item['output']['Files|full_name']
                    md5 = item['output']['Files|md5']
                    finding = 'Hostname: {0} | IP: {1} | Status: {2} | Location: {3} | MD5: {4}'\
                        .format(hostname, ip, status, full_name, md5)
                    hostnames.append(hostname)

                    self.found = True
                    self.add_sighting(attr_id, hostname)
                    self.add_attribute(eventid, finding)

                self.update_attribute(attr_id, hostnames, attr_uuid)

            else:
                print('SUCCESS: No System found containing files with hash {0}'.format(hash))

    def main(self):
        try:
            events = self.misp.search(tags=misp_tag)
            if events:
                for event in events:
                    eventid = str(event['Event']['id'])
                    for attributes in event['Event']['Attribute']:
                        if attributes['type'] == 'md5':
                            print('STATUS: Found MD5 {0} in Event {1}. Trying to lookup Endpoint with MVISION EDR.'
                                  .format(str(attributes['value']), eventid))
                            self.edr_search(eventid, attributes['value'], attributes['id'], attributes['uuid'])

                    for objects in event['Event']['Object']:
                        for attributes in objects['Attribute']:
                            if attributes['type'] == 'md5':
                                print('STATUS: Found MD5 {0} in Event {1}. Trying to lookup Endpoint with MVISION EDR.'
                                      .format(str(attributes['value']), eventid))
                                self.edr_search(eventid, attributes['value'], attributes['id'], attributes['uuid'])

                    self.misp.untag(event['Event']['uuid'], misp_tag)

                    if self.found is True:
                        self.misp.tag(event['Event']['uuid'], misp_ntag)

        except Exception as error:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            print('ERROR: Error in {location}.{funct_name}() - line {line_no} : {error}'
                  .format(location=__name__, funct_name=sys._getframe().f_code.co_name, line_no=exc_tb.tb_lineno,
                          error=str(error)))
Example #7
0
                misp_tag = []
                if 'Tag' in attribute:
                    for tag in attribute.get('Tag'):
                        misp_tag.append(tag.get('name'))

                mispattribute = MISPAttribute()
                mispattribute.from_dict(
                    **{
                        'value': attribute.get("value"),
                        'category': attribute.get("category"),
                        'type': attribute.get("type"),
                        'to_ids': attribute.get("to_ids"),
                        'comment': attribute.get("comment"),
                        'Tag': misp_tag
                    })
                res = api.add_attribute(event, mispattribute)
                time.sleep(insert_sleep)
                count_attributes = count_attributes + 1

        if 'Object' in data.get("response")[0].get("Event"):
            objects = data.get("response")[0].get("Event").get("Object")
            for obj in objects:
                misp_object = MISPObject(obj.get('name'))
                if 'Attribute' in obj:
                    for attribute in obj.get('Attribute'):
                        misp_object.add_attribute(
                            attribute.get('object_relation'),
                            type=attribute.get('type'),
                            category=attribute.get('category'),
                            value=attribute.get('value'),
                            to_ids=attribute.get('to_ids'),
Example #8
0
    if args.is_malware:
        arg_type = 'malware-sample'
    else:
        arg_type = 'attachment'

    # Create attributes
    attributes = []
    for f in files:
        a = MISPAttribute()
        a.type = arg_type
        a.value = f.name
        a.data = f
        a.comment = args.comment
        a.distribution = args.distrib
        if args.expand and arg_type == 'malware-sample':
            a.expand = 'binary'
        attributes.append(a)

    if args.event:
        for a in attributes:
            misp.add_attribute(args.event, a)
    else:
        m = MISPEvent()
        m.info = args.info
        m.distribution = args.distrib
        m.attributes = attributes
        if args.expand and arg_type == 'malware-sample':
            m.run_expansions()
        misp.add_event(m)