def bot_scan_backend(community, redis, consumer_name, api_key): session = requests.Session() api = PolyswarmAPI(api_key, community=community) consumer = EventConsumer(['scan-requests'], 'bot-scan-backend', consumer_name, get_walrus_db(redis), ScanRequest) producer = EventProducer('scan-results', get_walrus_db(redis)) waiter = ResultWaiter(api, producer) with ThreadPoolExecutor() as pool: for event in consumer.iter_events(): try: event = ScanRequest() if event.artifact_type == 'FILE': stream = session.get(event.uri, stream=True).raw result = api.submit(stream) elif event.artifact_type == 'URL': result = api.submit( event.uri, artifact_type=resources.ArtifactType.URL) else: logger.warning( 'Unsupported artifact type %s, maybe update this backend', event.artifact_type) continue future = pool.submit(waiter.wait_for_result, result.id, event.context) except Exception as e: logger.exception('Exception occurred processing event %s: %s', event, e)
def __init__(self, apikey): self.polyswarm_api = PolyswarmAPI(apikey) self.alert_output = {} self.alert_output['integration'] = INTEGRATION_NAME self.alert_output['polyswarm'] = {} self.alert_output['polyswarm']['found'] = 0 self.alert_output['polyswarm']['malicious'] = 0
def __init__(self): self.config = {} # type: Dict[str,str] self.config['polyswarm_api_key'] = demisto.params().get('api_key') self.config['base_url'] = demisto.params().get('base_url') self.config['polyswarm_community'] = demisto.params().get('polyswarm_community') self.polyswarm_api = PolyswarmAPI(key=self.config['polyswarm_api_key'], uri=self.config['base_url'])
def ruleset(test, name='test'): values = [] values.append( resources.YaraRuleset( { 'account_id': '1', 'created': '2019-11-13T16:27:45.013226', 'deleted': False, 'description': None, 'id': '67713199207380968', 'modified': '2019-11-13T16:27:45.013226', 'name': name, 'yara': 'rule eicar_av_test {\n /*\n Per standard, match only if entire file is EICAR string plus optional trailing whitespace.\n The raw EICAR string to be matched is:\n X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*\n */\n\n meta:\n description = "This is a standard AV test, intended to verify that BinaryAlert is working correctly."\n author = "Austin Byers | Airbnb CSIRT"\n reference = "http://www.eicar.org/86-0-Intended-use.html"\n\n strings:\n $eicar_regex = /^X5O!P%@AP\\[4\\\\PZX54\\(P\\^\\)7CC\\)7\\}\\$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!\\$H\\+H\\*\\s*$/\n\n condition:\n all of them\n}\n\nrule eicar_substring_test {\n /*\n More generic - match just the embedded EICAR string (e.g. in packed executables, PDFs, etc)\n */\n\n meta:\n description = "Standard AV test, checking for an EICAR substring"\n author = "Austin Byers | Airbnb CSIRT"\n\n strings:\n $eicar_substring = "$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!"\n\n condition:\n all of them\n}' }, api=PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma'), )) return values
def PolySwarmURL(url): polyswarm = PolyswarmAPI(key=POLYAPI) try: poly = (r'"' + url + r'"') metaresults = polyswarm.search_by_metadata("strings.urls:" + url) for y in metaresults: if (y.sha256): if (str(y.scan.get('detections', {}).get('malicious'))) != 'None': print("Polyswarm: Malicious") return 1 else: print("Polyswarm: Not Malicious") return 0 except Exception: print("Polyswarm API Quota reached.") return 0
def local_artifacts(test, path, files): file_paths = [os.path.join(path, file_name) for file_name in files] api = PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma') values = [ resources.LocalArtifact.from_path(api, full_path) for full_path in file_paths ] return values
def each_with_type(self, target, file_type): self.results = dict() poly = PolyswarmAPI(key=self.api_key) if file_type == 'url' or file_type == 'msg' or file_type == 'eml': pass else: positives = 0 total = 0 sha256 = None if file_type == "hash": sha256 = target.lower() else: sha256 = hashlib.sha256(open(target, 'r').read()).hexdigest() try: response = poly.search(sha256) self.results['scans'] = list() for result in response: if result.assertions: for assertion in result.assertions: if assertion.verdict: self.results['scans'].append({'av': assertion.author_name, 'veredict': 'Malware'}) positives += 1 total += 1 self.results['total'] = "{0}/{1}".format(positives, total) self.results['positives'] = positives self.results['PolyScore'] = result.polyscore self.results['permalink'] = result.permalink self.results['message'] = "Hash found" return True else: return False except NoResultsException: return False except Exception as error: return False
def artifact_archives(test): values = [] values.append( resources.ArtifactArchive( { 'id': '1', 'community': 'gamma', 'created': '2019-11-14T16:30:00.888191', 'uri': 's3/malicious' }, api=PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma'), )) return values
def hunts(test): values = [] values.append( resources.Hunt( { 'active': True, 'created': '2019-11-13T16:27:45.013226', 'id': '61210404295535902', 'status': 'SUCCESS' }, api=PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma'), )) return values
def __init__(self, *args, **kwargs): super(BaseTestCase, self).__init__(*args, **kwargs) self.test_runner = CliRunner() self.test_captured_output_file = '/tmp/output.txt' self.api_url = 'https://api.polyswarm.network/v2' self.test_api_key = '11111111111111111111111111111111' self.community = 'lima' self.api = PolyswarmAPI(self.test_api_key, community=self.community) self.test_hash_value = '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f' self.test_query = '_exists_:lief.libraries' self.test_submission_uuid = '49091542211453596' self.test_hunt_id = '63433636835291189' self.test_since = '2880' self.test_eicar = b'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' self.test_s3_file_url = 'http://minio:9000/'\ 'testing/testing/files/27/5a/02/'\ '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f?'\ 'response-content-disposition=attachment%3B%20filename%3Dtesting%2F'\ 'files%2F27%2F5a%2F02%'\ '2F275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f&'\ 'response-content-type=application%2Foctet-stream&'\ 'AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE'\ '&Signature=VLCdYUh8skB6cRqo7RUfGrycsKo%3D&Expires=1573768889'
class PolyswarmConnector(): def __init__(self): self.config = {} # type: Dict[str,str] self.config['polyswarm_api_key'] = demisto.params().get('api_key') self.config['base_url'] = demisto.params().get('base_url') self.config['polyswarm_community'] = demisto.params().get('polyswarm_community') self.polyswarm_api = PolyswarmAPI(key=self.config['polyswarm_api_key'], uri=self.config['base_url']) def _get_results(self, object_name: str, title: str, total_scans: int, positives: int, permalink: str, artifact: str, indicator: object) -> object: results = {'Scan_UUID': artifact, 'Total': str(total_scans), 'Positives': str(positives), 'Permalink': permalink, 'Artifact': artifact} readable_output = tableToMarkdown(title, results) return CommandResults( readable_output=readable_output, outputs_prefix=f'PolySwarm.{object_name}', outputs_key_field='Scan_UUID', outputs=results, indicator=indicator, # type: ignore ignore_auto_extract=True) def test_connectivity(self) -> bool: EICAR_HASH = '131f95c51cc819465fa1797f6ccacf9d494aaaff46fa3eac73ae63ffbdfd8267' # guardrails-disable-line try: results = self.polyswarm_api.search(EICAR_HASH) for result in results: if result.failed: return False except Exception: return False return True def get_score(self, polyscore) -> int: if float(polyscore) < 0.2: return Common.DBotScore.GOOD elif 0.2 <= float(polyscore) < 0.7: return Common.DBotScore.SUSPICIOUS else: # polyscore is >= 0.7 return Common.DBotScore.BAD def return_hash_results(self, results: list, title: str, error_msg: str) -> object: # default values total_scans: int = 0 positives: int = 0 md5: str = '' sha256: str = '' sha1: str = '' polyscore: int = 0 for result in results: if result.failed: return_error(error_msg) if not result.assertions: return_error('Run Rescan for this hash') # iterate for getting positives and total_scan number for assertion in result.assertions: if assertion.verdict: positives += 1 total_scans += 1 demisto.debug('Positives: {positives} - Total Scans: {total_scans}'. format(positives=positives, total_scans=total_scans)) md5 = result.md5 sha256 = result.sha256 sha1 = result.sha1 polyscore = result.polyscore dbot_score = Common.DBotScore(indicator=md5, indicator_type=DBotScoreType.FILE, integration_name='PolySwarm', score=self.get_score(polyscore)) indicator = Common.File(md5=md5, sha1=sha1, sha256=sha256, dbot_score=dbot_score) return self._get_results('File', title, total_scans, positives, result.permalink, sha256, indicator) def file_reputation(self, hashes: list) -> object: command_results = [] artifacts = argToList(hashes) for artifact in artifacts: title = 'PolySwarm File Reputation for Hash: %s' % artifact demisto.debug(f'[file_reputation] {title}') try: results = self.polyswarm_api.search(artifact) except Exception as err: return_error('{ERROR_ENDPOINT}{err}'. format(ERROR_ENDPOINT=ERROR_ENDPOINT, err=err)) error_msg = 'Error fetching results. Please try again.' command_results.append(self.return_hash_results(results, title, error_msg)) return command_results def detonate_file(self, entry_id: dict) -> object: title = 'PolySwarm File Detonation for Entry ID: %s' % entry_id demisto.debug(f'[detonate_file] {title}') try: file_info = demisto.getFilePath(entry_id) except Exception: return_error(f'File not found - EntryID: {entry_id}') try: demisto.debug(f'Submit file: {file_info}') instance = self.polyswarm_api.submit(file_info['path'], artifact_name=file_info['name']) result = self.polyswarm_api.wait_for(instance) except Exception as err: return_error('{ERROR_ENDPOINT}{err}'. format(ERROR_ENDPOINT=ERROR_ENDPOINT, err=err)) error_msg = 'Error submitting File.' return self.return_hash_results([result], title, error_msg) def rescan_file(self, hashes: list) -> object: command_results = [] artifacts = argToList(hashes) for artifact in artifacts: title = 'PolySwarm Rescan for Hash: %s' % artifact demisto.debug(f'[rescan_file] {title}') try: instance = self.polyswarm_api.rescan(artifact) result = self.polyswarm_api.wait_for(instance) except Exception as err: return_error('{ERROR_ENDPOINT}{err}'. format(ERROR_ENDPOINT=ERROR_ENDPOINT, err=err)) error_msg = 'Error rescaning File.' command_results.append(self.return_hash_results([result], title, error_msg)) return command_results def get_file(self, hash_file: str): demisto.debug(f'[get_file] Hash: {hash_file}') handle_file = io.BytesIO() try: self.polyswarm_api.download_to_handle(hash_file, handle_file) return fileResult(hash_file, handle_file.getvalue()) except Exception as err: return_error('{ERROR_ENDPOINT}{err}'. format(ERROR_ENDPOINT=ERROR_ENDPOINT, err=err)) def url_reputation(self, param: dict, artifact_type: str) -> list: command_results = [] artifacts = argToList(param[artifact_type]) for artifact in artifacts: title = 'PolySwarm %s Reputation for: %s' % (artifact_type.upper(), artifact) demisto.debug(f'[url_reputation] {title}') # default values total_scans = 0 positives = 0 polyscore = 0 # IP validation if artifact_type == 'ip': try: socket.inet_aton(artifact) except socket.error: return_error('Invalid IP Address: {ip}'. format(ip=artifact)) try: # PolySwarm API: URL, IP and Domain are artifact_type='url' instance = self.polyswarm_api.submit(artifact, artifact_type='url') result = self.polyswarm_api.wait_for(instance) if result.failed: return demisto.results('Error submitting URL.') # iterate for getting positives and total_scan number for assertion in result.assertions: if assertion.verdict: positives += 1 total_scans += 1 polyscore = result.polyscore except Exception as err: return_error('{ERROR_ENDPOINT}{err}'. format(ERROR_ENDPOINT=ERROR_ENDPOINT, err=err)) if artifact_type == 'ip': object_name = 'IP' dbot_score_type = DBotScoreType.IP elif artifact_type == 'url': object_name = 'URL' dbot_score_type = DBotScoreType.URL elif artifact_type == 'domain': object_name = 'Domain' dbot_score_type = DBotScoreType.DOMAIN dbot_score = Common.DBotScore(indicator=artifact, indicator_type=dbot_score_type, integration_name='PolySwarm', score=self.get_score(polyscore)) indicator = None if artifact_type == 'ip': indicator = Common.IP(ip=artifact, dbot_score=dbot_score) elif artifact_type == 'url': indicator = Common.URL(url=artifact, dbot_score=dbot_score) # type: ignore elif artifact_type == 'domain': indicator = Common.Domain(domain=artifact, dbot_score=dbot_score) # type: ignore results = self._get_results(object_name, title, total_scans, positives, result.permalink, artifact, indicator) command_results.append(results) return command_results def get_report(self, hashes: list) -> object: """ UUID is equal to Hash. """ title = 'PolySwarm Report for UUID: %s' % hashes demisto.debug(f'[get_report] {title}') return self.file_reputation(hashes)
def instances(test): values = [] values.append( resources.ArtifactInstance( { 'account_id': '1', 'artifact_id': '11611818710765483', 'assertions': [{ 'author': '0x05328f171b8c1463eaFDACCA478D9EE6a1d923F8', 'author_name': 'eicar', 'bid': '1000000000000000000', 'engine': { 'description': 'eicar', 'name': 'eicar', 'tags': [] }, 'mask': True, 'metadata': { 'malware_family': 'Eicar Test File', 'scanner': { 'environment': { 'architecture': 'x86_64', 'operating_system': 'Linux' } } }, 'verdict': True }], 'community': 'gamma', 'country': '', 'created': '2019-11-07T19:18:00.265903', 'extended_type': 'EICAR virus test files', 'polyscore': 0.5, 'failed': False, 'filename': '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f', 'first_seen': '2019-11-01T21:33:53.292099', 'id': 49091542211453596, 'last_seen': '2019-11-07T16:18:00.269290', 'last_scanned': '2019-11-07T16:18:00.269290', 'md5': '44d88612fea8a8f36de82e1278abb02f', 'metadata': None, 'mimetype': 'text/plain', 'result': True, 's3_file_name': 'testing/files/27/5a/02/275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f', 'sha1': '3395856ce81f2b7382dee72602f798b642f14140', 'sha256': '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f', 'size': 68, 'type': 'FILE', 'votes': [{ 'arbiter': '0xF870491ea0F53F67846Eecb57855284D8270284D', 'vote': True }], 'window_closed': True }, api=PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma'), )) return values
def metadata(test): values = [] values.append( resources.Metadata( { 'artifact': { 'created': '2020-01-14T17:48:55.854940+00:00', 'id': 19021969312842541, 'md5': '44d88612fea8a8f36de82e1278abb02f', 'sha1': '3395856ce81f2b7382dee72602f798b642f14140', 'sha256': '275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f', }, 'hash': { 'sha3_256': '8b4c4e204a8a039198e292d2291f4c451d80e4c38bf0cc04ad3841fea8755bd8', 'sha3_512': 'a20290c6ebf01dc5182bb57718250f61ab11b418466714632a7d1474a02849641f7b78e4093e19ad12fdbedbe02f3bec4ca3ec3235557e82ab5ac02d061e7007', 'sha512': 'cc805d5fab1fd71a4ab352a9c533e65fb2d5b885518f4e565e68847223b8e6b85cb48f3afad842726d99239c9e36505c64b0dc9a061d9e507d833277ada336ab', 'ssdeep': '3:a+JraNvsgzsVqSwHq9:tJuOgzsko', 'ssdeep_chunk': 'a+JraNvsgzsVqSwHq9', 'ssdeep_chunk_size': 3, 'ssdeep_double_chunk': 'tJuOgzsko', 'tlsh': '41a022003b0eee2ba20b00200032e8b00808020e2ce00a3820a020b8c83308803ec228', 'tlsh_quartiles': [ '0:0', '1:0', '2:0', '3:0', '4:0', '5:3', '6:2', '7:3', '8:0', '9:0', '10:3', '11:2', '12:3', '13:2', '14:3', '15:2', '16:0', '17:2', '18:2', '19:3', '20:2', '21:2', '22:0', '23:2', '24:0', '25:0', '26:2', '27:3', '28:0', '29:0', '30:0', '31:0', '32:0', '33:2', '34:0', '35:0', '36:0', '37:0', '38:0', '39:0', '40:0', '41:3', '42:0', '43:2', '44:3', '45:2', '46:2', '47:0', '48:2', '49:3', '50:0', '51:0', '52:0', '53:0', '54:2', '55:0', '56:0', '57:0', '58:2', '59:0', '60:0', '61:0', '62:0', '63:2', '64:0', '65:0', '66:3', '67:2', '68:0', '69:2', '70:3', '71:0', '72:3', '73:2', '74:0', '75:0', '76:0', '77:0', '78:2', '79:2', '80:0', '81:3', '82:2', '83:0', '84:0', '85:2', '86:0', '87:0', '88:2', '89:2', '90:0', '91:0', '92:0', '93:2', '94:0', '95:0', '96:2', '97:3', '98:2', '99:0', '100:3', '101:0', '102:2', '103:0', '104:0', '105:3', '106:0', '107:3', '108:0', '109:0', '110:2', '111:0', '112:2', '113:0', '114:0', '115:0', '116:0', '117:3', '118:3', '119:2', '120:3', '121:0', '122:0', '123:2', '124:0', '125:2', '126:2', '127:0' ], 'tlsh_quartiles_minimum_match': 32 }, 'scan': { 'countries': [], 'detections': { 'malicious': 100, 'benign': 2, 'total': 102 }, 'filename': [ 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious', 'malicious' ], 'first_scan': { 'created': '2020-01-14T17:48:55.854940+00:00', 'artifact_instance_id': 67493245269173378, 'eicar': { 'assertion': 'malicious', 'metadata': { 'malware_family': 'Eicar Test File', 'scanner': { 'environment': { 'architecture': 'x86_64', 'operating_system': 'Linux' } } } } }, 'first_seen': '2020-01-14T17:48:55.854940+00:00', 'last_seen': '2020-01-16T20:41:30.953689+00:00', 'latest_scan': { 'created': '2020-01-16T20:41:30.953689+00:00', 'artifact_instance_id': 67608711919932715, 'eicar': { 'assertion': 'malicious', 'metadata': { 'malware_family': 'Eicar Test File', 'scanner': { 'environment': { 'architecture': 'x86_64', 'operating_system': 'Linux' } } } } }, 'mimetype': { 'extended': 'EICAR virus test files', 'mime': 'text/plain' } }, 'strings': { 'domains': [], 'ipv4': [], 'ipv6': [], 'urls': [] } }, api=PolyswarmAPI(test.test_api_key, uri=test.api_url, community='gamma'), )) return values
class PolySwarm: def __init__(self, apikey): self.polyswarm_api = PolyswarmAPI(apikey) self.alert_output = {} self.alert_output['integration'] = INTEGRATION_NAME self.alert_output['polyswarm'] = {} self.alert_output['polyswarm']['found'] = 0 self.alert_output['polyswarm']['malicious'] = 0 def create_output(self, key, value): self.alert_output['polyswarm'][key] = value def return_output(self): return self.alert_output def search_hash(self, hash): try: Print.debug(f'PolySwarm Search Hash: {hash}') results = self.polyswarm_api.search(hash.lower().strip()) for artifact in results: if artifact.failed: msg = 'Failed to get result.' Print.debug(msg) self.create_output('error', "1") self.create_output('description', msg) return self.alert_output['polyswarm']['found'] = 1 if not artifact.assertions: msg = 'This artifact has not been scanned. Initiate a Scan on the artifact to get scan results."' Print.debug(msg) self.create_output('total', 0) self.create_output('positives', 0) self.create_output('description', msg) return Print.debug('Got artifact results') # all assertion responses from engines all_assertions = artifact.assertions # malicious only assertions from engines malicious_detections = artifact.json['detections']['malicious'] self.create_output('positives', malicious_detections) # total engines asserting total = artifact.json['detections']['total'] self.create_output('total', total) # a score between 0.0 and 1.0 indicating malintent self.create_output('polyscore', artifact.polyscore) if malicious_detections: for assertion in all_assertions: # output only by malicious ones if assertion.verdict: self.create_output( f'microengine.{assertion.engine_name}.verdict', 'maliciuos') if assertion.metadata.get('malware_family'): self.create_output( f'microengine.{assertion.engine_name}.malware_family', assertion.metadata.get('malware_family')) self.alert_output['polyswarm']['malicious'] = 1 if OUTPUT_METADATA: for h, h_val in artifact.metadata.hash.items(): self.create_output(f'metadata.hash.{str(h)}', str(h_val)) self.create_output('sha1', artifact.sha1) self.create_output('sha256', artifact.sha256) self.create_output('md5', artifact.md5) self.create_output('mimetype', artifact.mimetype) self.create_output('extended_type', artifact.extended_type) self.create_output('permalink', artifact.permalink) except api_exceptions.NoResultsException: self.create_output('description', 'The request returned no results.') except Exception as e: self.create_output('error', "1") self.create_output('description', str(e)) traceback.print_exc() Print.error(f'Uncaught exception {traceback.print_exc()}')