From dc0660acd0df74e874be4cf81c9b5d4381fb594f Mon Sep 17 00:00:00 2001 From: Calvin Krzywiec Date: Mon, 22 Nov 2021 15:46:46 -0500 Subject: [PATCH 1/2] feature: add qintel qsentry expansion module --- misp_modules/lib/__init__.py | 2 +- misp_modules/lib/qintel_helper.py | 263 ++++++++++++++++++ misp_modules/modules/expansion/__init__.py | 3 +- .../modules/expansion/qintel_qsentry.py | 221 +++++++++++++++ 4 files changed, 487 insertions(+), 2 deletions(-) create mode 100644 misp_modules/lib/qintel_helper.py create mode 100644 misp_modules/modules/expansion/qintel_qsentry.py diff --git a/misp_modules/lib/__init__.py b/misp_modules/lib/__init__.py index d92e989..2939e75 100644 --- a/misp_modules/lib/__init__.py +++ b/misp_modules/lib/__init__.py @@ -1,3 +1,3 @@ from .vt_graph_parser import * # noqa -all = ['joe_parser', 'lastline_api', 'cof2misp'] +all = ['joe_parser', 'lastline_api', 'cof2misp', 'qintel_helper'] diff --git a/misp_modules/lib/qintel_helper.py b/misp_modules/lib/qintel_helper.py new file mode 100644 index 0000000..47106f7 --- /dev/null +++ b/misp_modules/lib/qintel_helper.py @@ -0,0 +1,263 @@ +# Copyright (c) 2009-2021 Qintel, LLC +# Licensed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0.txt) + +from urllib.request import Request, urlopen +from urllib.parse import urlencode +from urllib.error import HTTPError +from time import sleep +from json import loads +import os +from copy import deepcopy +from datetime import datetime, timedelta +from gzip import GzipFile + +VERSION = '1.0.1' +USER_AGENT = 'integrations-helper' +MAX_RETRY_ATTEMPTS = 5 + +DEFAULT_HEADERS = { + 'User-Agent': f'{USER_AGENT}/{VERSION}' +} + +REMOTE_MAP = { + 'pmi': 'https://api.pmi.qintel.com', + 'qwatch': 'https://api.qwatch.qintel.com', + 'qauth': 'https://api.qauth.qintel.com', + 'qsentry_feed': 'https://qsentry.qintel.com', + 'qsentry': 'https://api.qsentry.qintel.com' +} + +ENDPOINT_MAP = { + 'pmi': { + 'ping': '/users/me', + 'cve': 'cves' + }, + 'qsentry_feed': { + 'anon': '/files/anonymization', + 'mal_hosting': '/files/malicious_hosting' + }, + 'qsentry': {}, + 'qwatch': { + 'ping': '/users/me', + 'exposures': 'exposures' + }, + 'qauth': {} +} + + +def _get_request_wait_time(attempts): + """ Use Fibonacci numbers for determining the time to wait when rate limits + have been encountered. + """ + + n = attempts + 3 + a, b = 1, 0 + for _ in range(n): + a, b = a + b, a + + return a + + +def _search(**kwargs): + remote = kwargs.get('remote') + max_retries = int(kwargs.get('max_retries', MAX_RETRY_ATTEMPTS)) + params = kwargs.get('params', {}) + headers = _set_headers(**kwargs) + + logger = kwargs.get('logger') + + params = urlencode(params) + url = remote + "?" + params + req = Request(url, headers=headers) + + request_attempts = 1 + while request_attempts < max_retries: + try: + return urlopen(req) + + except HTTPError as e: + response = e + + except Exception as e: + raise Exception('API connection error') from e + + if response.code not in [429, 504]: + raise Exception(f'API connection error: {response}') + + if request_attempts < max_retries: + wait_time = _get_request_wait_time(request_attempts) + + if response.code == 429: + msg = 'rate limit reached on attempt {request_attempts}, ' \ + 'waiting {wait_time} seconds' + + if logger: + logger(msg) + + else: + msg = f'connection timed out, retrying in {wait_time} seconds' + if logger: + logger(msg) + + sleep(wait_time) + + else: + raise Exception('Max API retries exceeded') + + request_attempts += 1 + + +def _set_headers(**kwargs): + headers = deepcopy(DEFAULT_HEADERS) + + if kwargs.get('user_agent'): + headers['User-Agent'] = \ + f"{kwargs['user_agent']}/{USER_AGENT}/{VERSION}" + + # TODO: deprecate + if kwargs.get('client_id') or kwargs.get('client_secret'): + try: + headers['Cf-Access-Client-Id'] = kwargs['client_id'] + headers['Cf-Access-Client-Secret'] = kwargs['client_secret'] + except KeyError: + raise Exception('missing client_id or client_secret') + + if kwargs.get('token'): + headers['x-api-key'] = kwargs['token'] + + return headers + + +def _set_remote(product, query_type, **kwargs): + remote = kwargs.get('remote') + endpoint = kwargs.get('endpoint', ENDPOINT_MAP[product].get(query_type)) + + if not remote: + remote = REMOTE_MAP[product] + + if not endpoint: + raise Exception('invalid search type') + + remote = remote.rstrip('/') + endpoint = endpoint.lstrip('/') + + return f'{remote}/{endpoint}' + + +def _process_qsentry(resp): + if resp.getheader('Content-Encoding', '') == 'gzip': + with GzipFile(fileobj=resp) as file: + for line in file.readlines(): + yield loads(line) + + +def search_pmi(search_term, query_type, **kwargs): + """ + Search PMI + + :param str search_term: Search term + :param str query_type: Query type [cve|ping] + :param dict kwargs: extra client args [remote|token|params] + :return: API JSON response object + :rtype: dict + """ + + kwargs['remote'] = _set_remote('pmi', query_type, **kwargs) + kwargs['token'] = kwargs.get('token', os.getenv('PMI_TOKEN')) + + params = kwargs.get('params', {}) + params.update({'identifier': search_term}) + kwargs['params'] = params + + return loads(_search(**kwargs).read()) + + +def search_qwatch(search_term, search_type, query_type, **kwargs): + """ + Search QWatch for exposed credentials + + :param str search_term: Search term + :param str search_type: Search term type [domain|email] + :param str query_type: Query type [exposures] + :param dict kwargs: extra client args [remote|token|params] + :return: API JSON response object + :rtype: dict + """ + + kwargs['remote'] = _set_remote('qwatch', query_type, **kwargs) + kwargs['token'] = kwargs.get('token', os.getenv('QWATCH_TOKEN')) + + params = kwargs.get('params', {}) + if search_type: + params.update({search_type: search_term}) + kwargs['params'] = params + + return loads(_search(**kwargs).read()) + + +def search_qauth(search_term, **kwargs): + """ + Search QAuth + + :param str search_term: Search term + :param dict kwargs: extra client args [remote|token|params] + :return: API JSON response object + :rtype: dict + """ + + if not kwargs.get('endpoint'): + kwargs['endpoint'] = '/' + + kwargs['remote'] = _set_remote('qauth', None, **kwargs) + kwargs['token'] = kwargs.get('token', os.getenv('QAUTH_TOKEN')) + + params = kwargs.get('params', {}) + params.update({'q': search_term}) + kwargs['params'] = params + + return loads(_search(**kwargs).read()) + + +def search_qsentry(search_term, **kwargs): + """ + Search QSentry + + :param str search_term: Search term + :param dict kwargs: extra client args [remote|token|params] + :return: API JSON response object + :rtype: dict + """ + + if not kwargs.get('endpoint'): + kwargs['endpoint'] = '/' + + kwargs['remote'] = _set_remote('qsentry', None, **kwargs) + kwargs['token'] = kwargs.get('token', os.getenv('QSENTRY_TOKEN')) + + params = kwargs.get('params', {}) + params.update({'q': search_term}) + kwargs['params'] = params + + return loads(_search(**kwargs).read()) + + +def qsentry_feed(query_type='anon', feed_date=datetime.today(), **kwargs): + """ + Fetch the most recent QSentry Feed + + :param str query_type: Feed type [anon|mal_hosting] + :param dict kwargs: extra client args [remote|token|params] + :param datetime feed_date: feed date to fetch + :return: API JSON response object + :rtype: Iterator[dict] + """ + + remote = _set_remote('qsentry_feed', query_type, **kwargs) + kwargs['token'] = kwargs.get('token', os.getenv('QSENTRY_TOKEN')) + + feed_date = (feed_date - timedelta(days=1)).strftime('%Y%m%d') + kwargs['remote'] = f'{remote}/{feed_date}' + + resp = _search(**kwargs) + for r in _process_qsentry(resp): + yield r diff --git a/misp_modules/modules/expansion/__init__.py b/misp_modules/modules/expansion/__init__.py index a817c2a..1666ffe 100644 --- a/misp_modules/modules/expansion/__init__.py +++ b/misp_modules/modules/expansion/__init__.py @@ -17,7 +17,8 @@ __all__ = ['cuckoo_submit', 'vmray_submit', 'bgpranking', 'circl_passivedns', 'c 'virustotal_public', 'apiosintds', 'urlscan', 'securitytrails', 'apivoid', 'assemblyline_submit', 'assemblyline_query', 'ransomcoindb', 'malwarebazaar', 'lastline_query', 'lastline_submit', 'sophoslabs_intelix', 'cytomic_orion', 'censys_enrich', - 'trustar_enrich', 'recordedfuture', 'html_to_markdown', 'socialscan', 'passive-ssh'] + 'trustar_enrich', 'recordedfuture', 'html_to_markdown', 'socialscan', 'passive-ssh', + 'qintel_qsentry'] minimum_required_fields = ('type', 'uuid', 'value') diff --git a/misp_modules/modules/expansion/qintel_qsentry.py b/misp_modules/modules/expansion/qintel_qsentry.py new file mode 100644 index 0000000..6733b93 --- /dev/null +++ b/misp_modules/modules/expansion/qintel_qsentry.py @@ -0,0 +1,221 @@ +import logging +import json + +from pymisp import MISPAttribute, MISPEvent, MISPTag, MISPObject +from . import check_input_attribute, checking_error, standard_error_message + +from qintel_helper import search_qsentry + +logger = logging.getLogger('qintel_qsentry') +logger.setLevel(logging.DEBUG) + +moduleinfo = { + 'version': '1.0', + 'author': 'Qintel, LLC', + 'description': 'Query Qintel QSentry for ip intelligence', + 'module-type': ['hover', 'expansion'] +} + +moduleconfig = ['token', 'remote'] + +misperrors = {'error': 'Error'} + +mispattributes = { + 'input': ['ip-src', 'ip-dst'], + 'output': ['ip-src', 'ip-dst', 'AS', 'freetext'], + 'format': 'misp_standard' +} + +TAG_COLOR = { + 'benign': '#27ae60', + 'suspicious': '#e6a902', + 'malicious': '#c0392b' +} + +CLIENT_HEADERS = { + 'User-Agent': f"MISP/{moduleinfo['version']}", +} + + +def _return_error(message): + misperrors['error'] = message + return misperrors + + +def _make_tags(enriched_attr, result): + + for tag in result['tags']: + color = TAG_COLOR['suspicious'] + if tag == 'criminal': + color = TAG_COLOR['malicious'] + + t = MISPTag() + t.from_dict(**{ + 'name': f'qintel:tag="{tag}"', + 'colour': color + }) + enriched_attr.add_tag(**t) + + return enriched_attr + + +def _make_enriched_attr(event, result, orig_attr): + + enriched_object = MISPObject('Qintel Threat Enrichment') + enriched_object.add_reference(orig_attr.uuid, 'related-to') + + enriched_attr = MISPAttribute() + enriched_attr.from_dict(**{ + 'value': orig_attr.value, + 'type': orig_attr.type, + 'distribution': 0, + 'object_relation': 'enriched-attr', + 'to_ids': orig_attr.to_ids + }) + + enriched_attr = _make_tags(enriched_attr, result) + enriched_object.add_attribute(**enriched_attr) + + comment_attr = MISPAttribute() + comment_attr.from_dict(**{ + 'value': '\n'.join(result.get('descriptions', [])), + 'type': 'text', + 'object_relation': 'descriptions', + 'distribution': 0 + }) + enriched_object.add_attribute(**comment_attr) + + last_seen = MISPAttribute() + last_seen.from_dict(**{ + 'value': result.get('last_seen'), + 'type': 'datetime', + 'object_relation': 'last-seen', + 'distribution': 0 + }) + enriched_object.add_attribute(**last_seen) + + event.add_attribute(**orig_attr) + event.add_object(**enriched_object) + + return event + + +def _make_asn_attr(event, result, orig_attr): + + asn_object = MISPObject('asn') + asn_object.add_reference(orig_attr.uuid, 'related-to') + + asn_attr = MISPAttribute() + asn_attr.from_dict(**{ + 'type': 'AS', + 'value': result.get('asn'), + 'object_relation': 'asn', + 'distribution': 0 + }) + asn_object.add_attribute(**asn_attr) + + org_attr = MISPAttribute() + org_attr.from_dict(**{ + 'type': 'text', + 'value': result.get('asn_name', 'unknown').title(), + 'object_relation': 'description', + 'distribution': 0 + }) + asn_object.add_attribute(**org_attr) + + event.add_object(**asn_object) + + return event + + +def _format_hover(event, result): + + enriched_object = event.get_objects_by_name('Qintel Threat Enrichment')[0] + + tags = ', '.join(result.get('tags')) + enriched_object.add_attribute('Tags', type='text', value=tags) + + return event + + +def _format_result(attribute, result): + + event = MISPEvent() + + orig_attr = MISPAttribute() + orig_attr.from_dict(**attribute) + + event = _make_enriched_attr(event, result, orig_attr) + event = _make_asn_attr(event, result, orig_attr) + + return event + + +def _check_config(config): + if not config: + return False + + if not isinstance(config, dict): + return False + + if config.get('token', '') == '': + return False + + return True + + +def _check_request(request): + if not request.get('attribute'): + return f'{standard_error_message}, {checking_error}' + + check_reqs = ('type', 'value') + if not check_input_attribute(request['attribute'], + requirements=check_reqs): + return f'{standard_error_message}, {checking_error}' + + if request['attribute']['type'] not in mispattributes['input']: + return 'Unsupported attribute type' + + +def handler(q=False): + if not q: + return False + + request = json.loads(q) + config = request.get('config') + + if not _check_config(config): + return _return_error('Missing Qintel token') + + check_request_error = _check_request(request) + if check_request_error: + return _return_error(check_request_error) + + search_args = { + 'token': config['token'], + 'remote': config.get('remote') + } + + try: + result = search_qsentry(request['attribute']['value'], **search_args) + except Exception as e: + return _return_error(str(e)) + + event = _format_result(request['attribute'], result) + if not request.get('event_id'): + event = _format_hover(event, result) + + event = json.loads(event.to_json()) + + ret_result = {key: event[key] for key in ('Attribute', 'Object') if key + in event} + return {'results': ret_result} + + +def introspection(): + return mispattributes + + +def version(): + moduleinfo['config'] = moduleconfig + return moduleinfo From 897164c5edaa653108a4b67e187318365464d4e4 Mon Sep 17 00:00:00 2001 From: Calvin Krzywiec Date: Mon, 22 Nov 2021 15:52:58 -0500 Subject: [PATCH 2/2] feature: add qintel qsentry module documentation --- documentation/logos/qintel.png | Bin 0 -> 47612 bytes .../website/expansion/qintel_qsentry.json | 13 +++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 documentation/logos/qintel.png create mode 100644 documentation/website/expansion/qintel_qsentry.json diff --git a/documentation/logos/qintel.png b/documentation/logos/qintel.png new file mode 100644 index 0000000000000000000000000000000000000000..fa3af768d7234d51238fd8d8d5df80b058017703 GIT binary patch literal 47612 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 Hmze(mT4uy9 literal 0 HcmV?d00001 diff --git a/documentation/website/expansion/qintel_qsentry.json b/documentation/website/expansion/qintel_qsentry.json new file mode 100644 index 0000000..4994a62 --- /dev/null +++ b/documentation/website/expansion/qintel_qsentry.json @@ -0,0 +1,13 @@ +{ + "description": "A hover and expansion module which queries Qintel QSentry for ip reputation data", + "logo": "qintel.png", + "requirements": [ + "A Qintel API token" + ], + "input": "ip address attribute", + "ouput": "Objects containing the enriched IP, threat tags, last seen attributes and associated Autonomous System information", + "features": "This module takes an ip-address (ip-src or ip-dst) attribute as input, and queries the Qintel QSentry API to retrieve ip reputation data", + "references": [ + "https://www.qintel.com/products/qsentry/" + ] +} \ No newline at end of file