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
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)
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()}')