def main(args): # for i in dir(stix2): # print(i) # sys.exit(0) pathname = os.path.dirname(sys.argv[0]) if len(sys.argv) > 3: namespace[0] = sys.argv[3] if len(sys.argv) > 4: namespace[1] = sys.argv[4].replace(" ", "_") namespace[1] = re.sub('[\W]+', '', namespace[1]) misp = pymisp.MISPEvent(None, False) misp.load_file(os.path.join(pathname, args[1])) SDOs = [] object_refs = [] external_refs = [] identity = setIdentity(misp, SDOs) attributes = readAttributes(misp, identity, object_refs, external_refs) buildRelationships(attributes, object_refs) report = eventReport(misp, identity, object_refs, external_refs) SDOs.append(report) for attribute in attributes: SDOs.append(attribute) stix_package = generateEventPackage(misp, SDOs) saveFile(args, pathname, stix_package) print(1)
def main(args): pathname = os.path.dirname(sys.argv[0]) if len(sys.argv) > 3: namespace[0] = sys.argv[3] if len(sys.argv) > 4: namespace[1] = sys.argv[4].replace(" ", "_") namespace[1] = re.sub('[\W]+', '', namespace[1]) misp = pymisp.MISPEvent(None, False) misp.load_file(os.path.join(pathname, args[1])) SDOs = [] object_refs = [] external_refs = [] identity = setIdentity(misp) SDOs.append(identity) attributes = readAttributes(misp, identity, object_refs, external_refs) buildRelationships(attributes, object_refs) report = eventReport(misp, identity, object_refs, external_refs) SDOs.append(report) for attribute in attributes: SDOs.append(attribute) stix_package = generateEventPackage(misp, SDOs) saveFile(args, pathname, stix_package) print(1) descFilename = os.path.join(pymisp.__path__[0], 'data/describeTypes.json') descFile = open(descFilename, 'r') types = json.loads(descFile.read()) print(types)
def feyemisp(self, alert, desc="FireEye alert", domain=None, url=None): if not self.misp or (not domain and not url): return ev = pymisp.MISPEvent() desc = unprintable(desc).strip() event_template = '{"orgc_id": "1", "info": "' + desc + \ '", "event_creator_email": "*****@*****.**", "locked": false, "Object": [], "Tag": [{"name": "FireEye"}, {"name": "EmailScanner"}], "Galaxy": [], "published": false, "distribution": "1", "proposal_email_lock": false, "threat_level_id": "2", "RelatedEvent": []}' att = [] if domain: att.append({ "category": "Network activity", "to_ids": True, "type": "domain", "value": domain, "comment": desc }) if url: att.append({ "category": "Network activity", "to_ids": True, "type": "url", "value": url, "comment": desc }) event_json = json.loads(event_template) event_json["Attribute"] = att ev.from_json(json.dumps(event_json)) self.misp.add_event(ev)
def __init__(self, args): self.misp_event = pymisp.MISPEvent() self.args = args if len(args) > 3: namespace[0] = args[3] if len(args) > 4: ns = args[4].replace(" ", "_") namespace[1] = re.sub('[\W]+', '', ns) if not namespace[0]: namespace[0] = 'https://www.misp-project.org' try: idgen.set_id_namespace({namespace[0]: namespace[1]}) except ValueError: try: idgen.set_id_namespace(Namespace(namespace[0], namespace[1])) except TypeError: idgen.set_id_namespace(Namespace(namespace[0], namespace[1], "MISP")) self.namespace_prefix = idgen.get_id_namespace_alias() self.simple_type_to_method = {"port": self.generate_port_observable, "domain|ip": self.generate_domain_ip_observable} self.simple_type_to_method.update(dict.fromkeys(hash_type_attributes["single"] + hash_type_attributes["composite"] + ["filename"] + ["attachment"], self.resolve_file_observable)) self.simple_type_to_method.update(dict.fromkeys(["ip-src", "ip-dst", "ip-src|port", "ip-dst|port"], self.generate_ip_observable)) self.simple_type_to_method.update(dict.fromkeys(["regkey", "regkey|value"], self.generate_regkey_observable)) self.simple_type_to_method.update(dict.fromkeys(["hostname", "domain", "url", "AS", "mutex", "named pipe", "link"], self.generate_simple_observable)) self.simple_type_to_method.update(dict.fromkeys(["email-src", "email-dst", "email-subject"], self.resolve_email_observable)) self.simple_type_to_method.update(dict.fromkeys(["http-method", "user-agent"], self.resolve_http_observable)) self.simple_type_to_method.update(dict.fromkeys(["pattern-in-file", "pattern-in-traffic", "pattern-in-memory"], self.resolve_pattern_observable))
def main(args): pathname = os.path.dirname(sys.argv[0]) stix2Event = loadEvent(args, pathname) stix2Event = stix2Event.get('objects') mispDict = buildMispDict(stix2Event) misp = pymisp.MISPEvent(None, False) misp.from_dict(**mispDict) saveFile(args, misp) print(1)
def main(args): pathname = os.path.dirname(args[0]) stixEvent = loadEvent(args, pathname) stixEvent = stixEvent["package"] mispDict = buildMispDict(stixEvent) #print(mispDict) misp = pymisp.MISPEvent(None, False) misp.from_dict(**mispDict) saveFile(args, pathname, misp) print(1)
def _insert_misp_event(self, intelmq_event): """Insert a new MISPEvent.""" new_misp_event = pymisp.MISPEvent() if 'feed.provider' in intelmq_event: new_misp_event.info = 'from {} via IntelMQ'.format( intelmq_event['feed.provider']) else: new_misp_event.info = 'via IntelMQ' # set the tags new_misp_event.add_tag(self.parameters.misp_tag_for_bot) if (self.parameters.add_feed_provider_as_tag and 'feed.provider' in intelmq_event): new_tag = 'IntelMQ:feed.provider="{}"'.format( intelmq_event['feed.provider']) new_misp_event.add_tag(new_tag) if (self.parameters.add_feed_name_as_tag and 'feed.name' in intelmq_event): new_tag = 'IntelMQ:feed.name="{}"'.format( intelmq_event['feed.name']) new_misp_event.add_tag(new_tag) for new_tag in self.parameters.misp_additional_tags: new_misp_event.add_tag(new_tag) # build the MISPObject and its attributes obj = new_misp_event.add_object(name=MISPOBJECT_NAME) fields_to_correlate = ( self.parameters.significant_fields + self.parameters.misp_additional_correlation_fields ) for object_relation, value in intelmq_event.items(): try: obj.add_attribute( object_relation, value=value, disable_correlation=( object_relation not in fields_to_correlate), to_ids=( object_relation in self.parameters.misp_to_ids_fields) ) except pymisp.NewAttributeError: msg = 'Ignoring "{}":"{}" as not in object template.' self.logger.debug(msg.format(object_relation, value)) misp_event = self.misp.add_event(new_misp_event) if self.parameters.misp_publish: self.misp.publish(misp_event) self.logger.info( 'Inserted new MISP event with id: {}'.format(misp_event.id))
def main(args): pathname = os.path.dirname(args[0]) stix2Event = loadEvent(args, pathname) stix2Event = stix2Event.get('objects') if checkIfFromMISP(stix2Event): mispDict = buildMispDict(stix2Event) else: mispDict = parseExternalStix(stix2Event) misp = pymisp.MISPEvent(None, False) misp.from_dict(**mispDict) saveFile(args, misp) print(1)
def create_event(self): event = pymisp.MISPEvent() event.info = 'test_event' event.threat_level_id = 3 event.distribution = 2 event.analysis = 1 event.add_attribute('ip-src', ip_list, comment='hogehoge') event.add_tag('test-dayo') event.publish() res = self.misp.add_event(event)
def main(args): pathname = os.path.dirname(args[0]) stixEvent, isJson = loadEvent(args, pathname) stixEvent = stixEvent["package"] if isJson: namefile = args[1] else: namefile = '{}.json'.format(args[1][:-4]) mispDict = buildMispDict(stixEvent) misp = pymisp.MISPEvent(None, False) misp.from_dict(**mispDict) saveFile(namefile, pathname, misp) print(1)
def get_misp_event(eventid, info): eventid=1#The event id of the MISP event to upload objects to #info="The event's title" misp = MakeConn().get() if eventid: event = misp.get_event(eventid) elif info: event = misp.new_event(info=info) else: event = misp.new_event(info="VirusTotal Report") misp_event = pymisp.MISPEvent() misp_event.load(event) return misp_event
def _event_obj(self) -> pymisp.MISPEvent: obj = pymisp.MISPEvent() obj.info = f"Intelowl Job-{self.job_id}" obj.distribution = 0 # your_organisation_only obj.threat_level_id = 4 # undefined obj.analysis = 2 # completed obj.add_tag("source:intelowl") obj.add_tag(f"tlp:{self.tlp}") # tlp tag for sharing # Add tags from Job for tag in self._job.tags.all(): obj.add_tag(f"intelowl-tag:{tag.label}") return obj
def insert_json(client, event_dict): #event_id = event_dict.get('Event', {}).get('id') uuid = event_dict.get('Event', {}).get('uuid') if uuid: event_obj = pymisp.MISPEvent() event_obj.from_dict(**event_dict) result = client.search(uuid=uuid) if len(result) > 0: client.update_event(event_obj) else: client.add_event(event_obj) else: raise Exception('There is no uuid in json')
def get_misp_event(event_id=None, info=None): ''' Smaller helper function for generating a new MISP event or using a preexisting one :event_id: The event id of the MISP event to upload objects to :info: The event's title/info ''' if event_id: event = misp.get_event(event_id) elif info: event = misp.new_event(info=info) else: event = misp.new_event(info="VirusTotal Report") misp_event = pymisp.MISPEvent() misp_event.load(event) return misp_event
def _create_event(self, artifact): """Create an event in MISP, return an Event object.""" event = pymisp.MISPEvent() event.info = self.event_info.format(source_name=artifact.source_name) # Add tags. for tag in self.tags: event.add_tag(tag) # Add references. if artifact.reference_link != "": event.add_attribute("link", artifact.reference_link) if artifact.reference_text != "": event.add_attribute("text", artifact.reference_text) if artifact.source_name != "": event.add_attribute("other", f'source:{artifact.source_name}') return event
def main(args): pathname = os.path.dirname(args[0]) stixEvent, isJson, fromMISP, stixJson = loadEvent(args, pathname) if isJson: namefile = args[1] else: namefile = '{}.json'.format(args[1]) if fromMISP: stixEvent = stixEvent["package"] mispDict = buildMispDict(stixEvent) else: if stixJson: mispDict = buildExternalDict(stixEvent) else: mispDict = buildExternalDict_fromPackage(stixEvent) misp = pymisp.MISPEvent(None, False) misp.from_dict(**mispDict) saveFile(namefile, pathname, misp) print(1)
def get_or_create_event(misp: pymisp.api.PyMISP, event_uuid: str): """ Returns a MISP Event with the given UUID. Creates a new event with the given UUID if it does not exist yet. @param misp The PyMISP instance to use @param event_uuid The Event UUID to fetch or create """ misp_event = pymisp.MISPEvent() misp_event.uuid = event_uuid event = misp.get_event(misp_event, deleted=False, pythonify=True) if not event or event.get("errors", None): logger.warn(f"Could not fetch MISP event with UUID {event_uuid}.") misp_event.info = "Retro-Matching roundtrip test event" event = misp.add_event(misp_event, pythonify=True) if not event or event.get("errors", None): errors = event.get("errors", {}) logger.critical( f"Error creating new event. Make sure the configured UUID is not already deleted in MISP: {errors}" ) logger.info(f"Created new MISP event with UUID '{event.uuid}'.") else: logger.info(f"Found MISP event with UUID '{event.uuid}'") return event
def parse(self, analysis_link, result): """ Parse the analysis result into a MISP event. :param str analysis_link: the analysis link :param dict[str, any] result: the JSON returned by the analysis client. :rtype: MISPEvent :return: some results that can be consumed by MIPS. """ self.misp_event = pymisp.MISPEvent() # Add analysis subject info if "url" in result["analysis_subject"]: o = pymisp.MISPObject("url") o.add_attribute("url", result["analysis_subject"]["url"]) else: o = pymisp.MISPObject("file") o.add_attribute("md5", type="md5", value=result["analysis_subject"]["md5"]) o.add_attribute("sha1", type="sha1", value=result["analysis_subject"]["sha1"]) o.add_attribute("sha256", type="sha256", value=result["analysis_subject"]["sha256"]) o.add_attribute( "mimetype", type="mime-type", value=result["analysis_subject"]["mime_type"] ) self.misp_event.add_object(o) # Add HTTP requests from url analyses network_dict = result.get("report", {}).get("analysis", {}).get("network", {}) for request in network_dict.get("requests", []): parsed_uri = parse.urlparse(request["url"]) o = pymisp.MISPObject(name='http-request') o.add_attribute('host', parsed_uri.netloc) o.add_attribute('method', "GET") o.add_attribute('uri', request["url"]) o.add_attribute("ip", request["ip"]) self.misp_event.add_object(o) # Add network behaviors from files for subject in result.get("report", {}).get("analysis_subjects", []): # Add DNS requests for dns_query in subject.get("dns_queries", []): hostname = dns_query.get("hostname") # Skip if it is an IP address try: if hostname == "wpad": continue _ = ipaddress.ip_address(hostname) continue except ValueError: pass o = pymisp.MISPObject(name='dns-record') o.add_attribute('queried-domain', hostname) self.misp_event.add_object(o) # Add HTTP conversations (as network connection and as http request) for http_conversation in subject.get("http_conversations", []): o = pymisp.MISPObject(name="network-connection") o.add_attribute("ip-src", http_conversation["src_ip"]) o.add_attribute("ip-dst", http_conversation["dst_ip"]) o.add_attribute("src-port", http_conversation["src_port"]) o.add_attribute("dst-port", http_conversation["dst_port"]) o.add_attribute("hostname-dst", http_conversation["dst_host"]) o.add_attribute("layer3-protocol", "IP") o.add_attribute("layer4-protocol", "TCP") o.add_attribute("layer7-protocol", "HTTP") self.misp_event.add_object(o) method, path, http_version = http_conversation["url"].split(" ") if http_conversation["dst_port"] == 80: uri = "http://{}{}".format(http_conversation["dst_host"], path) else: uri = "http://{}:{}{}".format( http_conversation["dst_host"], http_conversation["dst_port"], path ) o = pymisp.MISPObject(name='http-request') o.add_attribute('host', http_conversation["dst_host"]) o.add_attribute('method', method) o.add_attribute('uri', uri) o.add_attribute('ip', http_conversation["dst_ip"]) self.misp_event.add_object(o) # Add sandbox info like score and sandbox type o = pymisp.MISPObject(name="sandbox-report") sandbox_type = "saas" if is_analysis_hosted(analysis_link) else "on-premise" o.add_attribute("score", result["score"]) o.add_attribute("sandbox-type", sandbox_type) o.add_attribute("{}-sandbox".format(sandbox_type), "lastline") o.add_attribute("permalink", analysis_link) self.misp_event.add_object(o) # Add behaviors o = pymisp.MISPObject(name="sb-signature") o.add_attribute("software", "Lastline") for activity in result.get("malicious_activity", []): a = pymisp.MISPAttribute() a.from_dict(type="text", value=activity) o.add_attribute("signature", **a) self.misp_event.add_object(o) # Add mitre techniques for technique in self._get_mitre_techniques(result): self.misp_event.add_tag(technique)
def write_row(self, count, row, match, enrichments, output_stream): me = pymisp.MISPEvent() extra_info = self._extra_information_by_tag tag = match['tag'] containers = [row, match] if tag in extra_info: containers.append(extra_info[tag]) # create the "subject" (info) line me.info = self.construct_info(containers) # create attributes self.add_attributes(me, containers) # set basic attributes me.published = False me.distribution = "1" try: ts = float(row['ts']) me.set_date(ts) except Exception: try: t = dateparser.parse(row['ts']) me.set_date(t.timestamp()) except Exception: sys.stderr.write(f"couldn't convert date: {row['ts']}\n") # manually constructed attributes if 'uri' in row and row['uri'] != '-' and 'host' in row: me.add_attribute( type='url', category='Network activity', value=f'http://{row["host"]}:{row["id_resp_p"]}{row["uri"]}') # add in the row itself row_description = "" for item in row: row_description += f"{item}: {row[item]}\n" me.add_attribute(type='text', category="External analysis", value=row_description, comment="zeek row") # and the match match_description = "" for item in match: match_description += f"{item}: {match[item]}\n" me.add_attribute(type='text', category="External analysis", value=match_description, comment="threat source information") # If there is an external link to use, add it if self._web_report_urls: if not isinstance(self._web_report_urls, list): self._web_report_urls = [self._web_report_urls] for url in self._web_report_urls: location = url.format(count=count, row=row, match=match, enrichments=enrichments) me.add_attribute(type='link', category="External analysis", value=location, comment="GAWSEED report") # fake a priority if 'priority' in match: if match['priority'] >= 8: me.threat_level = 1 me.threat_level_id = 1 elif match['priority'] >= 5: me.threat_level = 2 me.threat_level_id = 2 else: me.threat_level = 3 me.threat_level_id = 3 self._misp.add_event(me)
def create_events(pulse_or_list, author=False, server=False, key=False, misp=False, blacklist_file = None, distribution=0, threat_level=4, analysis=2, publish=True, tlp=True, discover_tags=False, to_ids=False, author_tag=False, bulk_tag=None, dedup_titles=False, stop_on_error=False): """ Parse a Pulse or a list of Pulses and add it/them to MISP if server and key are present :param pulse_or_list: a Pulse or list of Pulses as returned by `get_pulses` :param author: Prepend the author to the Pulse name :type author: Boolean :param server: MISP server URL :param key: MISP API key :param misp: MISP connection object :type misp: :class:`pymisp.PyMISP` :param blacklist_file: The name of a file containing a list of pulse title regexes for pulses taht should be ignored :type blacklist_file: String :param distribution: distribution of the MISP event (0-4) :param threat_level: threat level of the MISP object (1-4) :param analysis: analysis stae of the MISP object (0-2) :param publish: Is the MISP event should be published? :type publish: Boolean :param tlp: Add TLP level tag to event :type tlp: Boolean :param discover_tags: discover MISP tags from Pulse tags :type discover_tags: Boolean :param to_ids: Flag pulse attributes as being sent to an IDS :type to_ids: Boolean :param author_tag: Add the pulse author as an event tag :type author_tag: Boolean :param bulk_tag: A tag that will be added to all events for categorization (e.g. OTX) :type bulk_tag: String :param dedup_titles: Search MISP for an existing event title and update it, rather than create a new one :type dedup_titles: Boolean :return: a dict or a list of dict with the selected attributes """ if not misp and (server and key): log.debug("Connection to MISP instance: {}".format(server)) try: misp = pymisp.ExpandedPyMISP(server, key, ssl=False) except pymisp.PyMISPError as ex: raise ImportException("Cannot connect to MISP instance: {}".format(ex.message)) except Exception as ex: raise ImportException("Cannot connect to MISP instance, unknown exception: {}".format(ex.message)) # Let's load the list of blacklisted pulse titles, if exists global _otx_blacklisted_titles if blacklist_file and not _otx_blacklisted_titles: if not os.path.isfile(blacklist_file): log.warn("The blacklisted pulse titles file that has been provided does not exist: {}".format(blacklist_file)) else: with open(blacklist_file) as f: lines = f.read().splitlines() for line in lines: if line != "": _otx_blacklisted_titles.append(re.compile(line)) # Let's load in cache all MISP tags available on the instance global _otx_tags_cache if _otx_tags_cache is None: _otx_tags_cache = misp.tags() if discover_tags: def get_tag_name(complete): parts = complete.split('=') if not len(parts): return complete last = parts[-1] if not len(last): return complete if last[0] == '"': last = last[1:] if last[-1] == '"': last = last[:-1] return last.lower() tags = dict() for tag in _otx_tags_cache: tags[get_tag_name(tag['name'])] = tag['name'] misp.discovered_tags = tags if isinstance(pulse_or_list, (list, tuple)) or inspect.isgenerator(pulse_or_list): misp_events = [] for pulse in pulse_or_list: try: misp_event = create_events(pulse, author=author, server=server, key=key, misp=misp, distribution=distribution, threat_level=threat_level, analysis=analysis, publish=publish, tlp=tlp, to_ids=to_ids, author_tag=author_tag, bulk_tag=bulk_tag, dedup_titles=dedup_titles, stop_on_error=stop_on_error) if misp_event: misp_events.append(misp_event) except Exception as ex: if stop_on_error: raise name = '' if pulse and 'name' in pulse: name = pulse['name'] log.error("Cannot import pulse {}: {}".format(name, ex)) return misp_events pulse = pulse_or_list if author: event_name = pulse['author_name'] + ' | ' + pulse['name'] else: event_name = pulse['name'] event_name = event_name.strip() try: dt = date_parser.parse(pulse['created']) except (ValueError, OverflowError): log.error("Cannot parse Pulse 'created' date.") dt = datetime.utcnow() event_date = dt.strftime('%Y-%m-%d') # Let's ignore the pulse if its title is blacklisted for regex in _otx_blacklisted_titles: if regex.match(pulse['name']): log.info("## *** IGNORED *** {name} - {date}".format(name=event_name, date=event_date)) return None log.info("## {name} - {date}".format(name=event_name, date=event_date)) result_event = { 'name': event_name, 'date': event_date, 'tags': list(), 'attributes': { 'hashes': { 'md5': list(), 'sha1': list(), 'sha256': list(), 'imphash': list(), 'pehash': list() }, 'hostnames': list(), 'domains': list(), 'urls': list(), 'ips': list(), 'emails': list(), 'mutexes': list(), 'references': list(), 'cves': list(), 'filenames': list(), 'yara': list() }, } if misp: if not dedup_titles: event = pymisp.MISPEvent() event.distribution = distribution event.threat_level_id = threat_level event.analysis = analysis event.info = event_name event.date = dt event = misp.add_event(event)['Event'] else: event = '' # Search MISP for the title result = misp.search(eventinfo=event_name, metadata=True) if len(result) == 0: event = pymisp.MISPEvent() event.distribution = distribution event.threat_level = threat_level event.analysis = analysis event.info = event_name event.set_date(dt) event = misp.add_event(event)['Event'] else: for evt in result: # If it exists, set 'event' to the event if evt['Event']['info'] == event_name: if 'SharingGroup' in evt['Event']: del evt['Event']['SharingGroup'] # This deletes the SharingGroup from the list, thx SparkyNZL event = evt['Event'] break if event == '': # Event not found, even though search results were returned # Build new event event = pymisp.MISPEvent() event.distribution = distribution event.threat_level = threat_level event.analysis = analysis event.info = event_name event.set_date(dt) misp.add_event(event) time.sleep(0.2) if tlp: tag = None if 'TLP' in pulse: tag = "tlp:{}".format(pulse['TLP']) elif 'tlp' in pulse: tag = "tlp:{}".format(pulse['tlp']) if tag is not None: log.info("\t - Adding tag: {}".format(tag)) tag_event(misp, event, tag) result_event['tags'].append(tag) if author_tag: tag_event(misp, event, pulse['author_name']) if bulk_tag is not None: tag_event(misp, event, bulk_tag) if misp and hasattr(misp, 'discovered_tags') and 'tags' in pulse: for pulse_tag in pulse['tags']: if pulse_tag.lower() in misp.discovered_tags: tag = misp.discovered_tags[pulse_tag.lower()] log.info("\t - Adding tag: {}".format(tag)) tag_event(misp, event, tag) result_event['tags'].append(tag) if 'references' in pulse: for reference in pulse['references']: if reference: log.info("\t - Adding external analysis link: {}".format(reference)) if misp: a = pymisp.MISPAttribute() a.category = "External analysis" a.type = 'link' a.value = reference add_attribute(misp, event, a) result_event['attributes']['references'].append(reference) if misp and 'description' in pulse and isinstance(pulse['description'], six.text_type) and pulse['description']: log.info("\t - Adding external analysis comment") a = pymisp.MISPAttribute() a.category = 'External analysis' a.type = 'comment' a.value = pulse['description'] add_attribute(misp, event, a) for ind in pulse['indicators']: ind_type = ind['type'] ind_val = ind['indicator'] a = pymisp.MISPAttribute() a.value = ind_val a.to_ids = to_ids if 'description' in ind and isinstance(ind['description'], six.text_type) and ind['description']: a.comment = ind['description'] if ind_type == 'FileHash-SHA256': log.info("\t - Adding SHA256 hash: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'sha256' add_attribute(misp, event, a) result_event['attributes']['hashes']['sha256'].append(ind_val) elif ind_type == 'FileHash-SHA1': log.info("\t - Adding SHA1 hash: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'sha1' add_attribute(misp, event, a) result_event['attributes']['hashes']['sha1'].append(ind_val) elif ind_type == 'FileHash-MD5': log.info("\t - Adding MD5 hash: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'md5' add_attribute(misp, event, a) result_event['attributes']['hashes']['md5'].append(ind_val) elif ind_type == 'FileHash-IMPHASH': log.info("\t - Adding IMPHASH hash: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'imphash' add_attribute(misp, event, a) result_event['attributes']['hashes']['imphash'].append(ind_val) elif ind_type == 'FileHash-PEHASH': log.info("\t - Adding PEHASH hash: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'pehash' add_attribute(misp, event, a) result_event['attributes']['hashes']['pehash'].append(ind_val) elif ind_type == 'YARA': ind_title = ind.get('title', ind_val) ind_desc = ind.get('description', '') if ind_title == '': ind_title = ind_val if not ind_desc == '': a.comment = ind_desc else: a.comment = "{} {}".format(ind_title, ind_desc) ind_val = ind.get('content', None) if ind_val is None or ind_val == "": log.warning("YARA indicator is empty: %s" % ind_title) continue log.info("\t - Adding YARA rule: {}".format(ind_title)) a.category = 'Artifacts dropped' a.type = 'yara' a.value = ind_val add_attribute(misp, event, a) result_event['attributes']['yara'].append({'title': ind_title, 'content': ind_val}) elif ind_type == 'Mutex': log.info("\t - Adding mutex: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'mutex' add_attribute(misp, event, a) result_event['attributes']['mutexes'].append(ind_val) elif ind_type == 'FilePath': log.info("\t - Adding filename: {}".format(ind_val)) a.category = 'Artifacts dropped' a.type = 'filename' add_attribute(misp, event, a) result_event['attributes']['filenames'].append(ind_val) elif ind_type == 'URI' or ind_type == 'URL': log.info("\t - Adding URL: {}".format(ind_val)) a.category = 'Network activity' a.type = 'url' add_attribute(misp, event, a) result_event['attributes']['urls'].append(ind_val) elif ind_type == 'domain': log.info("\t - Adding domain: {}".format(ind_val)) a.category = 'Network activity' a.type = 'domain' add_attribute(misp, event, a) result_event['attributes']['domains'].append(ind_val) elif ind_type == 'hostname': log.info("\t - Adding hostname: {}".format(ind_val)) a.category = 'Network activity' a.type = 'hostname' add_attribute(misp, event, a) result_event['attributes']['hostnames'].append(ind_val) elif ind_type == 'IPv4' or ind_type == 'IPv6': log.info("\t - Adding ip: {}".format(ind_val)) a.category = 'Network activity' a.type = 'ip-dst' add_attribute(misp, event, a) result_event['attributes']['ips'].append(ind_val) elif ind_type == 'email': log.info("\t - Adding email: {}".format(ind_val)) a.category = 'Network activity' a.type = 'email-dst' result_event['attributes']['emails'].append(ind_val) add_attribute(misp, event, a) elif ind_type == 'CVE': log.info("\t - Adding CVE: {}".format(ind_val)) a.type = 'External analysis' a.type = 'vulnerability' add_attribute(misp, event, a) result_event['attributes']['cves'].append(ind_val) else: log.warning("Unsupported indicator type: %s" % ind_type) if misp and publish: misp.publish(event) return result_event
def __init__(self): self.misp_event = pymisp.MISPEvent() self.SDOs = [] self.object_refs = [] self.external_refs = []
def __init__(self): self.misp_event = pymisp.MISPEvent() self.event = [] self.misp_event['Galaxy'] = []
def createActor(iUUID, iUpdate=False): try: # fUNCTION SETUP # ----------------------------------------------- myUUID = iUUID myLinks = [] myTags = [] myMeta = [] myCommonName = "" # ATTRIBUTES COMMON FIELDS # ----------------------------------------------- attributeToIDS = 0 # 0 false : 1 true attributeComment = "" attribDisableCorrelation = 1 # 0 false : 1 true # MISP SETUP # ----------------------------------------------- event = pm.MISPEvent() event.uuid = myUUID # GET META FOR ACTOR (USE COMMON NAME AS INCIDENT NAME) myMeta = db.get_actor_meta(myUUID) if gv._DEBUG: print("f(x) createActor: ACTOR META") print(json.dumps(myMeta, indent=4)) # USED AS INCIDENT NAME myCommonName = myMeta["commonname"] event.info = "Threat Actor: " + myCommonName print("f(x) createActor: ACTOR NAME: {}".format(myCommonName)) # USED AS A TEXT ATTRIBUTE myDescription = myMeta["description"] if myDescription != "": attributeType = "text" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createFamily: CREATING FAMILY COMMENT: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, myDescription, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, myDescription, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # ----------------------------------------------- # GET TAGS if myCommonName != "UNATTRIBUTED" and myCommonName != "ERROR": # GET TAGS myTags = db.get_set_all_tags(myUUID) event.tags = myTags if gv._DEBUG: print("f(x) createActor: TAGS CREATED") print(*myTags, sep="\n") # REFERENCES/URLS myLinks = db.get_links(myUUID) for link in myLinks: attributeType = "link" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createActor: CREATING ACTOR LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {}\nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, link["url"], attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute( attributeType, link["url"], comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # MARK SOURCE OF INFORMATION attributeType = "link" attributeCategory = "Internal reference" attributeComment = "DATA FROM MALPEDIA." if gv._DEBUG: print( "f(x) createActor: CREATING ACTOR ATTRIBUTION LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, gv._MALPEDIA_URL, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, gv._MALPEDIA_URL, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) gv._THREAD_LIST.append( executor.submit(pushToMISP, event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG)) # pushToMISP(event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG) except Exception as e: exc_type, _, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print("f(x) createActor: {}: {}: {}".format(exc_type, fname, exc_tb.tb_lineno)) sys.exit(e)
def createFamily(iUUID, iUpdate=False): try: # fUNCTION SETUP # ----------------------------------------------- myUUID = iUUID myLinks = [] myTags = [] myMeta = [] myCommonName = "" # ATTRIBUTES COMMON FIELDS # ----------------------------------------------- attributeToIDS = 0 # 0 false : 1 true attributeComment = "" attribDisableCorrelation = 1 # 0 false : 1 true # MISP SETUP # ----------------------------------------------- event = pm.MISPEvent() event.uuid = myUUID # GET UUID METADATA FROM PARENT CHILD TABLE # ----------------------------------------------- iPC_META = db.get_parent_child_data(iUUID=myUUID) parentuuid = iPC_META["parentuuid"] event.extends_uuid = parentuuid # ----------------------------------------------- # REFERENCES/URLS myLinks = db.get_links(myUUID) for link in myLinks: attributeType = "link" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createFamily: LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {}\nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, link["url"], attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, link["url"], comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # GET TAGS myTags = db.get_set_all_tags(myUUID) event.tags = myTags if gv._DEBUG: print("f(x) createFamily: TAGS") print(*myTags, sep="\n") # GET META FOR ACTOR (USE COMMON NAME AS INCIDENT NAME) myMeta = db.get_family_meta(iUUID=myUUID) if gv._DEBUG: print("f(x) createFamily: META") print(json.dumps(myMeta, indent=4)) # USED AS INCIDENT NAME myCommonName = myMeta["commonname"] event.info = myCommonName print("f(x) createFamily: MALWARE NAME: {}".format(myCommonName)) # USED AS A TEXT ATTRIBUTE myDescription = myMeta["description"] if myDescription != "": attributeType = "text" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createFamily: CREATING FAMILY COMMENT: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, myDescription, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, myDescription, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # MARK SOURCE OF INFORMATION attributeType = "link" attributeCategory = "Internal reference" attributeComment = "DATA FROM MALPEDIA." if gv._DEBUG: print( "f(x) createFamily: ATTRIBUTION LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, gv._MALPEDIA_URL, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, gv._MALPEDIA_URL, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # YARA # ADD OBJECTS # ----------------------------------------------- # YARA iYara = db.get_yara_rules(myUUID) tlp = "" yaraAbsPath = "" for yara in iYara: tagList = [] newTag = MISPTag() tlp = yara["tlp"] yaraAbsPath = yara["path_to_yara"] tlpTag = "tlp:" + tlp.split("_")[1] newTag.name = tlpTag tagList.append(newTag) yaraUUID = yara["attribute_uuid"] yaraContents = "" with open(yaraAbsPath, 'r') as yaraIn: yaraContents = yaraIn.read() yaraIn.close() misp_object = pm.tools.GenericObjectGenerator("yara") misp_object.comment = tlpTag misp_object.uuid = yaraUUID subAttribute = misp_object.add_attribute("yara", yaraContents) subAttribute.disable_correlation = True subAttribute.to_ids = False subAttribute.comment = tlpTag subAttribute.tags = tagList event.add_object(misp_object) if gv._DEBUG: print("f(x) createFamily: YARA") print(*iYara, sep="\n") gv._THREAD_LIST.append( executor.submit(pushToMISP, event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG)) # pushToMISP(event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG) except Exception as e: exc_type, _, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print("f(x) createFamily: {}: {}: {}".format(exc_type, fname, exc_tb.tb_lineno)) sys.exit(e)
def createPath(iUUID, iUpdate=False): try: # fUNCTION SETUP # ----------------------------------------------- myUUID = iUUID myTags = [] myName = "" # ATTRIBUTES COMMON FIELDS # ----------------------------------------------- attributeToIDS = 0 # 0 false : 1 true attributeComment = "" attribDisableCorrelation = 1 # 0 false : 1 true # MISP SETUP # ----------------------------------------------- event = pm.MISPEvent() event.uuid = myUUID # GET UUID METADATA FROM PARENT CHILD TABLE # ----------------------------------------------- iPC_META = db.get_parent_child_data(iUUID=myUUID) parentuuid = iPC_META["parentuuid"] myName = iPC_META["name"] event.extends_uuid = parentuuid event.info = myName print("f(x) createPath: MALWARE PATH NAME: {}".format(myName)) # GET TAGS FROM PARENT AND ADD TO THIS PATH myTags = db.get_set_all_tags(myUUID) event.tags = myTags if gv._DEBUG: print("f(x) createPath: TAGS") print(*myTags, sep="\n") # MARK SOURCE OF INFORMATION attributeType = "link" attributeCategory = "Internal reference" attributeComment = "DATA FROM MALPEDIA." if gv._DEBUG: print( "f(x) createPath: ATTRIBUTION LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, gv._MALPEDIA_URL, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, gv._MALPEDIA_URL, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) gv._THREAD_LIST.append( executor.submit(pushToMISP, event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG)) # pushToMISP(event, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG) except Exception as e: exc_type, _, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print("f(x) createPath: {}: {}: {}".format(exc_type, fname, exc_tb.tb_lineno)) sys.exit(e)
def createMalware(iUUID, iUpdate=False): try: # fUNCTION SETUP # ----------------------------------------------- myUUID = iUUID myTags = [] # ATTRIBUTES COMMON FIELDS # ----------------------------------------------- attributeToIDS = 0 # 0 false : 1 true attributeComment = "" attribDisableCorrelation = 1 # 0 false : 1 true # MISP SETUP # ----------------------------------------------- event = pm.MISPEvent() event.uuid = myUUID # GET UUID METADATA FROM PARENT CHILD TABLE # ----------------------------------------------- iPC_META = db.get_parent_child_data(iUUID=myUUID) parentuuid = iPC_META["parentuuid"] event.extends_uuid = parentuuid name = iPC_META["name"] if name in gv._BLACKLISTED_FILES: return True event.info = name print("f(x) createMalware: MALWARE SAMPLE NAME: {}".format(name)) # SET VERSION myVersion = iPC_META["version"] if myVersion != "": attributeType = "text" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createMalware: CREATING FAMILY COMMENT: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, myVersion, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, myVersion, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # SET DATE ADDED date_added = iPC_META["date_added"] if valid_date(date_added): event.date = date_added else: event.date = datetime.date.today() # GET TAGS myTags = db.get_set_all_tags(myUUID) event.tags = myTags if gv._DEBUG: print("f(x) createMalware: TAGS") print(*myTags, sep="\n") # MARK SOURCE OF INFORMATION attributeType = "link" attributeCategory = "Internal reference" attributeComment = "DATA FROM MALPEDIA." if gv._DEBUG: print( "f(x) createMalware: ATTRIBUTION LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, gv._MALPEDIA_URL, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, gv._MALPEDIA_URL, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # ADD ATTACHMENT myPath = iPC_META["path"] fo = None peo = None seos = None # CREATE ATTACHMENT BUT DON'T UPLOAD IT AGAIN IF THIS IS JUST AN UPDATE if iUpdate == False: for f in glob.glob(iPC_META["path"]): try: fo, peo, seos = make_binary_objects(f) except Exception as e: continue gv._THREAD_LIST.append( uexecutor.submit(pushToMISPWithAttachment, event, myPath, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG, fo, peo, seos)) # pushToMISPWithAttachment(event, myPath, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG, fo , peo, seos) except Exception as e: exc_type, _, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print("f(x) createMalware: {}: {}: {}".format(exc_type, fname, exc_tb.tb_lineno)) sys.exit(e)
def main(args): logging.info('Passing through misp_exporter') with open(args.fingerprint) as file: try: data = json.load(file) except Exception: logging.error('Fingerprint not compatible.') return misp = pymisp.ExpandedPyMISP(args.misp_url, args.misp_key, ssl=False, debug=True) event = pymisp.MISPEvent(strict_validation=True) event.info = args.event_info event.distribution = args.distribution event.threat_level_id = args.threat_level event.analysis = args.analysis_level event.add_tag(tag='validated') ddos = pymisp.MISPObject('ddos', strict=True) logging.info('Fingerprint processed: {}'.format(args.fingerprint)) if 'attack_vector' in data: av = data['attack_vector'][0] snort = { 'protocol': [], 'src_ip': [], 'src_port': [], 'dst_port': [], 'options': [], } df = find_ips(av) logging.info('IPs found: {}'.format(len(df['ip']))) subnets = utils.smart_aggregate(df) logging.info('The IPs were summarized in: {} subnets'.format( len(subnets))) if args.subnets: add_attributes(event, subnets, 'ip-src', 'attacker subnet') ddos.add_attributes('ip-src', *subnets) snort['src_ip'] += subnets else: add_attributes(event, df['ip'], 'ip-src', 'attacker ip') ddos.add_attributes('ip-src', *df['ip']) snort['src_ip'] += df['ip'].tolist() if 'srcport' in av: sport = find_attr(av['srcport'], 'srcport') add_attributes(event, sport['srcport'], 'port', 'source port of attack') ddos.add_attributes('src-port', *sport['srcport']) snort['src_port'] += sport['srcport'].tolist() if 'dstport' in av: dport = find_attr(av['dstport'], 'dstport') add_attributes(event, dport['dstport'], 'port', 'destination port of attack') ddos.add_attributes('dst-port', *sport['dstport']) snort['dst_port'] += sport['dstport'] if 'ip_proto' in av: proto4 = find_attr(av['ip_proto'], 'ip_proto') add_attributes(event, proto4['ip_proto'], 'other', '4 level protocol of attack') ddos.add_attributes('protocol', *proto4['ip_proto']) snort['protocol'] += proto4['ip_proto'].tolist() if 'dns_qry_name' in av: snort['options'] += snort_content(av['dns_qry_name']) if 'http_request' in av: snort['options'] += snort_content(av['http_request']) if 'http_response' in av: snort['options'] += snort_content(av['http_response']) if 'http_user_agent' in av: snort['options'] += snort_content(av['http_user_agent']) if 'icmp_type' in av: snort['options'] += snort_itype(av['icmp_type']) if 'icmp_code' in av: snort['options'] += snort_icode(av['icmp_code']) if 'ip_ttl' in av: snort['options'] += snort_ttl(av['ip_ttl']) if 'ntp_priv_reqcode' in av: snort['options'] += snort_content(av['ntp_priv_reqcode']) if 'tcp_flags' in av: snort['options'] += snort_flags(av['tcp_flags']) if 'tags' in av: for tag in av['tags']: event.add_tag(tag=tag) if 'duration_sec' in av: add_attribute_comment(event, 'duration_sec', av['duration_sec']) if 'total_dst_ports' in av: add_attribute_comment(event, 'total_dst_ports', av['total_dst_ports']) if 'total_ips' in av: add_attribute_comment(event, 'total_ips', av['total_ips']) if 'total_packets' in av: add_attribute_comment(event, 'total_packets', av['total_packets']) add_attribute_snort(event, snort) event.add_tag(tag='ddos attack') if 'amplifiers' in data: amp = data['amplifiers'][0] dfa = find_ips(amp) logging.info('Amplifier IPs found: {}'.format(len(dfa['ip']))) subnetsa = utils.smart_aggregate(dfa) logging.info('The IPs were summarized in: {} subnets'.format( len(subnetsa))) if args.subnets: add_attributes(event, subnetsa, 'ip-src', 'amplifier subnet') for elem in subnetsa: ddos.add_attribute('ip-src', elem, to_ids=0) else: add_attributes(event, dfa['ip'], 'ip-src', 'amplifier ip') for elem in dfa['ip']: ddos.add_attribute('ip-src', elem, to_ids=0) event.add_tag(tag='ddos amplification attack') p = pathlib.Path(args.fingerprint) comment = 'DDoS fingerprint json file generated by dissector' event.add_attribute(type='attachment', value=p.name, data=p, comment=comment) event.add_object(ddos, pythonify=True) event = misp.add_event(event, pythonify=True)
def misp_send(self, strMISPEventID, strInput, strInfo, strUsername): # Establish communication with MISP. # The main processing block. try: objects = [] # Get comments and tags from string input. str_comment, tags = self.get_comm_and_tags(strInput) if tags == None: self.misp_logger.info('Irate not in Tags: %s equals None' % tags) response = None return response # Setup misp objects. mispobj_email = pymisp.MISPObject(name="email") mispobj_file = pymisp.MISPObject(name="file") mispobj_files = {} mispobj_domainip = pymisp.MISPObject(name="domain-ip") url_no = 0 file_no = 0 mispobj_urls = {} for line in strInput.splitlines(): # Catch domain and add to domain/IP object. if ("domain:" in line.lower()): mispobj_domainip = pymisp.MISPObject(name="domain-ip") vals = line.split(":", 1) mispobj_domainip.add_attribute("domain", value=vals[1].strip(), comment=str_comment) objects.append(mispobj_domainip) # Catch IP and add to domain/IP object. elif ("ip:" in line.lower()) or ( "ip-dst:" in line.lower()) or ("ip-src:" in line.lower()): if "domain:" in strInput.splitlines(): mispobj_domainip = pymisp.MISPObject(name="domain-ip") vals = line.split(":", 1) mispobj_domainip.add_attribute("ip", value=vals[1].strip(), comment=str_comment) objects.append(mispobj_domainip) else: mispobj_network_connection = pymisp.MISPObject( name="network-connection") vals = line.split(":", 1) if ("ip:" in line.lower()) or ("ip-dst:" in line.lower()): mispobj_network_connection.add_attribute( "ip-dst", type="ip-dst", value=vals[1].strip(), comment=str_comment) else: mispobj_network_connection.add_attribute( "ip-src", type="ip-src", value=vals[1].strip(), comment=str_comment) objects.append(mispobj_network_connection) # Catch email and add to email object. elif ("source-email:" in line.lower()) or ( "email-source" in line.lower()) or ("from:" in line.lower()): vals = line.split(":", 1) mispobj_email.add_attribute("from", value=vals[1].strip(), comment=str_comment) # Catch URL and add to URL object. elif ("url:" in line.lower()) or ( ('kit:' in line.lower() or ('creds:' in line.lower())) and (('hxxp' in line.lower()) or ('http' in line.lower()))): vals = line.split(":", 1) url = vals[1].strip() url = refang(url) parsed = urlparse(url) mispobj_url = pymisp.MISPObject(name="url") mispobj_url.add_attribute("url", value=parsed.geturl(), category="Payload delivery", comment=str_comment) if parsed.hostname: mispobj_url.add_attribute("host", value=parsed.hostname, comment=str_comment) if parsed.scheme: mispobj_url.add_attribute("scheme", value=parsed.scheme, comment=str_comment) if parsed.port: mispobj_url.add_attribute("port", value=parsed.port, comment=str_comment) mispobj_urls[url_no] = mispobj_url url_no += 1 # Catch different hash types, and add to file object. elif ("sha1:" in line.lower()) or ("SHA1:" in line): vals = line.split(":", 1) mispobj_file.add_attribute("sha1", value=vals[1].strip(), comment=str_comment) elif ("sha256:" in line.lower()) or ("SHA256:" in line): vals = line.split(":", 1) mispobj_file.add_attribute("sha256", value=vals[1].strip(), comment=str_comment) elif ("md5:" in line.lower()) or ("MD5:" in line): vals = line.split(":", 1) mispobj_file.add_attribute("md5", value=vals[1].strip(), comment=str_comment) # Catch subject and add to email object. elif ("subject:" in line.lower()): self.misp_logger.info('adding subject') vals = line.split(":", 1) mispobj_email.add_attribute("subject", value=vals[1].strip(), comment=str_comment) # catch hash|filename pair and add to file object. elif ("hash|filename:" in line.lower()): vals = line.split(":", 1) val = vals[1].split("|") l_hash = val[0] l_filename = val[1] l_mispobj_file = pymisp.MISPObject(name="file") if len(re.findall(r"\b[a-fA-F\d]{32}\b", l_hash)) > 0: l_mispobj_file.add_attribute("md5", value=l_hash.strip(), comment=str_comment) l_mispobj_file.add_attribute("filename", value=l_filename.strip(), comment=str_comment) mispobj_files[file_no] = l_mispobj_file elif len(re.findall(r'\b[0-9a-f]{40}\b', l_hash)) > 0: l_mispobj_file.add_attribute("sha1", value=l_hash.strip(), comment=str_comment) l_mispobj_file.add_attribute("filename", value=l_filename.strip(), comment=str_comment) mispobj_files[file_no] = l_mispobj_file elif len(re.findall(r'\b[A-Fa-f0-9]{64}\b', l_hash)) > 0: l_mispobj_file.add_attribute("sha256", value=l_hash.strip(), comment=str_comment) l_mispobj_file.add_attribute("filename", value=l_filename.strip(), comment=str_comment) mispobj_files[file_no] = l_mispobj_file file_no += 1 # Add all misp objects to List to be processed and submitted to MISP server as one. if len(mispobj_file.attributes) > 0: objects.append(mispobj_file) if len(mispobj_email.attributes) > 0: objects.append(mispobj_email) for _, u_value in mispobj_urls.items(): if len(u_value.attributes) > 0: objects.append(u_value) for _, f_value in mispobj_files.items(): if len(f_value.attributes) > 0: objects.append(f_value) # Update timestamp and event. except Exception: error = traceback.format_exc() response = "Error occured when converting string to misp objects:\n %s" % error self.misp_logger.error(response) return response if self.check_object_length(objects) != True: self.misp_logger.error( 'Input from %s did not contain accepted tags.\n Input: \n%s' % (strUsername, strInput)) return "Error in the tags you entered. Please see the guide for accepted tags." try: event = self.misp.new_event(info=strInfo, distribution='0', analysis='2', threat_level_id='3', published=True) misp_event = pymisp.MISPEvent() misp_event.load(event) self.submit_to_misp(self.misp, misp_event, objects) for tag in tags: self.misp.tag(misp_event.uuid, tag) self.misp.add_internal_comment(misp_event.id, reference="Author: " + strUsername, comment=str_comment) self.misp.fast_publish(misp_event.id, alert=False) misp_event = self.misp.get_event(misp_event.id) response = misp_event # for response in misp_event: if ('errors' in response and response['errors'] != None): return ("Submission error: " + repr(response['errors'])) else: if response['Event']['RelatedEvent']: e_related = "" for each in response['Event']['RelatedEvent']: e_related = e_related + each['Event']['id'] + ", " return "Created ID: " + str( response['Event'] ['id']) + "\nRelated Events: " + ''.join(e_related) else: return "Created ID: " + str(response['Event']['id']) except Exception: error = traceback.format_exc() response = "Error occured when submitting to misp:\n %s" % error self.misp_logger.error(response) return response
def add_event(self, event: DtlMispEvent): """Add a new event into the misp. If the event already exist, it is ignored""" misp_event = pymisp.MISPEvent() misp_event.load(event) if not self.misp_backend.event_exists(misp_event): return self.misp_backend.add_event(misp_event, pythonify=True)
def parse(self, analysis_link: str, result: Dict[str, Any]) -> pymisp.MISPEvent: """ Parse the analysis result into a MISP event. :param str analysis_link: the analysis link :param dict[str, any] result: the JSON returned by the analysis client. :rtype: pymisp.MISPEvent :return: a MISP event """ misp_event = pymisp.MISPEvent() # Add analysis subject info if "url" in result["analysis_subject"]: o = pymisp.MISPObject("url") o.add_attribute("url", result["analysis_subject"]["url"]) else: o = pymisp.MISPObject("file") o.add_attribute("md5", type="md5", value=result["analysis_subject"]["md5"]) o.add_attribute("sha1", type="sha1", value=result["analysis_subject"]["sha1"]) o.add_attribute("sha256", type="sha256", value=result["analysis_subject"]["sha256"]) o.add_attribute("mimetype", category="Payload delivery", type="mime-type", value=result["analysis_subject"]["mime_type"]) misp_event.add_object(o) # Add HTTP requests from url analyses network_dict = result.get("report", {}).get("analysis", {}).get("network", {}) for request in network_dict.get("requests", []): if not request["url"] and not request["ip"]: continue o = pymisp.MISPObject(name="http-request") o.add_attribute("method", "GET") if request["url"]: parsed_uri = parse.urlparse(request["url"]) o.add_attribute("host", parsed_uri.netloc) o.add_attribute("uri", request["url"]) if request["ip"]: o.add_attribute("ip-dst", request["ip"]) misp_event.add_object(o) # Add network behaviors from files for subject in result.get("report", {}).get("analysis_subjects", []): # Add DNS requests for dns_query in subject.get("dns_queries", []): hostname = dns_query.get("hostname") # Skip if it is an IP address try: if hostname == "wpad" or hostname == "localhost": continue # Invalid hostname, e.g., hostname: ZLKKJRPY or 2.2.0.10.in-addr.arpa. if "." not in hostname or hostname[-1] == ".": continue _ = ipaddress.ip_address(hostname) continue except ValueError: pass o = pymisp.MISPObject(name="domain-ip") o.add_attribute("hostname", type="hostname", value=hostname) for ip in dns_query.get("results", []): o.add_attribute("ip", type="ip-dst", value=ip) misp_event.add_object(o) # Add HTTP conversations (as network connection and as http request) for http_conversation in subject.get("http_conversations", []): o = pymisp.MISPObject(name="network-connection") o.add_attribute("ip-src", http_conversation["src_ip"]) o.add_attribute("ip-dst", http_conversation["dst_ip"]) o.add_attribute("src-port", http_conversation["src_port"]) o.add_attribute("dst-port", http_conversation["dst_port"]) o.add_attribute("hostname-dst", http_conversation["dst_host"]) o.add_attribute("layer3-protocol", "IP") o.add_attribute("layer4-protocol", "TCP") o.add_attribute("layer7-protocol", "HTTP") misp_event.add_object(o) method, path, http_version = http_conversation["url"].split( " ") if http_conversation["dst_port"] == 80: uri = "http://{}{}".format(http_conversation["dst_host"], path) else: uri = "http://{}:{}{}".format( http_conversation["dst_host"], http_conversation["dst_port"], path) o = pymisp.MISPObject(name="http-request") o.add_attribute("host", http_conversation["dst_host"]) o.add_attribute("method", method) o.add_attribute("uri", uri) o.add_attribute("ip-dst", http_conversation["dst_ip"]) misp_event.add_object(o) # Add sandbox info like score and sandbox type o = pymisp.MISPObject(name="sandbox-report") sandbox_type = "saas" if tau_clients.is_task_hosted( analysis_link) else "on-premise" o.add_attribute("score", result["score"]) o.add_attribute("sandbox-type", sandbox_type) o.add_attribute("{}-sandbox".format(sandbox_type), "vmware-nsx-defender") o.add_attribute("permalink", analysis_link) misp_event.add_object(o) # Add behaviors # Check if its not empty first, as at least one attribute has to be set for sb-signature object if result.get("malicious_activity", []): o = pymisp.MISPObject(name="sb-signature") o.add_attribute("software", "VMware NSX Defender") for activity in result.get("malicious_activity", []): a = pymisp.MISPAttribute() a.from_dict(type="text", value=activity) o.add_attribute("signature", **a) misp_event.add_object(o) # Add mitre techniques for techniques in result.get("activity_to_mitre_techniques", {}).values(): for technique in techniques: for misp_technique_id, misp_technique_name in self.techniques_galaxy.items( ): if technique["id"].casefold( ) in misp_technique_id.casefold(): # If report details a sub-technique, trust the match # Otherwise trust it only if the MISP technique is not a sub-technique if "." in technique[ "id"] or "." not in misp_technique_id: misp_event.add_tag(misp_technique_name) break return misp_event