Beispiel #1
0
    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
Beispiel #2
0
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()}')