def test_scan_url(self):
        vt = PublicApi(API_KEY)

        try:
            print(json.dumps(vt.scan_url('www.wired.com'), sort_keys=False, indent=4))
        except Exception as e:
            self.fail(e)
예제 #2
0
def analyze_domain(domain):

    if domain in os.listdir(SCAN_RESULT_DIR):
        return

    print(domain)

    vt = VirusTotalPublicApi(API_KEY)

    domain_response = vt.get_domain_report(domain)

    if 'results' not in domain_response.keys():
        print('  - ERROR results not in domain_response keys')
        return True

    if domain_response['results']['verbose_msg'] == 'Domain not found':
        print('  - ERROR Domain not found')
        return True

    url_response = vt.get_url_report(domain)

    if 'results' not in url_response.keys():
        print('  - ERROR results not in url_response keys')
        return True


    if 'verbose_msg' in url_response['results'].keys() and url_response['results']['verbose_msg'] == 'Resource does not exist in the dataset': 
        vt.scan_url(domain)
        print('  - resource does not exist: asking scan')
        return False

        
    results = domain_response['results']

    if 'Websense ThreatSeeker category' in results.keys():
        url_response['Websense ThreatSeeker category'] = results['Websense ThreatSeeker category']

    if 'categories' in results.keys():
        url_response['categories'] = results['categories']

    if 'TrendMicro category' in results.keys():
        url_response['TrendMicro category'] = results['TrendMicro category']

    with open(os.path.join(SCAN_RESULT_DIR, domain), 'w') as data_file:
        data_file.write(json.dumps(url_response))

    return True
예제 #3
0
def analize_url(url: str) -> json:
    """
    Peticion a la API de vt para que analize una url asociada a un fichero
    :param url:
    :return:
    """
    vt = VirusTotalPublicApi(VIRUSTOTAL_API_KEY)
    response = vt.scan_url(url)
    return json.dumps(response, sort_keys=False)
예제 #4
0
    def test_scan_url(self):
        vt = PublicApi(API_KEY)

        try:
            print json.dumps(vt.scan_url('www.wired.com'),
                             sort_keys=False,
                             indent=4)
        except Exception as e:
            self.fail(e)
예제 #5
0
파일: IDS.py 프로젝트: Kw3nt/PyIPS
def link_to_virustotal(link, pkt):
    ''' IN CASE WE FOUND GET link, WE SCAN IT '''
    print 'SCANNING %s'%link
    virus_total_instance = PublicApi('2e1d7b6e998ed0a9830269571ecffa110e41dd8bf34b88ad41e40b4351165d18')
    REQ = virus_total_instance.scan_url(link)
    print 'Waiting for virustotal'
    while True:
        if 'Scan finished' in str(virus_total_instance.get_url_report(link)):
            print 'Scan finished!'
            REP = virus_total_instance.get_url_report(link)['results']['positives']
            break
        else:
            print 'Naaa not yet'
    if REP == '0' or REP == 0:
        print 'SCANNED %s - VERDICT OK [REP=%s]'%(link,REP)
        pkt.accept()
    else:
        print 'SCANNED %s - VERDICT KO [REP=%s]'%(link,REP)
        pkt.drop()
    '''
def main(url):
    apikey = fetchapikey()
    vt = VirusTotalPublicApi(apikey)
    response = vt.scan_url(url)
    reply = []
    if "error" in response.keys():
        respcode="0x01"
        permlink="Report permalink could not be fetched due to an error"
        resource="Resource could not be fetched due to an error"
        scandate="Scan date could not be fetched due to an error"
        scanidty="Scan ID could not be fetched due to an error"
        verbmesg="Please check your internet connection and the URL for typos and try again"
        reply=[respcode,permlink,resource,scandate,scanidty,verbmesg]
    else:
        respcode=str(response["response_code"])
        permlink=str(response["results"]["permalink"])
        resource=str(response["results"]["resource"])
        scandate=str(response["results"]["scan_date"])
        scanidty=str(response["results"]["scan_id"])
        verbmesg=str(response["results"]["verbose_msg"])
        reply=[respcode,permlink,resource,scandate,scanidty,verbmesg]
    return reply
    def _virustotal_function(self, event, *args, **kwargs):
        """Function: perform different scans on the following types:
            ip addresses
            hash - this will attempt to find an existing file report on the hash
            domain
            url - this will attempt to find an existing file report on the url. If none exist, a new scan is queued
            file - this will start a new scan for the file and queue for a report later.
        """
        try:
            validateFields(('incident_id', 'vt_type'), kwargs)  # required

            # Init RequestsCommon with app.config options
            rc = RequestsCommon(opts=self.opts, function_opts=self.options)

            # Create a VirusTotal instance with the API Token and any proxies gathered by RequestsCommon
            vt = VirusTotal(self.options['api_token'], rc.get_proxies())

            # Get the function parameters:
            incident_id = kwargs.get("incident_id")  # number
            artifact_id = kwargs.get("artifact_id")  # number
            attachment_id = kwargs.get("attachment_id")  # number
            vt_type = kwargs.get("vt_type")  # text
            vt_data = kwargs.get("vt_data")  # text

            self.log = logging.getLogger(__name__)
            self.log.info("incident_id: %s", incident_id)
            self.log.info("artifact_id: %s", artifact_id)
            self.log.info("attachment_id: %s", attachment_id)
            self.log.info("vt_type: %s", vt_type)
            self.log.info("vt_data: %s", vt_data)

            yield StatusMessage("starting...")

            # determine next steps based on the API call to make
            if vt_type.lower() == 'file':
                entity = get_input_entity(get_resilient_client(self.resilient),
                                          incident_id, attachment_id,
                                          artifact_id)
                # Create a temporary file to write the binary data to.
                with tempfile.NamedTemporaryFile(
                        'w+b', delete=False) as temp_file_binary:
                    # Write binary data to a temporary file. Make sure to close the file here...this
                    # code must work on Windows and on Windows the file cannot be opened a second time
                    # While open.  Floss will open the file again to read the data, so close before
                    # calling Floss.
                    temp_file_binary.write(entity["data"])
                    temp_file_binary.close()
                    try:
                        response = vt.scan_file(temp_file_binary.name,
                                                filename=entity["name"])
                    except Exception as err:
                        raise err
                    finally:
                        os.unlink(temp_file_binary.name)

                file_result = self.return_response(response,
                                                   vt.get_file_report,
                                                   time.time())

                ## was a sha-256 returned? try an existing report first
                if file_result.get("sha256"):
                    response = vt.get_file_report(file_result.get("sha256"))
                    report_result = self.return_response(
                        response, None, time.time())

                    if report_result.get(
                            "response_code") and report_result.get(
                                "response_code") == 1:
                        result = report_result
                    else:
                        result = file_result

            elif vt_type.lower() == 'url':
                # attempt to see if a report already exists
                response = vt.get_url_report(vt_data)
                result = self.return_response(response, None, time.time())

                # check if result is not found, meaning no report exists
                if result['response_code'] == RC_NOT_FOUND:
                    response = vt.scan_url(vt_data)
                    result = self.return_response(response, vt.get_url_report,
                                                  time.time())

            elif vt_type.lower() == 'ip':
                response = vt.get_ip_report(vt_data)
                result = self.return_response(response, None, time.time())

            elif vt_type.lower() == 'domain':
                response = vt.get_domain_report(vt_data)
                result = self.return_response(response, None, time.time())

            elif vt_type.lower() == 'hash':
                response = vt.get_file_report(vt_data)
                result = self.return_response(response, None, time.time())

            else:
                raise ValueError(
                    "Unknown type field: {}. Check workflow pre-processor script."
                    .format(vt_type))

            results = {"scan": result}

            self.log.debug("scan: {}".format(results))

            # Produce a FunctionResult with the results
            yield FunctionResult(results)
        except Exception:
            yield FunctionError()
예제 #8
0
class VirusTotalAnalyzer(Analyzer):

    def __init__(self):
        Analyzer.__init__(self)
        self.service = self.get_param('config.service', None, 'Service parameter is missing')
        self.virustotal_key = self.get_param('config.key', None, 'Missing VirusTotal API key')
        self.polling_interval = self.get_param('config.polling_interval', 60)
        self.proxies = self.get_param('config.proxy', None)
        self.vt = VirusTotalPublicApi(self.virustotal_key, self.proxies)

    def wait_file_report(self, id):
        results = self.check_response(self.vt.get_file_report(id))
        code = results.get('response_code', None)
        if code == 1:
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_file_report(id)

    def wait_url_report(self, id):
        results = self.check_response(self.vt.get_url_report(id))
        code = results.get('response_code', None)
        if code == 1 and (results.get('scan_id') == id):
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_url_report(id)

    def check_response(self, response):
        if type(response) is not dict:
            self.error('Bad response : ' + str(response))
        status = response.get('response_code', -1)
        if status == 204:
            self.error('VirusTotal api rate limit exceeded (Status 204).')
        if status != 200:
            self.error('Bad status : ' + str(status))
        results = response.get('results', {})
        if 'Missing IP address' in results.get('verbose_msg', ''):
            results['verbose_msg'] = 'IP address not available in VirusTotal'
        return results

        # 0 => not found
        # -2 => in queue
        # 1 => ready

    def read_scan_response(self, response, func):
        results = self.check_response(response)
        code = results.get('response_code', None)
        scan_id = results.get('scan_id', None)
        if code == 1 and scan_id is not None:
            func(scan_id)
        else:
            self.error('Scan not found')

    def summary(self, raw):
        taxonomies = []
        level = "info"
        namespace = "VT"
        predicate = "GetReport"
        value = "0"

        if self.service == "scan":
            predicate = "Scan"

        result = {
            "has_result": True
        }

        if raw["response_code"] != 1:
            result["has_result"] = False

        result["positives"] = raw.get("positives", 0)
        result["total"] = raw.get("total", 0)

        if "scan_date" in raw:
            result["scan_date"] = raw["scan_date"]

        if self.service == "get":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "resolutions" in raw:
                result["resolutions"] = len(raw["resolutions"])
                value = "{} resolution(s)".format(result["resolutions"])
                if result["resolutions"] == 0:
                    level = "safe"
                elif result["resolutions"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"
            if "detected_urls" in raw:
                result["detected_urls"] = len(raw["detected_urls"])
                value = "{} detected_url(s)".format(result["detected_urls"])
                if result["detected_urls"] == 0:
                    level = "safe"
                elif result["detected_urls"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_downloaded_samples" in raw:
                result["detected_downloaded_samples"] = len(
                    raw["detected_downloaded_samples"])

        if self.service == "scan":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

        taxonomies.append(self.build_taxonomy(level, namespace, predicate, value))
        return {"taxonomies": taxonomies}

    def run(self):
        if self.service == 'scan':
            if self.data_type == 'file':
                filename = self.get_param('filename', 'noname.ext')
                filepath = self.get_param('file', None, 'File is missing')
                self.read_scan_response(
                    self.vt.scan_file(filepath, from_disk=True, filename=filename),
                    self.wait_file_report
                )
            elif self.data_type == 'url':
                data = self.get_param('data', None, 'Data is missing')
                self.read_scan_response(
                    self.vt.scan_url(data), self.wait_url_report)
            else:
                self.error('Invalid data type')
        elif self.service == 'get':
            if self.data_type == 'domain':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(
                    self.vt.get_domain_report(data)))
            elif self.data_type == 'fqdn':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(
                    self.vt.get_domain_report(data)))
            elif self.data_type == 'ip':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_ip_report(data)))
            elif self.data_type == 'file':
                hashes = self.get_param('attachment.hashes', None)
                if hashes is None:
                    filepath = self.get_param('file', None, 'File is missing')
                    hash = hashlib.sha256(open(filepath, 'rb').read()).hexdigest()
                else:
                    # find SHA256 hash
                    hash = next(h for h in hashes if len(h) == 64)

                self.report(self.check_response(self.vt.get_file_report(hash)))
            elif self.data_type == 'hash':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_file_report(data)))
            elif self.data_type == 'url':
                data = self.get_param('data', None, 'Data is missing')
                self.report(self.check_response(self.vt.get_url_report(data)))
            else:
                self.error('Invalid data type')
        else:
            self.error('Invalid service')
예제 #9
0
class VirusTotalAnalyzer(Analyzer):
    def __init__(self):
        Analyzer.__init__(self)
        self.service = self.get_param("config.service", None,
                                      "Service parameter is missing")
        self.virustotal_key = self.get_param("config.key", None,
                                             "Missing VirusTotal API key")
        self.polling_interval = self.get_param("config.polling_interval", 60)
        self.rescan_hash_older_than_days = self.get_param(
            "config.rescan_hash_older_than_days", None)
        self.highlighted_antivirus = self.get_param(
            "config.highlighted_antivirus", None)
        self.download_sample = self.get_param("config.download_sample", False)
        self.download_sample_if_highlighted = self.get_param(
            "config.download_sample_if_highlighted", False)
        self.obs_path = None
        self.proxies = self.get_param("config.proxy", None)
        if (self.download_sample or self.download_sample_if_highlighted
                or self.service == "download"):
            self.vt_pay = PrivateApi(self.virustotal_key, self.proxies)
        self.vt = PublicApi(self.virustotal_key, self.proxies)

    def get_file(self, hash):
        self.obs_path = "{}/{}".format(tempfile.gettempdir(), hash)
        response = self.vt_pay.get_file(hash)
        if response.get("response_code", None) == 200:
            with open(self.obs_path, "wb") as f:
                f.write(response["results"])
            kind = filetype.guess(self.obs_path)
            if kind and kind.extension != None:
                os.rename(self.obs_path,
                          "{}.{}".format(self.obs_path, kind.extension))
                self.obs_path = "{}.{}".format(self.obs_path, kind.extension)

    def wait_file_report(self, id):
        results = self.check_response(self.vt.get_file_report(id))
        code = results.get("response_code", None)
        if code == 1:
            if self.data_type == "hash" and (
                    self.download_sample or
                (self.download_sample_if_highlighted
                 and self.highlighted_antivirus and any([
                     results.get("scans", {}).get(av, {}).get(
                         "detected", None) == False
                     for av in self.highlighted_antivirus
                 ]))):
                self.get_file(self.get_param("data", None, "Data is missing"))
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_file_report(id)

    def wait_url_report(self, id):
        results = self.check_response(self.vt.get_url_report(id))
        code = results.get("response_code", None)
        if code == 1 and (results.get("scan_id") == id):
            self.report(results)
        else:
            time.sleep(self.polling_interval)
            self.wait_url_report(id)

    def check_response(self, response):
        if type(response) is not dict:
            self.error("Bad response : " + str(response))
        status = response.get("response_code", -1)
        if status == 204:
            self.error("VirusTotal api rate limit exceeded (Status 204).")
        if status != 200:
            self.error("Bad status : " + str(status))
        results = response.get("results", {})
        if "Missing IP address" in results.get("verbose_msg", ""):
            results["verbose_msg"] = "IP address not available in VirusTotal"
        return results

        # 0 => not found
        # -2 => in queue
        # 1 => ready

    def read_scan_response(self, response, func):
        results = self.check_response(response)
        code = results.get("response_code", None)
        scan_id = results.get("scan_id", None)
        if code == 1 and scan_id is not None:
            func(scan_id)
        else:
            self.error("Scan not found")

    def artifacts(self, raw):
        artifacts = []
        if self.obs_path:
            tags = []
            # This will work only in scan/rescan workflow, not in download only
            if self.highlighted_antivirus:
                for av in self.highlighted_antivirus:
                    detected = raw.get("scans",
                                       {}).get(av, {}).get("detected", None)
                    if detected == False:
                        tags.append("to_{}".format(av))
            artifacts.append(
                self.build_artifact("file", self.obs_path, tags=tags))
        return artifacts

    def summary(self, raw):
        taxonomies = []
        level = "info"
        namespace = "VT"
        predicate = "GetReport"
        value = "0"

        if self.service == "scan":
            predicate = "Scan"
        elif self.service == "rescan":
            predicate = "Rescan"
        elif self.service == "download":
            return {"taxonomies": taxonomies}

        result = {"has_result": True}

        if raw["response_code"] != 1:
            result["has_result"] = False

        result["positives"] = raw.get("positives", 0)
        result["total"] = raw.get("total", 0)

        if "scan_date" in raw:
            result["scan_date"] = raw["scan_date"]

        if self.service == "get":
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "resolutions" in raw:
                result["resolutions"] = len(raw["resolutions"])
                value = "{} resolution(s)".format(result["resolutions"])
                if result["resolutions"] == 0:
                    level = "safe"
                elif result["resolutions"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_urls" in raw:
                result["detected_urls"] = len(raw["detected_urls"])
                value = "{} detected_url(s)".format(result["detected_urls"])
                if result["detected_urls"] == 0:
                    level = "safe"
                elif result["detected_urls"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

            if "detected_downloaded_samples" in raw:
                result["detected_downloaded_samples"] = len(
                    raw["detected_downloaded_samples"])

        if self.service in ["scan", "rescan"]:
            if "scans" in raw:
                result["scans"] = len(raw["scans"])
                value = "{}/{}".format(result["positives"], result["total"])
                if result["positives"] == 0:
                    level = "safe"
                elif result["positives"] < 5:
                    level = "suspicious"
                else:
                    level = "malicious"

        taxonomies.append(
            self.build_taxonomy(level, namespace, predicate, value))

        if self.highlighted_antivirus:
            for av in self.highlighted_antivirus:
                detected = raw.get("scans", {}).get(av,
                                                    {}).get("detected", None)
                if detected == False:
                    taxonomies.append(
                        self.build_taxonomy("info", namespace, av,
                                            "Not detected!"))

        return {"taxonomies": taxonomies}

    def run(self):
        if self.service == "scan":
            if self.data_type == "file":
                filename = self.get_param("filename", "noname.ext")
                filepath = self.get_param("file", None, "File is missing")
                self.read_scan_response(
                    self.vt.scan_file(filepath,
                                      from_disk=True,
                                      filename=filename),
                    self.wait_file_report,
                )
            elif self.data_type == "url":
                data = self.get_param("data", None, "Data is missing")
                self.read_scan_response(self.vt.scan_url(data),
                                        self.wait_url_report)
            else:
                self.error("Invalid data type")

        elif self.service == "rescan":
            if self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                self.read_scan_response(self.vt.rescan_file(data),
                                        self.wait_file_report)
            else:
                self.error("Invalid data type")

        elif self.service == "download":
            if self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                self.get_file(data)
                self.report({"message": "file downloaded"})

        elif self.service == "get":
            if self.data_type == "domain":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_domain_report(data))

            elif self.data_type == "fqdn":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_domain_report(data))

            elif self.data_type == "ip":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_ip_report(data))

            elif self.data_type == "file":
                hashes = self.get_param("attachment.hashes", None)
                if hashes is None:
                    filepath = self.get_param("file", None, "File is missing")
                    hash = hashlib.sha256(open(filepath,
                                               "rb").read()).hexdigest()
                else:
                    hash = next(h for h in hashes if len(h) == 64)
                results = self.check_response(self.vt.get_file_report(hash))

            elif self.data_type == "hash":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_file_report(data))

            elif self.data_type == "url":
                data = self.get_param("data", None, "Data is missing")
                results = self.check_response(self.vt.get_url_report(data))
            else:
                self.error("Invalid data type")

            # if aged and enabled rescan
            if self.data_type == "hash" and self.rescan_hash_older_than_days:
                if (datetime.strptime(results["scan_date"],
                                      "%Y-%m-%d %H:%M:%S") - datetime.now()
                    ).days > self.rescan_hash_older_than_days:
                    self.read_scan_response(self.vt.rescan_file(data),
                                            self.wait_file_report)

            # download if hash, dangerous and not seen by av
            if (self.data_type == "hash"
                    and (results.get("response_code", None) == 1)
                    and (results.get("positives", 0) >= 5)
                    and (self.download_sample or
                         (self.download_sample_if_highlighted
                          and self.highlighted_antivirus and any([
                              results.get("scans", {}).get(av, {}).get(
                                  "detected", None) == False
                              for av in self.highlighted_antivirus
                          ])))):
                self.get_file(data)
            self.report(results)

        else:
            self.error("Invalid service")