├── README.md └── misp_stix.py /README.md: -------------------------------------------------------------------------------- 1 | # MISP-STIX-ESM 2 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 3 | 4 | This Script will download MISP events in STIX format. McAfee ESM will be configured to pull STIX files from the folder location via SCP and run automated triage processes. 5 | 6 | screen shot 2018-06-26 at 16 31 48 7 | 8 | ## Component Description 9 | 10 | **McAfee Enterprise Security Manager (ESM)** is a security information and event management (SIEM) solution that delivers actionable intelligence and integrations to prioritize, investigate, and respond to threats. 11 | https://www.mcafee.com/enterprise/en-us/products/enterprise-security-manager.html 12 | 13 | **MISP** threat sharing platform is free and open source software helping information sharing of threat and cyber security indicators. 14 | https://github.com/MISP/MISP 15 | 16 | ## Prerequisites 17 | 18 | Download the [Latest Release](https://github.com/mohlcyber/MISP-STIX-ESM/releases) 19 | * Extract the release .zip file 20 | 21 | MISP platform installation ([Link](https://github.com/MISP/MISP)) (tested with MISP 2.4.121) 22 | 23 | Requests ([Link](http://docs.python-requests.org/en/master/user/install/#install)) 24 | 25 | PyMISP library installation ([Link](https://github.com/MISP/PyMISP)) 26 | ```sh 27 | git clone https://github.com/MISP/PyMISP.git 28 | cd PyMISP/ 29 | python setup.py install 30 | ``` 31 | ## Configuration 32 | MISP receives intelligence feeds from multiple sources. The provided script will export tagged events as STIX files and McAfee ESM will pull these STIX files for automated investigations. 33 | 34 | ### misp_stix.py 35 | The misp_stix.py script will export tagged events as STIX files to a given location. 36 | 37 | Enter the MISP IP/URL, API key, MISP Tag to look for and the location where the STIX files should be stored (line 12 - 15). 38 | 39 | Screenshot 2019-11-07 at 11 48 33 40 | 41 | ### ESM Configuration 42 | 43 | Log into the McAfee ESM platform and open ESM properties. 44 | Go to the Cyber Threat Feeds and add a new feed. In the source enter the IP, username, password and path to the folder that contains the STIX files that got previous downloaded through the misp_stix.py script. 45 | 46 | screen shot 2018-06-27 at 18 30 04 47 | 48 | Define the frequency, watchlist and backtrace options to automate triage steps. 49 | 50 | McAfee ESM will pull new STIX file and check if any events have been seen in the past related to the artifacts. 51 | -------------------------------------------------------------------------------- /misp_stix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Written by mohlcyber v.0.3 12/02/2020 3 | 4 | import sys 5 | import requests 6 | import time 7 | 8 | from pymisp import ExpandedPyMISP 9 | 10 | requests.packages.urllib3.disable_warnings() 11 | 12 | misp_url = 'https://1.1.1.1/' 13 | misp_verify = False 14 | misp_key = 'API Key' 15 | misp_tag = 'McAfee: Export to ESM' 16 | misp_path = 'stix/' 17 | 18 | 19 | class MISP(): 20 | def __init__(self): 21 | self.misp = ExpandedPyMISP(misp_url, misp_key, False) 22 | self.headers = { 23 | 'Authorization': misp_key, 24 | 'Accept': 'application/xml', 25 | 'User-Agent': 'PyMISP' 26 | } 27 | 28 | def get_events(self, **kwargs): 29 | tags = kwargs.pop('tags', None) 30 | format = kwargs.pop('format', None) 31 | eid = kwargs.pop('eid', None) 32 | res = self.misp.search(eventid=eid, tags=tags, return_format=format) 33 | return res 34 | 35 | def get_stix(self, eventid, format): 36 | payload = { 37 | "returnFormat": format, 38 | "eventid": eventid 39 | } 40 | stix = requests.post(misp_url + 'events/restSearch', headers=self.headers, data=payload, verify=misp_verify) 41 | return stix.content 42 | 43 | def main(self): 44 | results = self.get_events(tags=misp_tag, format='json') 45 | try: 46 | if results: 47 | for result in results: 48 | eventid = result['Event']['id'] 49 | euuid = result['Event']['uuid'] 50 | 51 | stix = self.get_stix(eventid, 'stix') 52 | with open(misp_path + 'misp_stix_{0}.xml'.format(str(eventid)), 'w') as esm_stix: 53 | esm_stix.write(stix.decode()) 54 | esm_stix.close() 55 | print('SUCCESS: Successful exported the STIX file for event {0}.'.format(str(eventid))) 56 | 57 | objects = result['Event']['Object'] 58 | for fields in objects: 59 | for attributes in fields['Attribute']: 60 | attuuid = attributes['uuid'] 61 | 62 | if 'Tag' in attributes: 63 | for tags in attributes['Tag']: 64 | atttag = tags['name'] 65 | if atttag == misp_tag: 66 | self.misp.untag(attuuid, misp_tag) 67 | 68 | attributes = result['Event']['Attribute'] 69 | for fields in attributes: 70 | attuuid = fields['uuid'] 71 | 72 | if 'Tag' in fields: 73 | for tags in fields['Tag']: 74 | atttag = tags['name'] 75 | if atttag == misp_tag: 76 | self.misp.untag(attuuid, misp_tag) 77 | 78 | self.misp.untag(euuid, misp_tag) 79 | 80 | else: 81 | print('STATUS: Could not find Events that are tagged with {0}.'.format(str(misp_tag))) 82 | except Exception as e: 83 | exc_type, exc_obj, exc_tb = sys.exc_info() 84 | print("ERROR: Error in {location}.{funct_name}() - line {line_no} : {error}" 85 | .format(location=__name__, funct_name=sys._getframe().f_code.co_name, line_no=exc_tb.tb_lineno, 86 | error=str(e))) 87 | 88 | 89 | if __name__ == '__main__': 90 | 91 | while True: 92 | misp = MISP() 93 | misp.main() 94 | time.sleep(60) --------------------------------------------------------------------------------