From f944db91c77d70d7f2de30b3ce06ce1a529ec8fd Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Fri, 2 Nov 2018 10:25:48 +0100 Subject: [PATCH 1/7] Added support for enabling/disabling certificate validation Added support for proxy configuration --- analyzers/IBMXForce/IBMXForce_Lookup.json | 9 +++++++- analyzers/IBMXForce/ibmxforce_lookup.py | 27 ++++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/analyzers/IBMXForce/IBMXForce_Lookup.json b/analyzers/IBMXForce/IBMXForce_Lookup.json index e9d26600c..dc1bc9f66 100644 --- a/analyzers/IBMXForce/IBMXForce_Lookup.json +++ b/analyzers/IBMXForce/IBMXForce_Lookup.json @@ -37,6 +37,13 @@ "required": true, "multi": false, "type": "string" + }, + { + "name": "verify", + "description": "Enable/Disable certificate verification", + "required": false, + "multi": false, + "type": "string" } ] -} +} \ No newline at end of file diff --git a/analyzers/IBMXForce/ibmxforce_lookup.py b/analyzers/IBMXForce/ibmxforce_lookup.py index c283464e1..52525822e 100755 --- a/analyzers/IBMXForce/ibmxforce_lookup.py +++ b/analyzers/IBMXForce/ibmxforce_lookup.py @@ -2,6 +2,7 @@ # encoding: utf-8 import requests from datetime import datetime +from urllib3.exceptions import InsecureRequestWarning from cortexutils.analyzer import Analyzer @@ -15,6 +16,16 @@ def __init__(self): self.url = self.get_param('config.url', None, 'Missing API url') self.key = self.get_param('config.key', None, 'Missing API key') self.pwd = self.get_param('config.pwd', None, 'Missing API password') + self.verify = self.str2bool(self.get_param('config.verify', True)) + if not self.verify: + requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) + self.proxies = self.get_param('config.proxy', None) + + def str2bool(self, v): + if isinstance(v, str) or isinstance(v, int) or isinstance(v, unicode) : + return v.lower() in ("yes", "true", "t", "1") + if isinstance(v, bool): + return v def parse_data(self, date): try: @@ -111,10 +122,10 @@ def ip_query(self, data): _session = requests.Session() _session.auth = (self.key, self.pwd) - _query_ip = _session.get('%s/ipr/%s' % (self.url, data)) + _query_ip = _session.get('%s/ipr/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) _query_malware = _session.get( - '%s/ipr/malware/%s' % (self.url, data)) - _query_info = _session.get('%s/resolve/%s' % (self.url, data)) + '%s/ipr/malware/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) + _query_info = _session.get('%s/resolve/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) ip_data = _query_ip.json() if _query_ip.status_code == 200 else {} malware_data = _query_malware.json() if _query_malware.status_code == 200 else {} @@ -136,10 +147,10 @@ def domain_query(self, data): _session = requests.Session() _session.auth = (self.key, self.pwd) - _query_url = _session.get('%s/url/%s' % (self.url, data)) + _query_url = _session.get('%s/url/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) _query_malware = _session.get( - '%s/url/malware/%s' % (self.url, data)) - _query_info = _session.get('%s/resolve/%s' % (self.url, data)) + '%s/url/malware/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) + _query_info = _session.get('%s/resolve/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) url_data = _query_url.json() if _query_url.status_code == 200 else {} malware_data = _query_malware.json() if _query_malware.status_code == 200 else {} @@ -162,7 +173,7 @@ def malware_query(self, data): _session.auth = (self.key, self.pwd) _query_malware = _session.get( - '%s/malware/%s' % (self.url, data)) + '%s/malware/%s' % (self.url, data), proxies=self.proxies, verify=self.verify) if _query_malware.status_code == 200: return self.cleanup(malware_data=_query_malware.json()) @@ -215,4 +226,4 @@ def run(self): if __name__ == '__main__': - IBMXForceAnalyzer().run() + IBMXForceAnalyzer().run() \ No newline at end of file From 9e48bf372ffd07757eb88fa4cdcc6210e7bee32e Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Wed, 2 Jan 2019 17:40:19 +0100 Subject: [PATCH 2/7] Adjusted emlparser to enhance the "Auto Extract" feature of The Hive --- analyzers/EmlParser/parse.py | 163 ++++++++++++++++++++++++++- analyzers/EmlParser/requirements.txt | 1 + 2 files changed, 163 insertions(+), 1 deletion(-) mode change 100755 => 100644 analyzers/EmlParser/parse.py diff --git a/analyzers/EmlParser/parse.py b/analyzers/EmlParser/parse.py old mode 100755 new mode 100644 index 864591e84..d70698270 --- a/analyzers/EmlParser/parse.py +++ b/analyzers/EmlParser/parse.py @@ -8,6 +8,155 @@ import hashlib from pprint import pprint +#Observables imports +from cortexutils.extractor import Extractor +from builtins import str as unicode +import re + +class CustomExtractor(Extractor): + def __init__(self, ignore=None): + #Extractor.__init__(self) + self.ignore = ignore + self.regex = self.__init_regex() + + @staticmethod + def __init_regex(): + + logging.info("Preparing regex statements") + + """ + Returns compiled regex list. + + :return: List of {type, regex} dicts + :rtype: list + """ + + #### Generic regexes + + # IPv4 + regex = [{ + 'types': ['ip'], + 'regex': re.compile(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', re.MULTILINE) + }] + + # URL + regex.append({ + 'types': ['url','fqdn','domain','uri_path'], + 'regex': re.compile(r'((?:http|https):\/\/((?:(?:.*?)\.)?(.*?(?:\.\w+)+))\/?([a-zA-Z0-9\/\-\_\.\~\=\?]+\??)?)', re.MULTILINE) + }) + + # mail + regex.append({ + 'types': ['mail','domain'], + 'regex': re.compile(r'((?:[a-zA-Z0-9\/\-\_\.]+)@{1}([a-zA-Z0-9\-\_]+\.[a-zA-Z0-9\-\_\.]+)+)', re.MULTILINE) + }) + + ### Mail Specific regexes + + return regex + + def __findmatch(self, value): + """Checks if the given value is contains regexes + + :param value: The value to check + :type value: str or number + :return: Data type of value, if known, else empty string + :rtype: str + """ + found_observables = [] + if isinstance(value, (str, unicode)): + for r in self.regex: + #content = value + #logging.info("Checking regex: {}".format(r.get('regex'))) + #logging.info("Checking value: {}".format(value)) + matches = re.findall(r.get('regex'), value) + #logging.info("Matches: {}".format(str(matches))) + if len(matches) > 0: + + for found_observable in matches: + if isinstance(found_observable, tuple): + i = 0 + for groups in found_observable: + found_observables.append({ + 'type': r.get('types')[i], + 'value': found_observable[i] + }) + i += 1 + else: + found_observables.append({ + 'type': r.get('types')[0], + 'value': found_observable + }) + if len(found_observables) > 0: + return found_observables + else: + return '' + + # if self.ignore: + # if isinstance(value, str) and self.ignore in value: + # return '' + # if self.ignore == value: + # return '' + # return '' + + def check_iterable(self, iterable): + """ + Checks values of a list or a dict on ioc's. Returns a list of dict {type, value}. Raises TypeError, if iterable + is not an expected type. + + :param iterable: List or dict of values + :type iterable: list dict str + :return: List of ioc's matching the regex + :rtype: list + """ + results = [] + # Only the string left + logging.info("Checking content of variable") + if isinstance(iterable, (str, unicode)): + #logging.info("Content is a string") + dt = self.__findmatch(iterable) + logging.info("dt = {}".format(str(dt))) + if len(dt) > 0: + results.extend(dt) + elif isinstance(iterable, list): + #logging.info("Content is a list") + for item in iterable: + if isinstance(item, list) or isinstance(item, dict): + results.extend(self.check_iterable(item)) + else: + dt = self.__findmatch(item) + #logging.info("dt = {}".format(str(dt))) + if len(dt) > 0: + results.extend(dt) + elif isinstance(iterable, dict): + #logging.info("Content is a dict") + for _, item in iterable.items(): + if isinstance(item, list) or isinstance(item, dict): + results.extend(self.check_iterable(item)) + else: + dt = self.__findmatch(item) + logging.info("dt = {}".format(str(dt))) + if len(dt) > 0: + results.extend(dt) + else: + raise TypeError('Not supported type.') + + logging.info('results: {}'.format(str(results))) + results_dedup = self.deduplicate(results) + return results_dedup + + def deduplicate(self, list_of_objects): + dedup_list = [] + for object in list_of_objects: + present = False + for new_object in dedup_list: + if object['type'] == new_object['type'] and object['value'] == new_object['value']: + present = True + if not present: + dedup_list.append(object) + return dedup_list + + class EmlParserAnalyzer(Analyzer): def __init__(self): @@ -35,12 +184,24 @@ def summary(self, raw): namespace = "EmlParser" predicate = "Attachments" value = "\"0\"" - + if "attachments" in raw: value = len(raw["attachments"]) taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) return {"taxonomies": taxonomies} + + def artifacts(self, raw): + # Use the regex extractor, if auto_extract setting is not False + logging.info("Looking for artifacts") + if self.auto_extract: + logging.info("Looking for artifacts2") + extractor = CustomExtractor(ignore=self.get_data()) + return extractor.check_iterable(raw) + + # Return empty list + return [] + def parseEml(filepath): diff --git a/analyzers/EmlParser/requirements.txt b/analyzers/EmlParser/requirements.txt index bd0fe8249..f1b90baeb 100644 --- a/analyzers/EmlParser/requirements.txt +++ b/analyzers/EmlParser/requirements.txt @@ -1,2 +1,3 @@ cortexutils;python_version>='3.5' eml_parser +python-magic From 0973b6cfbac4ee0386dd6274af12f0db4d097df3 Mon Sep 17 00:00:00 2001 From: Jeffrey E Date: Thu, 3 Jan 2019 13:05:40 +0100 Subject: [PATCH 3/7] Enhanced regexes --- analyzers/EmlParser/parse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/analyzers/EmlParser/parse.py b/analyzers/EmlParser/parse.py index 87f9d7b57..985b774fb 100644 --- a/analyzers/EmlParser/parse.py +++ b/analyzers/EmlParser/parse.py @@ -37,7 +37,7 @@ def __init_regex(): # IPv4 regex = [{ 'types': ['ip'], - 'regex': re.compile(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', re.MULTILINE) + 'regex': re.compile(r'(?:^|\D)((?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9]))(?:\D|$)', re.MULTILINE) }] # URL @@ -49,7 +49,7 @@ def __init_regex(): # mail regex.append({ 'types': ['mail','domain'], - 'regex': re.compile(r'((?:[a-zA-Z0-9\/\-\_\.]+)@{1}([a-zA-Z0-9\-\_]+\.[a-zA-Z0-9\-\_\.]+)+)', re.MULTILINE) + 'regex': re.compile(r'((?:[a-zA-Z0-9\/\-\_\.\+]+)@{1}([a-zA-Z0-9\-\_]+\.[a-zA-Z0-9\-\_\.]+)+)', re.MULTILINE) }) ### Mail Specific regexes From f2e1f761ff405091a43b05172128ec7e750b0337 Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Thu, 14 Feb 2019 17:40:24 +0100 Subject: [PATCH 4/7] Added task based mail respondings --- responders/Mailer/Mailer.json | 4 ++-- responders/Mailer/mailer.py | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/responders/Mailer/Mailer.json b/responders/Mailer/Mailer.json index 459adff51..0175a561f 100644 --- a/responders/Mailer/Mailer.json +++ b/responders/Mailer/Mailer.json @@ -4,8 +4,8 @@ "author": "CERT-BDF", "url": "https://github.com/TheHive-Project/Cortex-Analyzers", "license": "AGPL-V3", - "description": "Send an email with information from a TheHive case or alert", - "dataTypeList": ["thehive:case", "thehive:alert"], + "description": "Send an email with information from a TheHive case, task or alert", + "dataTypeList": ["thehive:case", "thehive:alert", "thehive:case_task"], "command": "Mailer/mailer.py", "baseConfig": "Mailer", "configurationItems": [ diff --git a/responders/Mailer/mailer.py b/responders/Mailer/mailer.py index 3c1627111..90b2f1014 100755 --- a/responders/Mailer/mailer.py +++ b/responders/Mailer/mailer.py @@ -30,7 +30,17 @@ def run(self): if mail_tags: mail_to = mail_tags.pop() else: - self.error('recipient address not found in observables') + self.error('recipient address not found in tags') + elif self.data_type == 'thehive:case_task': + # Search recipient address in tags + descr_array = description.splitlines() + if 'mailto:' in descr_array[0]: + mail_to = descr_array[0].replace("mailto\:", "") + else: + self.error('recipient address not found in description') + #Set rest of description as body + del descr_array[0] + description = '\n'.join(descr_array) elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param('data.artifacts', None, 'recipient address not found in observables') @@ -58,4 +68,4 @@ def operations(self, raw): if __name__ == '__main__': - Mailer().run() + Mailer().run() \ No newline at end of file From 5fcf7e9fb4627144a7e30bb1949fff12e8e5c8c2 Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Mon, 18 Feb 2019 13:25:48 +0100 Subject: [PATCH 5/7] Revert "Added task based mail respondings" Added branch for it This reverts commit f2e1f761ff405091a43b05172128ec7e750b0337. --- responders/Mailer/Mailer.json | 4 ++-- responders/Mailer/mailer.py | 14 ++------------ 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/responders/Mailer/Mailer.json b/responders/Mailer/Mailer.json index 0175a561f..459adff51 100644 --- a/responders/Mailer/Mailer.json +++ b/responders/Mailer/Mailer.json @@ -4,8 +4,8 @@ "author": "CERT-BDF", "url": "https://github.com/TheHive-Project/Cortex-Analyzers", "license": "AGPL-V3", - "description": "Send an email with information from a TheHive case, task or alert", - "dataTypeList": ["thehive:case", "thehive:alert", "thehive:case_task"], + "description": "Send an email with information from a TheHive case or alert", + "dataTypeList": ["thehive:case", "thehive:alert"], "command": "Mailer/mailer.py", "baseConfig": "Mailer", "configurationItems": [ diff --git a/responders/Mailer/mailer.py b/responders/Mailer/mailer.py index 90b2f1014..3c1627111 100755 --- a/responders/Mailer/mailer.py +++ b/responders/Mailer/mailer.py @@ -30,17 +30,7 @@ def run(self): if mail_tags: mail_to = mail_tags.pop() else: - self.error('recipient address not found in tags') - elif self.data_type == 'thehive:case_task': - # Search recipient address in tags - descr_array = description.splitlines() - if 'mailto:' in descr_array[0]: - mail_to = descr_array[0].replace("mailto\:", "") - else: - self.error('recipient address not found in description') - #Set rest of description as body - del descr_array[0] - description = '\n'.join(descr_array) + self.error('recipient address not found in observables') elif self.data_type == 'thehive:alert': # Search recipient address in artifacts artifacts = self.get_param('data.artifacts', None, 'recipient address not found in observables') @@ -68,4 +58,4 @@ def operations(self, raw): if __name__ == '__main__': - Mailer().run() \ No newline at end of file + Mailer().run() From fa18080504b3de67ff0ea6b21bf68fd8cce5c59f Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Tue, 19 Feb 2019 13:41:32 +0100 Subject: [PATCH 6/7] Adjusted code so that only analyzer specific regex are to be added --- analyzers/EmlParser/parse.py | 151 +++-------------------------------- 1 file changed, 9 insertions(+), 142 deletions(-) diff --git a/analyzers/EmlParser/parse.py b/analyzers/EmlParser/parse.py index 985b774fb..645cce427 100644 --- a/analyzers/EmlParser/parse.py +++ b/analyzers/EmlParser/parse.py @@ -14,149 +14,29 @@ from builtins import str as unicode import re -class CustomExtractor(Extractor): - def __init__(self, ignore=None): - #Extractor.__init__(self) - self.ignore = ignore - self.regex = self.__init_regex() +class EnhancedExtractor(Extractor): @staticmethod - def __init_regex(): + def __init_analyzer_regex(): - logging.info("Preparing regex statements") + logging.info("Preparing mail specific regex statements") """ - Returns compiled regex list. + Returns compiled regex list specifically for mail. :return: List of {type, regex} dicts :rtype: list """ - - #### Generic regexes - # IPv4 - regex = [{ - 'types': ['ip'], - 'regex': re.compile(r'(?:^|\D)((?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9])\.(?:25[0-5]|2[0-4]\d|[1]\d\d|[1-9]\d|[0-9]))(?:\D|$)', re.MULTILINE) - }] - - # URL - regex.append({ - 'types': ['url','fqdn','domain','uri_path'], - 'regex': re.compile(r'((?:http|https):\/\/((?:(?:.*?)\.)?(.*?(?:\.\w+)+))\/?([a-zA-Z0-9\/\-\_\.\~\=\?]+\??)?)', re.MULTILINE) - }) + ### Mail Specific regexes - # mail + # Received from by header regex.append({ - 'types': ['mail','domain'], - 'regex': re.compile(r'((?:[a-zA-Z0-9\/\-\_\.\+]+)@{1}([a-zA-Z0-9\-\_]+\.[a-zA-Z0-9\-\_\.]+)+)', re.MULTILINE) + 'types': ['fqdn'], + 'regex': re.compile(r'Received: from \[?([A-Za-z0-9\.\-]*)\]?', re.MULTILINE) }) - - ### Mail Specific regexes return regex - - def __findmatch(self, value): - """Checks if the given value is contains regexes - - :param value: The value to check - :type value: str or number - :return: Data type of value, if known, else empty string - :rtype: str - """ - found_observables = [] - if isinstance(value, (str, unicode)): - for r in self.regex: - #content = value - #logging.info("Checking regex: {}".format(r.get('regex'))) - #logging.info("Checking value: {}".format(value)) - matches = re.findall(r.get('regex'), value) - #logging.info("Matches: {}".format(str(matches))) - if len(matches) > 0: - - for found_observable in matches: - if isinstance(found_observable, tuple): - i = 0 - for groups in found_observable: - found_observables.append({ - 'type': r.get('types')[i], - 'value': found_observable[i] - }) - i += 1 - else: - found_observables.append({ - 'type': r.get('types')[0], - 'value': found_observable - }) - if len(found_observables) > 0: - return found_observables - else: - return '' - - # if self.ignore: - # if isinstance(value, str) and self.ignore in value: - # return '' - # if self.ignore == value: - # return '' - # return '' - - def check_iterable(self, iterable): - """ - Checks values of a list or a dict on ioc's. Returns a list of dict {type, value}. Raises TypeError, if iterable - is not an expected type. - - :param iterable: List or dict of values - :type iterable: list dict str - :return: List of ioc's matching the regex - :rtype: list - """ - results = [] - # Only the string left - logging.info("Checking content of variable") - if isinstance(iterable, (str, unicode)): - #logging.info("Content is a string") - dt = self.__findmatch(iterable) - logging.info("dt = {}".format(str(dt))) - if len(dt) > 0: - results.extend(dt) - elif isinstance(iterable, list): - #logging.info("Content is a list") - for item in iterable: - if isinstance(item, list) or isinstance(item, dict): - results.extend(self.check_iterable(item)) - else: - dt = self.__findmatch(item) - #logging.info("dt = {}".format(str(dt))) - if len(dt) > 0: - results.extend(dt) - elif isinstance(iterable, dict): - #logging.info("Content is a dict") - for _, item in iterable.items(): - if isinstance(item, list) or isinstance(item, dict): - results.extend(self.check_iterable(item)) - else: - dt = self.__findmatch(item) - logging.info("dt = {}".format(str(dt))) - if len(dt) > 0: - results.extend(dt) - else: - raise TypeError('Not supported type.') - - logging.info('results: {}'.format(str(results))) - results_dedup = self.deduplicate(results) - return results_dedup - - def deduplicate(self, list_of_objects): - dedup_list = [] - for object in list_of_objects: - present = False - for new_object in dedup_list: - if object['type'] == new_object['type'] and object['value'] == new_object['value']: - present = True - if not present: - dedup_list.append(object) - return dedup_list - class EmlParserAnalyzer(Analyzer): @@ -190,20 +70,7 @@ def summary(self, raw): value = len(raw["attachments"]) taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) - return {"taxonomies": taxonomies} - - def artifacts(self, raw): - # Use the regex extractor, if auto_extract setting is not False - logging.info("Looking for artifacts") - if self.auto_extract: - logging.info("Looking for artifacts2") - extractor = CustomExtractor(ignore=self.get_data()) - return extractor.check_iterable(raw) - - # Return empty list - return [] - - + return {"taxonomies": taxonomies} def parseEml(filepath): From 098d76f6501c795dd48e193dc4456b7ba1b91337 Mon Sep 17 00:00:00 2001 From: Jeffrey Everling Date: Tue, 19 Feb 2019 18:09:21 +0100 Subject: [PATCH 7/7] Fixed some issues --- analyzers/EmlParser/parse.py | 43 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/analyzers/EmlParser/parse.py b/analyzers/EmlParser/parse.py index 645cce427..42d279a35 100644 --- a/analyzers/EmlParser/parse.py +++ b/analyzers/EmlParser/parse.py @@ -9,34 +9,34 @@ import base64 from pprint import pprint -#Observables imports +#Required for analyzer specific observable auto extraction from cortexutils.extractor import Extractor -from builtins import str as unicode import re class EnhancedExtractor(Extractor): - + + def __init__(self, ignore=None): + Extractor.__init__(self) + self.asregex = self.__init_analyzer_regex() + @staticmethod def __init_analyzer_regex(): - - logging.info("Preparing mail specific regex statements") - + """ Returns compiled regex list specifically for mail. :return: List of {type, regex} dicts :rtype: list """ - - ### Mail Specific regexes - # Received from by header - regex.append({ - 'types': ['fqdn'], - 'regex': re.compile(r'Received: from \[?([A-Za-z0-9\.\-]*)\]?', re.MULTILINE) - }) + ### Mail Specific regexes + # Received from + as_regex = [{ + 'types': ['fqdn','fqdn'], + 'regex': re.compile(r'from\s\[?([A-Za-z0-9\.\-]*)\]?.*?\sby\s\[?([A-Za-z0-9\.\-]*)\]?', re.MULTILINE) + }] - return regex + return as_regex class EmlParserAnalyzer(Analyzer): @@ -65,12 +65,21 @@ def summary(self, raw): namespace = "EmlParser" predicate = "Attachments" value = "\"0\"" - + if "attachments" in raw: value = len(raw["attachments"]) taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) - return {"taxonomies": taxonomies} + return {"taxonomies": taxonomies} + + def artifacts(self, raw): + # Use the regex extractor, if auto_extract setting is not False + if self.auto_extract: + extractor = EnhancedExtractor(ignore=self.get_data()) + return extractor.check_iterable(raw) + + # Return empty list + return [] def parseEml(filepath): @@ -147,4 +156,4 @@ def parseEml(filepath): return result if __name__ == '__main__': - EmlParserAnalyzer().run() + EmlParserAnalyzer().run() \ No newline at end of file