CheckPointSandBlast

Uploads files using polling. The service supports Microsoft Office files, as well as PDF, SWF, archives, and executables. Active content will be cleaned from any documents that you upload (Microsoft Office and PDF files only). Queries on existing IOCs, file status, analysis, and reports. Downloads files from the database. Supports both appliance and cloud. Supported Threat Emulation versions are any R80x.

Forensics & Malware Analysis · Check Point Threat Emulation (SandBlast)

Details

IDCheckPointSandBlast
ProviderCheckPoint Software Technologies
CategoryForensics & Malware Analysis
From Version6.5.0
Docker Imagedemisto/python3:3.12.13.10116658
Supported ModulesAgentix XSIAM

README

Check Point Threat Emulation (SandBlast)

Threat Emulation performs remote analysis by uploading files to a virtual SandBox. Uploaded files are monitored in multiple OS and microsoft office application versions. Malicious files are saved in the ThreatCloud. Safe files are available for download after inspection.

Upload files using polling, the service supports Microsoft Office files, as well as PDF, SWF, archives and executables. Active content will be cleaned from any documents that you upload (Microsoft Office and PDF files only). Query on existing IOCs, file status, analysis, reports. Download files from the database. Supports both appliance and cloud. Supported Threat Emulation versions are any R80x.
This integration was integrated and tested with version v1 of CheckPointSandBlast

Configure Check Point Threat Emulation (SandBlast) in Cortex

Parameter Description Required
Server URL https://te.checkpoint.com True
Authorization - API Key   False
Trust any certificate (not secure)   False
Use system proxy settings   False
Source Reliability Reliability of the source providing the intelligence data. True

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

file


Runs reputation on files.

Base Command

file

Input

Argument Name Description Required
file Hash of the file to query. Supports MD5, SHA1, and SHA256. Required

Context Output

Path Type Description
File.MD5 String The MD5 hash of the file.
File.SHA1 String The SHA1 hash of the file.
File.SHA256 String The SHA256 hash of the file.
File.Malicious.Vendor String The vendor that reported the file as malicious.
File.Malicious.Description String A description explaining why the file was determined to be malicious.
DBotScore.Indicator String The indicator that was tested.
DBotScore.Type String The indicator type.
DBotScore.Vendor String The vendor used to calculate the score.
DBotScore.Reliability String Reliability of the source providing the intelligence data.
DBotScore.Score Number The actual score.

Command example

!file file=e129988964fa250bc8186bfe6f399f12

Context Example

{
    "DBotScore": [
        {
            "Indicator": "e129988964fa250bc8186bfe6f399f12",
            "Reliability": "C - Fairly reliable",
            "Score": 0,
            "Type": "file",
            "Vendor": "VirusTotal"
        },
        {
            "Indicator": "e129988964fa250bc8186bfe6f399f12",
            "Reliability": "C - Fairly reliable",
            "Score": 1,
            "Type": "file",
            "Vendor": "CheckPointSandBlast"
        }
    ],
    "File": {
        "MD5": "e129988964fa250bc8186bfe6f399f12",
        "Malicious": {
            "Description": {
                "confidence": 0,
                "malware_family": 0,
                "malware_type": 0,
                "severity": 0,
                "signature_name": ""
            },
            "Vendor": "CheckPointSandBlast"
        },
        "SHA1": "a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027",
        "SHA256": "7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168"
    }
}

Human Readable Output

Results of file hash: “e129988964fa250bc8186bfe6f399f12”

MD5 SHA1 SHA256 Malicious
e129988964fa250bc8186bfe6f399f12 a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027 7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168 Vendor: CheckPointSandBlast
Description: {“signature_name”: “”, “malware_family”: 0, “malware_type”: 0, “severity”: 0, “confidence”: 0}

sandblast-query


Use the Query API to have a client application look for either the analysis report of a specific file on the Check Point Threat Prevention service databases or the status of a file, uploaded for analysis. It is recommended to add file_name.

Base Command

sandblast-query

Input

Argument Name Description Required
file_name Name of the file to query. Recommended to use, without it status will be “PARTIALLY_FOUND”. Optional
file_hash File hash to query, accepted digests are: md5, sha1 and sha256. Only md5 returns ‘FOUND’ status. Required
features Features to use on the file. Possible values are: Threat Emulation, Anti-Virus, Threat Extraction, All. Default is All. Optional
reports Comma separated list of supported report formats. Note - Requesting for PDF and summary reports simultaneously is not supported. Possible values are: pdf, xml, tar, summary. Default is xml, summary. Optional
method Threat extraction request method. Possible values are: clean, pdf. Default is pdf. Optional
extracted_parts Comma separated list of fields to be cleaned in the file. Only relevant if method = clean. Possible values are: Linked Objects, Macros and Code, Sensitive Hyperlinks, PDF GoToR Actions, PDF Launch Actions, PDF URI Actions, PDF Sound Actions, PDF Movie Actions, PDF JavaScript Actions, PDF Submit Form Actions, Database Queries, Embedded Objects, Fast Save Data, Custom Properties, Statistic Properties, Summary Properties. Default is Linked Objects, Macros and Code, Sensitive Hyperlinks, PDF GoToR Actions, PDF Launch Actions, PDF URI Actions, PDF Sound Actions, PDF Movie Actions, PDF JavaScript Actions, PDF Submit Form Actions, Database Queries, Embedded Objects, Fast Save Data. Optional

Context Output

Path Type Description  
SandBlast.Query.Status String Status of requested features.  
SandBlast.Query.MD5 String The file’s MD5.  
SandBlast.Query.SHA1 String The file’s SHA1.  
SandBlast.Query.SHA256 String The file’s SHA256.  
SandBlast.Query.FileType String File type can be different from the one sent in the query request (according to the type to identify).  
SandBlast.Query.FileName String Name of the file saved on Check Point databases.  
SandBlast.Query.Features String Features used.  
SandBlast.Query.AntiVirus.SignatureName String If the file is not detected by Anti-Virus, the signature name is empty.  
SandBlast.Query.AntiVirus.MalwareFamily Number ID for malware family, if available: {0-}.  
SandBlast.Query.AntiVirus.MalwareType Number ID for malware type, if available: {0-}.  
SandBlast.Query.AntiVirus.Severity Number 0 for benign files. Minimum: 0 Maximum: 4  
SandBlast.Query.AntiVirus.Confidence Number 0 for benign files. Minimum: 0 Maximum 5  
SandBlast.Query.AntiVirus.Status String Status of Anti-Virus on the requested file.  
SandBlast.Query.ThreatExtraction.Method String Method that was used.  
SandBlast.Query.ThreatExtraction.ExtractResult String CP_EXTRACT_RESULT_UNKNOWN (Default - returned if the POD did not receive an answer from the Threat Extraction engine in 60 seconds). CP_EXTRACT_RESULT_SUCCESS, CP_EXTRACT_RESULT_FAILURE, CP_EXTRACT_RESULT_TIMEOUT, CP_EXTRACT_RESULT_UNSUPPORTED_FILE, CP_EXTRACT_RESULT_NOT_SCRUBBED, CP_EXTRACT_RESULT_INTERNAL_ERROR, CP_EXTRACT_RESULT_DISK_LIMIT_REACHED, CP_EXTRACT_RESULT_ENCRYPTED_FILE, CP_EXTRACT_RESULT_DOCSEC_FILE, CP_EXTRACT_RESULT_OUT_OF_MEMORY  
SandBlast.Query.ThreatExtraction.ExtractedFileDownloadId String The download id of the extracted file, for download request. Only sent when extract_result = CP_EXTRACT_RESULT_SUCCESS  
SandBlast.Query.ThreatExtraction.OutputFileName String Clean file name.  
SandBlast.Query.ThreatExtraction.Time String Time for threat extraction completion.  
SandBlast.Query.ThreatExtraction.ExtractContent String Content of extracted file.  
SandBlast.Query.ThreatExtraction.TexProduct Boolean True if the queried file is already a Sandblast-safe copy.  
SandBlast.Query.ThreatExtraction.Status String Status of Threat Extraction on the requested file.  
SandBlast.Upload.ThreatExtraction.ExtractionData.InputExtension String Uploaded filename-extension as sent by the client.  
SandBlast.Query.ThreatExtraction.ExtractionData.InputRealExtension String Extension as resolved by Threat Extraction.  
SandBlast.Query.ThreatExtraction.ExtractionData.Message String Status message for scrub_result  
SandBlast.Query.ThreatExtraction.ExtractionData.ProtectionName String Potential malicious content extracted.  
SandBlast.Query.ThreatExtraction.ExtractionData.ProtectionType String Protection done for scrub_method: Conversion to PDF Content Removal
SandBlast.Query.ThreatExtraction.ExtractionData.ProtocolVersion String Protocol used.  
SandBlast.Query.ThreatExtraction.ExtractionData.RealExtension String Real extension as resolved by Threat Extraction  
SandBlast.Query.ThreatExtraction.ExtractionData.Risk Number Represents the risk of the part that was extracted from the document.  
SandBlast.Query.ThreatExtraction.ExtractionData.ScrubActivity String Readable result from Threat Extraction.  
SandBlast.Query.ThreatExtraction.ExtractionData.ScrubMethod String Convert to PDF Clean Document.
SandBlast.Query.ThreatExtraction.ExtractionData.ScrubResult Number Code result from Threat Extraction.  
SandBlast.Query.ThreatExtraction.ExtractionData.ScrubTime String Threat Extraction process time.  
SandBlast.Query.ThreatExtraction.ExtractionData.ScrubbedContent String Content that was removed  
SandBlast.Query.ThreatEmulation.Trust Number Rating of the threat data and its relevance to this instance. It is recommended to block threats with confidence medium and above.  
SandBlast.Query.ThreatEmulation.Score Number Threat Emulation score.  
SandBlast.Query.ThreatEmulation.CombinedVerdict String Combined verdict of all the images. Benign reports are not supported for local gateways.  
SandBlast.Query.ThreatEmulation.Severity Number Combined severity of threats found. In case threats are not found, this field is not given. 1 - low, 2 - medium, 3 - high, 4 - critical.  
SandBlast.Query.ThreatEmulation.Confidence Number Rating of the threat data and its relevance to this instance. It is recommended to block threats with confidence 2 and above. 1 - low, 2 - medium, 3 - high.  
SandBlast.Query.ThreatEmulation.Images String Sand boxes used in Threat Emulation. Information about image types can be found in https://sc1.checkpoint.com/documents/TPAPI/CP_1.0_ThreatPreventionAPI_APIRefGuide/html_frameset.htm under “Query API” -> “Query Response Format” -> “Images Object Format”.  
SandBlast.Query.ThreatEmulation.Status String Status of Threat Emulation on the requested file.  

Command example

!sandblast-query file_hash=e129988964fa250bc8186bfe6f399f12 file_name=HelloWorld.pdf

Context Example

{
    "SandBlast": {
        "Query": {
            "AntiVirus": {
                "Confidence": 0,
                "MalwareFamily": 0,
                "MalwareType": 0,
                "Severity": 0,
                "SignatureName": "",
                "Status": {
                    "code": 1001,
                    "label": "FOUND",
                    "message": "The request has been fully answered."
                }
            },
            "Features": [
                "te",
                "av",
                "extraction"
            ],
            "FileName": "HelloWorld.pdf",
            "FileType": "pdf",
            "MD5": "e129988964fa250bc8186bfe6f399f12",
            "SHA1": "a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027",
            "SHA256": "7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168",
            "Status": {
                "code": 1001,
                "label": "FOUND",
                "message": "The request has been fully answered."
            },
            "ThreatEmulation": {
                "CombinedVerdict": "benign",
                "Images": [
                    {
                        "id": "e50e99f3-5963-4573-af9e-e3f4750b55e2",
                        "report": {
                            "verdict": "benign"
                        },
                        "revision": 1,
                        "status": "found"
                    },
                    {
                        "id": "3ff3ddae-e7fd-4969-818c-d5f1a2be336d",
                        "report": {
                            "verdict": "benign"
                        },
                        "revision": 1,
                        "status": "found"
                    }
                ],
                "Score": -2147483648,
                "Status": {
                    "code": 1001,
                    "label": "FOUND",
                    "message": "The request has been fully answered."
                },
                "Trust": 0
            },
            "ThreatExtraction": {
                "ExtractContent": "",
                "ExtractResult": "CP_EXTRACT_RESULT_SUCCESS",
                "ExtractedFileDownloadId": "11aa4b44-6699-43fe-b73a-d42435551b06",
                "ExtractionData": {
                    "InputExtension": "pdf",
                    "InputRealExtension": "pdf",
                    "Message": "OK",
                    "ProtectionName": "Extract potentially malicious content",
                    "ProtectionType": "Conversion to PDF",
                    "ProtocolVersion": "",
                    "RealExtension": "pdf",
                    "Risk": 0,
                    "ScrubActivity": "PDF file was converted to PDF",
                    "ScrubMethod": "Convert to PDF",
                    "ScrubResult": 0,
                    "ScrubTime": "0.114",
                    "ScrubbedContent": ""
                },
                "Method": "pdf",
                "OutputFileName": "HelloWorld.cleaned.pdf",
                "Status": {
                    "code": 1001,
                    "label": "FOUND",
                    "message": "The request has been fully answered."
                },
                "TexProduct": false,
                "Time": "0.114"
            }
        }
    }
}

Human Readable Output

Query Results

File Info

Filename Filetype Label Message Md5 Sha1 Sha256
HelloWorld.pdf pdf FOUND The request has been fully answered. e129988964fa250bc8186bfe6f399f12 a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027 7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168

Threat Emulation

Combinedverdict
benign

Anti-Virus

Malwarefamily Malwaretype Confidence Severity
0 0 0 0

Threat Extraction

Extractresult Extractedfiledownloadid Risk
CP_EXTRACT_RESULT_SUCCESS 11aa4b44-6699-43fe-b73a-d42435551b06 0

sandblast-upload


Use the Upload API to have a client application request that Check Point Threat Prevention modules scan and analyze a file. When you upload a file to the service, the file is encrypted. It is un-encrypted during analysis, and then deleted. This command uses polling with query. The stages of polling are ‘UPLOAD_SUCCESS’, ‘PENDING’ and ends with ‘FOUND’ or ‘PARTIALLY_FOUND’. Once the command is done polling it will return analyzed information about the file.

Base Command

sandblast-upload

Input

Argument Name Description Required
interval_in_seconds Interval in seconds between each poll. Default is 60. Optional
timeout_in_seconds Time out in seconds till polling ends. Default is 600. Optional
file_id ID of the file to upload, which will be taken from the uploaded file to XSOAR. Required
file_name Rename the file to upload, if empty the uploaded file will keep its original name. Optional
features Features to use on the file. Possible values are: Threat Emulation, Anti-Virus, Threat Extraction, All. Default is All. Optional
image_ids ID of available OS images. An image is an operating system configuration. Inputs must be of same length as image_revisions and will be paired according to position. Information about image types can be found in https://sc1.checkpoint.com/documents/TPAPI/CP_1.0_ThreatPreventionAPI_APIRefGuide/html_frameset.htm under “Query API” -> “Query Response Format” -> “Images Object Format”. Possible values are: e50e99f3-5963-4573-af9e-e3f4750b55e2, 7e6fe36e-889e-4c25-8704-56378f0830df, 8d188031-1010-4466-828b-0cd13d4303ff, 5e5de275-a103-4f67-b55b-47532918fa59, 3ff3ddae-e7fd-4969-818c-d5f1a2be336d, 6c453c9b-20f7-471a-956c-3198a868dc92, 10b4a9c6-e414-425c-ae8b-fe4dd7b25244. Optional
image_revisions Revisions of available OS images. An image is an operating system configuration. Inputs must be of same length as image_ids and will be paired according to position. Optional
reports Comma separated list of supported report formats. Note - Requesting for PDF and summary reports simultaneously is not supported. Possible values are: pdf, xml, tar, summary. Default is xml, summary. Optional
method Threat extraction request method. Possible values are: clean, pdf. Default is pdf. Optional
extracted_parts Comma separated list of fields to be cleaned in the file. Only relevant if method = clean. Possible values are: Linked Objects, Macros and Code, Sensitive Hyperlinks, PDF GoToR Actions, PDF Launch Actions, PDF URI Actions, PDF Sound Actions, PDF Movie Actions, PDF JavaScript Actions, PDF Submit Form Actions, Database Queries, Embedded Objects, Fast Save Data, Custom Properties, Statistic Properties, Summary Properties. Default is Linked Objects, Macros and Code, Sensitive Hyperlinks, PDF GoToR Actions, PDF Launch Actions, PDF URI Actions, PDF Sound Actions, PDF Movie Actions, PDF JavaScript Actions, PDF Submit Form Actions, Database Queries, Embedded Objects, Fast Save Data. Optional

Context Output

Path Type Description  
SandBlast.Upload.Status String Status of requested features.  
SandBlast.Upload.MD5 String The file’s MD5.  
SandBlast.Upload.SHA1 String The file’s SHA1.  
SandBlast.Upload.SHA256 String The file’s SHA256.  
SandBlast.Upload.FileType String File type can be different from the one sent in the upload request (according to the type to identify).  
SandBlast.Upload.FileName String Name of the file saved on Check Point databases.  
SandBlast.Upload.Features String Features used.  
SandBlast.Upload.AntiVirus.SignatureName String If the file is not detected by Anti-Virus, the signature name is empty.  
SandBlast.Upload.AntiVirus.MalwareFamily Number ID for malware family, if available: {0-}.  
SandBlast.Upload.AntiVirus.MalwareType Number ID for malware type, if available: {0-}.  
SandBlast.Upload.AntiVirus.Severity Number 0 for benign files. Minimum: 0 Maximum: 4  
SandBlast.Upload.AntiVirus.Confidence Number 0 for benign files. Minimum: 0 Maximum 5  
SandBlast.Upload.AntiVirus.Status String Status of Anti-Virus on the requested file.  
SandBlast.Upload.ThreatExtraction.Method String Method that was used.  
SandBlast.Upload.ThreatExtraction.ExtractResult String CP_EXTRACT_RESULT_UNKNOWN (Default - returned if the POD did not receive an answer from the Threat Extraction engine in 60 seconds). CP_EXTRACT_RESULT_SUCCESS, CP_EXTRACT_RESULT_FAILURE, CP_EXTRACT_RESULT_TIMEOUT, CP_EXTRACT_RESULT_UNSUPPORTED_FILE, CP_EXTRACT_RESULT_NOT_SCRUBBED, CP_EXTRACT_RESULT_INTERNAL_ERROR, CP_EXTRACT_RESULT_DISK_LIMIT_REACHED, CP_EXTRACT_RESULT_ENCRYPTED_FILE, CP_EXTRACT_RESULT_DOCSEC_FILE, CP_EXTRACT_RESULT_OUT_OF_MEMORY  
SandBlast.Upload.ThreatExtraction.ExtractedFileDownloadId String The download id of the extracted file, for download request. Only sent when extract_result = CP_EXTRACT_RESULT_SUCCESS  
SandBlast.Upload.ThreatExtraction.OutputFileName String Clean file name.  
SandBlast.Upload.ThreatExtraction.Time String Time for threat extraction completion.  
SandBlast.Upload.ThreatExtraction.ExtractContent String Content of extracted file.  
SandBlast.Upload.ThreatExtraction.TexProduct Boolean True if the queried file is already a Sandblast-safe copy.  
SandBlast.Upload.ThreatExtraction.Status String Status of Threat Extraction on the requested file.  
SandBlast.Upload.ThreatExtraction.ExtractionData.InputExtension String Uploaded filename-extension as sent by the client.  
SandBlast.Upload.ThreatExtraction.ExtractionData.InputRealExtension String Extension as resolved by Threat Extraction.  
SandBlast.Upload.ThreatExtraction.ExtractionData.Message String Status message for scrub_result  
SandBlast.Upload.ThreatExtraction.ExtractionData.ProtectionName String Potential malicious content extracted.  
SandBlast.Upload.ThreatExtraction.ExtractionData.ProtectionType String Protection done for scrub_method: Conversion to PDF Content Removal
SandBlast.Upload.ThreatExtraction.ExtractionData.ProtocolVersion String Protocol used.  
SandBlast.Upload.ThreatExtraction.ExtractionData.RealExtension String Real extension as resolved by Threat Extraction  
SandBlast.Upload.ThreatExtraction.ExtractionData.Risk Number Represents the risk of the part that was extracted from the document.  
SandBlast.Upload.ThreatExtraction.ExtractionData.ScrubActivity String Readable result from Threat Extraction.  
SandBlast.Upload.ThreatExtraction.ExtractionData.ScrubMethod String Convert to PDF Clean Document.
SandBlast.Upload.ThreatExtraction.ExtractionData.ScrubResult Number Code result from Threat Extraction.  
SandBlast.Upload.ThreatExtraction.ExtractionData.ScrubTime String Threat Extraction process time.  
SandBlast.Upload.ThreatExtraction.ExtractionData.ScrubbedContent String Content that was removed  
SandBlast.Upload.ThreatEmulation.Trust Number Rating of the threat data and its relevance to this instance. It is recommended to block threats with confidence medium and above.  
SandBlast.Upload.ThreatEmulation.Score Number Threat Emulation score.  
SandBlast.Upload.ThreatEmulation.CombinedVerdict String Combined verdict of all the images. Benign reports are not supported for local gateways.  
SandBlast.Upload.ThreatEmulation.Severity Number Combined severity of threats found. In case threats are not found, this field is not given.  
SandBlast.Upload.ThreatEmulation.Images String Sand boxes used in Threat Emulation. Information about image types can be found in https://sc1.checkpoint.com/documents/TPAPI/CP_1.0_ThreatPreventionAPI_APIRefGuide/html_frameset.htm under “Query API” -> “Query Response Format” -> “Images Object Format”.  
SandBlast.Upload.ThreatEmulation.Status String Status of Threat Emulation on the requested file.  

Command example

!sandblast-upload file_id=252@117def34-6ca2-4db3-86eb-c9378ad46e65

Context Example

{
    "SandBlast": {
        "Upload": {
            "AntiVirus": {
                "Confidence": 0,
                "MalwareFamily": 0,
                "MalwareType": 0,
                "Severity": 0,
                "SignatureName": "",
                "Status": {
                    "code": 1001,
                    "label": "FOUND",
                    "message": "The request has been fully answered."
                }
            },
            "Features": [
                "te",
                "av",
                "extraction"
            ],
            "FileName": "HelloWorld.pdf",
            "FileType": ".pdf",
            "MD5": "e129988964fa250bc8186bfe6f399f12",
            "SHA1": "a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027",
            "SHA256": "7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168",
            "Status": {
                "code": 1003,
                "label": "PENDING",
                "message": "The request is pending."
            },
            "ThreatEmulation": {
                "CombinedVerdict": "benign",
                "Images": [
                    {
                        "id": "3ff3ddae-e7fd-4969-818c-d5f1a2be336d",
                        "report": {
                            "verdict": "benign"
                        },
                        "revision": 1,
                        "status": "found"
                    },
                    {
                        "id": "e50e99f3-5963-4573-af9e-e3f4750b55e2",
                        "report": {
                            "verdict": "benign"
                        },
                        "revision": 1,
                        "status": "found"
                    }
                ],
                "Score": -2147483648,
                "Status": {
                    "code": 1001,
                    "label": "FOUND",
                    "message": "The request has been fully answered."
                },
                "Trust": 0
            },
            "ThreatExtraction": {
                "Method": "pdf",
                "Status": {
                    "code": 1003,
                    "label": "PENDING",
                    "message": "The request is pending."
                },
                "TexProduct": false
            }
        }
    }
}

Human Readable Output

Upload Results

File Info

Filename Filetype Label Message Md5 Sha1 Sha256
HelloWorld.pdf .pdf UPLOAD_SUCCESS The file was uploaded successfully. e129988964fa250bc8186bfe6f399f12 a5e7aa50b66fdad3ae3b5e9ca66283a263bf7027 7e1eeaa9ac04812ce89eabb824d65073a3a37a1600ad1e1b7748ae12e04bb168

sandblast-download


Use the Download API to download a scanned file from the ThreatCloud according to the file ID.

Base Command

sandblast-download

Input

Argument Name Description Required
file_id ID of the file to download, which will be taken from “Extractedfiledownloadid” from “Threat Extraction” results. Required

Context Output

Path Type Description
File.Size Number The size of the file.
File.SHA1 String The SHA1 hash of the file.
File.SHA256 String The SHA256 hash of the file.
File.Name String The name of the file.
File.SSDeep String The SSDeep hash of the file.
File.EntryID String The entry ID of the file.
File.Info String File information.
File.Type String The file type.
File.MD5 String The MD5 hash of the file.
File.Extension String The file extension.

Command example

!sandblast-download file_id=9dc066ec-ae77-4c96-b176-8dc88db515a9

Context Example

{
    "File": {
        "EntryID": "279@117def34-6ca2-4db3-86eb-c9378ad46e65",
        "Extension": "pdf",
        "Info": "application/pdf",
        "MD5": "63a6c12e9b7aa5fb8a1c758de8b87926",
        "Name": "HelloWorld.cleaned.pdf",
        "SHA1": "febf2e17da8f2d2264897069c6358c001f2fc62d",
        "SHA256": "63d3c65cef4eda67d58d81150a9295393990ad81cbc6607e62092d708b9973bb",
        "SHA512": "e7c5058ea2fbd6834fbcdb0699c713e58b54bd7f3e9e340cf48bd3feebe04ef52f9edf0876f051f15bb0f6d09c3b9ae685654267cc281279023e677e95a2c55e",
        "SSDeep": "384:DGW1n7dLCkC4Ta3ZyCJhpVgizPvth6irUABhcLk5JcRzcpnSMTxZYH06ZJWY:yMa3gCJai3ZHBc8SMTxY",
        "Size": 16228,
        "Type": "PDF document, version 1.5"
    }
}

Human Readable Output

sandblast-quota


Use the Quote API to have a client application get the current license and quota status of the API Key that you use in the authorization of the other APIs. For cloud services only.

Base Command

sandblast-quota

Input

There are no input arguments for this command.

Context Output

Path Type Description
SandBlast.Quota.RemainQuotaHour Number Remaining quota hours.
SandBlast.Quota.RemainQuotaMonth Number Remaining quota months.
SandBlast.Quota.AssignedQuotaHour Number Assigned quota hours.
SandBlast.Quota.AssignedQuotaMonth Number Assigned quota months.
SandBlast.Quota.HourlyQuotaNextReset String Hourly quota next reset.
SandBlast.Quota.MonthlyQuotaNextReset String Monthly quota next reset.
SandBlast.Quota.QuotaId String Quota ID.
SandBlast.Quota.CloudMonthlyQuotaPeriodStart String Cloud monthly quota period start.
SandBlast.Quota.CloudMonthlyQuotaUsageForThisGw Number Cloud monthly quota usage for this GW.
SandBlast.Quota.CloudHourlyQuotaUsageForThisGw Number Cloud hourly quota usage for this GW.
SandBlast.Quota.CloudMonthlyQuotaUsageForQuotaId Number Cloud monthly quota usage for QuotaID.
SandBlast.Quota.CloudHourlyQuotaUsageForQuotaId Number Cloud hourly quota usage for QuotaID.
SandBlast.Quota.MonthlyExceededQuota Number Monthly exceeded quota.
SandBlast.Quota.HourlyExceededQuota Number Hourly exceeded quota.
SandBlast.Quota.CloudQuotaMaxAllowToExceedPercentage Number Cloud quota max allowed to exceed percentage.
SandBlast.Quota.PodTimeGmt String Pod time GMT.
SandBlast.Quota.QuotaExpiration String Quota expiration.
SandBlast.Quota.Action String Quota action.

Command example


#### Context Example

```json
{
    "SandBlast": {
        "Quota": {
            "Action": "ALLOW",
            "AssignedQuotaHour": 500,
            "AssignedQuotaMonth": 10000,
            "CloudHourlyQuotaUsageForQuotaId": 2,
            "CloudHourlyQuotaUsageForThisGw": 2,
            "CloudMonthlyQuotaPeriodStart": "2022-08-01T00:00:00.000Z",
            "CloudMonthlyQuotaUsageForQuotaId": 4,
            "CloudMonthlyQuotaUsageForThisGw": 4,
            "CloudQuotaMaxAllowToExceedPercentage": 1000,
            "HourlyExceededQuota": 0,
            "HourlyQuotaNextReset": "2022-08-01T15:00:00.000Z",
            "MonthlyExceededQuota": 0,
            "MonthlyQuotaNextReset": "2022-09-01T00:00:00.000Z",
            "PodTimeGmt": "2022-08-01T14:42:44.000Z",
            "QuotaExpiration": "2022-09-22T00:00:00.000Z",
            "QuotaId": "D21T63R",
            "RemainQuotaHour": 498,
            "RemainQuotaMonth": 9996
        }
    }
}

Human Readable Output

Quota Information

Remainquotahour Remainquotamonth Assignedquotahour Assignedquotamonth Hourlyquotanextreset Monthlyquotanextreset Quotaid Cloudmonthlyquotaperiodstart Cloudmonthlyquotausageforthisgw Cloudhourlyquotausageforthisgw Cloudmonthlyquotausageforquotaid Cloudhourlyquotausageforquotaid Monthlyexceededquota Hourlyexceededquota Cloudquotamaxallowtoexceedpercentage Podtimegmt Quotaexpiration Action
498 9996 500 10000 2022-08-01T15:00:00.000Z 2022-09-01T00:00:00.000Z D21T63R 2022-08-01T00:00:00.000Z 4 2 4 2 0 0 1000 2022-08-01T14:42:44.000Z 2022-09-22T00:00:00.000Z ALLOW

Configuration parameters

  • url — Server URL (required)
  • credentials
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings
  • integrationReliability — Source Reliability

Commands (5)

  • file

    Runs reputation on files.

  • sandblast-download

    Uses the Download API to download a scanned file from the ThreatCloud according to the file ID.

  • sandblast-query

    Use the Query API to have a client application look for either a specific file's analysis report on the Check Point Threat Prevention service databases or the status of a file, uploaded for analysis. It is recommended to add file_name.

  • sandblast-quota

    Uses the Quota API to have a client application get the current license and quota status of the API key used in the authorization of the other APIs. For cloud services only.

  • sandblast-upload

    Uses the Upload API to have a client application request for Check Point Threat Prevention modules to scan and analyze a file. When you upload a file to the service, the file is encrypted. It is un-encrypted during analysis and then deleted. This command uses polling with query. The stages of polling are 'UPLOAD_SUCCESS', 'PENDING' and ends with 'FOUND' or 'PARTIALLY_FOUND'. Once the command is done polling, it returns analyzed information about the file.

import demistomock as demisto  # noqa: F401
from CommonServerPython import *  # noqa: F401

"""
Check Point Threat Emulation (SandBlast) API Integration for Cortex XSOAR (aka Demisto).
"""
from typing import Any
from CommonServerUserPython import *


""" GLOBAL/PARAMS """


DEFAULT_INTERVAL = 60
DEFAULT_TIMEOUT = 600
MD5_SIZE = 32
SHA1_SIZE = 40
SHA256_SIZE = 64
DIGEST_BY_LENGTH = {
    MD5_SIZE: "md5",
    SHA1_SIZE: "sha1",
    SHA256_SIZE: "sha256",
}
EXTRACTED_PARTS_CODE_BY_DESCRIPTION = {
    "Linked Objects": 1025,
    "Macros and Code": 1026,
    "Sensitive Hyperlinks": 1034,
    "PDF GoToR Actions": 1137,
    "PDF Launch Actions": 1139,
    "PDF URI Actions": 1141,
    "PDF Sound Actions": 1142,
    "PDF Movie Actions": 1143,
    "PDF JavaScript Actions": 1150,
    "PDF Submit Form Actions": 1151,
    "Database Queries": 1018,
    "Embedded Objects": 1019,
    "Fast Save Data": 1021,
    "Custom Properties": 1017,
    "Statistic Properties": 1036,
    "Summary Properties": 1037,
}
FEATURE_BY_NAME = {"Threat Emulation": "te", "Anti-Virus": "av", "Threat Extraction": "extraction", "All": "all"}
QUOTA_HEADERS = [
    "RemainQuotaHour",
    "RemainQuotaMonth",
    "AssignedQuotaHour",
    "AssignedQuotaMonth",
    "HourlyQuotaNextReset",
    "MonthlyQuotaNextReset",
    "QuotaId",
    "CloudMonthlyQuotaPeriodStart",
    "CloudMonthlyQuotaUsageForThisGw",
    "CloudHourlyQuotaUsageForThisGw",
    "CloudMonthlyQuotaUsageForQuotaId",
    "CloudHourlyQuotaUsageForQuotaId",
    "MonthlyExceededQuota",
    "HourlyExceededQuota",
    "CloudQuotaMaxAllowToExceedPercentage",
    "PodTimeGmt",
    "QuotaExpiration",
    "Action",
]


""" CLIENT CLASS """


class Client(BaseClient):
    """
    API Client to communicate with Check Point Threat Prevention API.
    """

    VERSION = "v1"

    def __init__(self, host: str, api_key: str, reliability: str, verify: bool = False, proxy: bool = False):
        """
        Client constructor, set headers and call super class BaseClient.

        Args:
            host (str): Check Point Threat Emulation (SandBlast) API URL.
            api_key (str): API key to connect to the server.
            verify (bool): SSL verification handled by BaseClient. Defaults to False.
            proxy (bool): System proxy is handled by BaseClient. Defaults to False.
        """
        super().__init__(
            base_url=f"{host}/tecloud/api/{Client.VERSION}/file", verify=verify, proxy=proxy, headers={"Authorization": api_key}
        )
        self.reliability = reliability

    def query_request(
        self,
        features: list[str],
        reports: list[str],
        method: str,
        file_name: str = None,
        extracted_parts_codes: list[int] = None,
        **kwargs,
    ) -> dict[str, Any]:
        """
        Return an analysis report or status of a file that was uploaded according to a file hash.

        Args:
            features (List[str]): Features to include in the query, options: te, av, extraction.
            reports (List[str]): Report format for the query, options: pdf, xml, tar, summary.
            method (str): Threat extraction method, options: clean, pdf.
            file_name (str): Name of the file to query. Defaults to None.
            extracted_parts_codes (List[int]): Cleans file according to inserted codes.
                Defaults to None.
            **kwargs: can hold -
                md5 (str): md5 digest of the file to query. Defaults to None.
                sha1 (str): sha1 digest of the file to query. Defaults to None.
                sha256 (str): sha256 digest of the file to query. Defaults to None.

        Returns:
            Dict[str, Any]: Analysis report or status of the queried file.
        """
        json_data = remove_empty_elements(
            {
                "request": {
                    "features": features,
                    "md5": kwargs.get("md5"),
                    "sha1": kwargs.get("sha1"),
                    "sha256": kwargs.get("sha256"),
                    "file_name": file_name,
                    "te": {
                        "reports": reports,
                    },
                    "extraction": {"extracted_parts_codes": extracted_parts_codes, "method": method},
                }
            }
        )

        return self._http_request(method="POST", url_suffix="/query", json_data=json_data)

    def upload_request(
        self,
        file_path: str,
        file_name: str,
        file_type: str,
        features: list[str],
        image_ids: list[str],
        image_revisions: list[Optional[int]],
        reports: list[str],
        method: str,
        extracted_parts_codes: list[int] = None,
    ) -> dict[str, Any]:
        """
        Once the file has been uploaded return an analysis report or status of a file
        that was uploaded.

        Args:
            file_path (str): Path to the file to upload.
            file_name (str): Name of the file to upload.
            file_type (str): Type (extension) of the file to upload.
            features (List[str]): Features to include when uploading, options: te, av, extraction.
            image_ids (List[str]): ID of available OS images.
                An image is an operating system configuration.
            image_revisions (List[int]): Revision of available OS images.
                An image is an operating system configuration.
            reports (List[str]): Report format to upload, options: pdf, xml, tar, summary.
            method (str): Threat extraction method, options: clean, pdf.
            extracted_parts_codes (List[int]): Cleans file according to inserted codes.
                Defaults to None.

        Returns:
            Dict[str, Any]: Analysis report or status of the uploaded file.
        """
        request = json.dumps(
            remove_empty_elements(
                {
                    "request": {
                        "file_name": file_name,
                        "file_type": file_type,
                        "features": features,
                        "te": {
                            "reports": reports,
                            "images": [
                                {"id": image_id, "image_revision": revision}
                                for image_id, revision in zip(image_ids, image_revisions)
                            ],
                        },
                        "extraction": {"extracted_parts_codes": extracted_parts_codes, "method": method},
                    }
                }
            )
        )

        with open(file_path, "rb") as file_handler:
            file = (file_name, file_handler.read())

        return self._http_request(method="POST", url_suffix="/upload", files={"request": request, "file": file})

    def download_request(self, file_id: str) -> requests.Response:
        """
        Return the file saved in the server.

        Args:
            file_id (str): ID of the file in the database.

        Returns:
            bytes: File in database.
        """
        return self._http_request(method="GET", url_suffix="/download", params={"id": file_id}, resp_type="response")

    def quota_request(self) -> dict[str, Any]:
        """
        Return the quota information about current API key.

        Returns:
            Dict[str, Any]: Quota information.
        """
        return self._http_request(
            method="POST",
            url_suffix="/quota",
        )


""" COMMAND FUNCTIONS """


def test_module(client: Client) -> str:
    """
    Tests API connectivity and authentication
    Returning 'ok' indicates that the integration works like it is supposed to.
    Connection to the service is successful.
    Raises exceptions if something goes wrong.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.

    Returns:
        str: 'ok' if test passed, anything else will fail the test.
    """
    try:
        client.query_request(
            file_name="test.pdf",
            features=["te", "av", "extraction"],
            reports=["xml", "summary"],
            method="pdf",
            **{"md5": "80f284ccdf2afae0f5347f4532584a61"},  # type:ignore
        )
    except DemistoException as e:
        e_string = str(e)

        if "403" in e_string:
            return "Authorization Error: make sure API Key is correctly set"

        if "404" in e_string:
            return "URL Error: make sure URL is correctly set"

        return e_string

    return "ok"


def file_command(client: Client, args: dict[str, Any]) -> list[CommandResults]:
    """
    Get file_hash list from user input and check if they are in the correct format.
    Client will make a Query request with every file_hash,
    if the file_hash exists in the server a dbot_score will be calculated.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Raises:
        ValueError: In case the file_hash isn't

    Returns:
        List[CommandResults]: Indicator for every file_hash
    """
    files = argToList(args["file"])
    command_results: list[CommandResults] = []

    for file_hash in files:
        try:
            hash_type = get_hash_type(file_hash)

            if hash_type not in ("md5", "sha1", "sha256"):
                raise ValueError(f'Hash "{file_hash}" is not of type SHA-256, SHA-1 or MD5')

            raw_response = client.query_request(
                features=["te", "av", "extraction"], reports=["xml", "summary"], method="pdf", **{hash_type: file_hash}
            )

            label = dict_safe_get(raw_response, ["response", "status", "label"])

            if label not in ("FOUND", "PARTIALLY_FOUND"):
                message = dict_safe_get(raw_response, ["response", "status", "message"])
                command_results.append(CommandResults(readable_output=f'File not found: "{file_hash}"\n{message}'))
                continue

            file_indicator = get_file_indicator(file_hash, hash_type, raw_response, client.reliability)
            verdict_str = file_indicator.dbot_score.to_readable()

            score_description = {
                "confidence": dict_safe_get(raw_response, ["response", "te", "confidence"]),
                "severity": dict_safe_get(raw_response, ["response", "te", "severity"]),
                "signature_name": dict_safe_get(raw_response, ["response", "av", "malware_info", "signature_name"]),
            }
            outputs = remove_empty_elements(
                {
                    "MD5": dict_safe_get(raw_response, ["response", "md5"]),
                    "SHA1": dict_safe_get(raw_response, ["response", "sha1"]),
                    "SHA256": dict_safe_get(raw_response, ["response", "sha256"]),
                    verdict_str: {"Vendor": "CheckPointSandBlast", "Description": score_description},
                }
            )
            readable_output = tableToMarkdown(
                f'Results of file hash: "{file_hash}"',
                outputs,
                headers=[
                    "MD5",
                    "SHA1",
                    "SHA256",
                    verdict_str,
                ],
            )

            command_results.append(
                CommandResults(
                    readable_output=readable_output,
                    outputs_prefix=outputPaths.get("file"),
                    indicator=file_indicator,
                    outputs=outputs,
                    raw_response=raw_response,
                )
            )

        except Exception as e:
            command_results.append(CommandResults(readable_output=f'Could not process file: "{file_hash}"\n{str(e)}'))

    return command_results


def query_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Query information of a file.
    The command will be a bridge between the client request and the presented value to the user.
    Get arguments inputted by the user and send them to the client.
    Once a response has been received, process and return it so it can be sent to the user.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Raises:
        ValueError: reports input was invalid.
        ValueError: file_hash input was invalid.

    Returns:
        CommandResults: Information about the queried file.
    """
    file_name = args.get("file_name", "")
    file_hash = args["file_hash"]
    features = argToList(args.get("features", ""))
    reports = argToList(args.get("reports"))
    method = args.get("method", "")
    extracted_parts = argToList(args.get("extracted_parts"))

    features = [FEATURE_BY_NAME[feature] for feature in features]

    if "all" in features:
        features = ["te", "av", "extraction"]

    if "te" in features and {"pdf", "summary"}.issubset(reports):
        raise ValueError("Requesting for PDF and summary reports simultaneously is not supported!")

    if method != "clean":
        extracted_parts_codes = None
    else:
        extracted_parts_codes = [EXTRACTED_PARTS_CODE_BY_DESCRIPTION[extracted_part] for extracted_part in extracted_parts]

    file_hash_size = len(file_hash)
    digest = DIGEST_BY_LENGTH.get(file_hash_size)

    if digest is None:
        raise ValueError("file_hash is not recognized!")

    raw_output = client.query_request(
        file_name=file_name,
        features=features,
        reports=reports,
        method=method,
        extracted_parts_codes=extracted_parts_codes,
        **{digest: file_hash},
    )

    output = raw_output.get("response", {"": ""})
    readable_output = get_analysis_readable_output(features, output, "Query")
    output = get_analysis_context_output(output)

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="SandBlast.Query",
        outputs_key_field=["MD5", "SHA1", "SHA256"],
        outputs=output,
        raw_response=raw_output,
    )


def upload_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Upload a file to the server.
    The command will be a bridge between the client request and the presented value to the user.
    Get arguments inputted by the user and send them to the client.
    Once a response has been received, process and return it so it can be sent to the user.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Raises:
        ValueError: The new file's name extension is different from the original.
        ValueError: The length of image_id and image_revision isn't equal.
        ValueError: Reports input was invalid.

    Returns:
        CommandResults: Information about the uploaded file.
    """
    file_id = args["file_id"]
    file_name = args.get("file_name")
    features = argToList(args.get("features"))
    image_ids = argToList(args.get("image_ids"))
    image_revisions = [arg_to_number(image_revision) for image_revision in argToList(args.get("image_revisions"))]
    reports = argToList(args.get("reports"))
    method = args.get("method", "")
    extracted_parts = argToList(args.get("extracted_parts"))

    file_entry = demisto.getFilePath(file_id)

    if not file_name:
        file_name = file_entry["name"]

    file_type = os.path.splitext(file_name)[1]

    if file_type != os.path.splitext(file_entry["name"])[1]:
        raise ValueError("New file name must have the same extension as the original file!")

    features = [FEATURE_BY_NAME[feature] for feature in features]

    if "all" in features:
        features = ["te", "av", "extraction"]

    if len(image_ids) != len(image_revisions):
        raise ValueError("Image IDs and image revisions must be of same length!")

    if "te" in features and {"pdf", "summary"}.issubset(reports):
        raise ValueError("Requesting for PDF and summary reports simultaneously is not supported!")

    if method != "clean":
        extracted_parts_codes = None
    else:
        extracted_parts_codes = [EXTRACTED_PARTS_CODE_BY_DESCRIPTION[extracted_part] for extracted_part in extracted_parts]

    raw_output = client.upload_request(
        file_path=file_entry["path"],
        file_name=file_name,
        file_type=file_type,
        features=features,
        image_ids=image_ids,
        image_revisions=image_revisions,
        reports=reports,
        method=method,
        extracted_parts_codes=extracted_parts_codes,
    )

    output = raw_output.get("response", {"": ""})
    readable_output = get_analysis_readable_output(features, output, "Upload")
    output = get_analysis_context_output(output)

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="SandBlast.Upload",
        outputs_key_field=["MD5", "SHA1", "SHA256"],
        outputs=output,
        raw_response=raw_output,
    )


def download_command(client: Client, args: dict[str, Any]) -> Any:
    """
    Download a file from the server.
    The command will be a bridge between the client request and the presented value to the user.
    Get arguments inputted by the user and send them to the client.
    Once a response has been received, process and return it so it can be sent to the user.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Returns:
        Any: File from the server.
    """
    file_id = args["file_id"]

    output = client.download_request(file_id)

    content_disposition = output.headers.get("Content-Disposition")
    split_content_disposition = content_disposition.split('"') if content_disposition is not None else []

    if len(split_content_disposition) < 2:
        file_name = "file.pdf"
    else:
        file_name = split_content_disposition[1]

    return fileResult(filename=file_name, data=output.content)


def quota_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Get quota information about an API key.
    The command will be a bridge between the client request and the presented value to the user.
    Once a response has been received, process and return it so it can be sent to the user.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Returns:
        CommandResults: Quota information about the API key.
    """
    raw_outputs = client.quota_request()
    outputs = raw_outputs.get("response")[0]  # type:ignore

    output = get_quota_context_output(outputs)

    readable_output = tableToMarkdown(
        "Quota Information",
        output,
        headers=QUOTA_HEADERS,
        headerTransform=string_to_table_header,
        removeNull=True,
    )

    return CommandResults(
        readable_output=readable_output,
        outputs_prefix="SandBlast.Quota",
        outputs_key_field="QuotaId",
        outputs=output,
        raw_response=raw_outputs,
    )


""" POLLING COMMANDS """


def setup_upload_polling_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """
    Initiate polling command for upload command.

    Args:
        client (Client): Connection to the client class from which we can run the desired request.
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request.

    Returns:
        CommandResults: A result to return to the user which will be presented in a markdown value.
            The result itself will depend on the stage of polling.
    """
    return upload_polling_command(args, client=client)


@polling_function(
    name="sandblast-upload",
    interval=arg_to_number(demisto.args().get("interval_in_seconds", DEFAULT_INTERVAL)),
    timeout=arg_to_number(demisto.args().get("timeout_in_seconds", DEFAULT_TIMEOUT)),
    requires_polling_arg=False,
)
def upload_polling_command(args: dict[str, Any], **kwargs) -> PollResult:
    """
    Polling command to display the progress of the upload command.
    After the first run, progress will be shown through the query command.
    Once a new file is uploaded to the server, upload command will provide the status
    'UPLOAD_SUCCESS' and pass arguments to the with query command.
    Query command will run till its status is 'FOUND' or 'PARTIALLY_FOUND',
    which is the ending term for the polling command.

    Args:
        args (Dict[str, Any]): Arguments passed down by the CLI to provide in the HTTP request and a Client.

    Returns:
        PollResult: A result to return to the user which will be set as a CommandResults.
            The result itself will depend on the stage of polling.
    """
    if "file_hash" not in args:
        command_results = upload_command(kwargs["client"], args)

    else:
        command_results = query_command(kwargs["client"], args)

    raw_response = command_results.raw_response

    file_name = dict_safe_get(raw_response, ["response", "file_name"])
    file_hash = dict_safe_get(raw_response, ["response", "md5"])
    label = dict_safe_get(raw_response, ["response", "status", "label"])

    if label in ("FOUND", "PARTIALLY_FOUND"):
        return PollResult(
            response=command_results,
            continue_to_poll=False,
        )

    polling_args = {"file_name": file_name, "file_hash": file_hash, **args}

    return PollResult(
        response=command_results, continue_to_poll=True, args_for_next_run=polling_args, partial_result=command_results
    )


""" HELPER FUNCTIONS """


def get_analysis_context_output(output: dict[str, Any]) -> dict[str, Any]:
    av = dict_safe_get(output, ["av"])
    malware_info = dict_safe_get(av, ["malware_info"])
    extraction = dict_safe_get(output, ["extraction"])
    extraction_data = dict_safe_get(extraction, ["extraction_data"])
    te = dict_safe_get(output, ["te"])

    return remove_empty_elements(
        {
            "Status": dict_safe_get(output, ["status"]),
            "MD5": dict_safe_get(output, ["md5"]),
            "SHA1": dict_safe_get(output, ["sha1"]),
            "SHA256": dict_safe_get(output, ["sha256"]),
            "FileType": dict_safe_get(output, ["file_type"]),
            "FileName": dict_safe_get(output, ["file_name"]),
            "Features": dict_safe_get(output, ["features"]),
            "AntiVirus": {
                "SignatureName": dict_safe_get(malware_info, ["signature_name"]),
                "MalwareFamily": dict_safe_get(malware_info, ["malware_family"]),
                "MalwareType": dict_safe_get(malware_info, ["malware_type"]),
                "Severity": dict_safe_get(malware_info, ["severity"]),
                "Confidence": dict_safe_get(malware_info, ["confidence"]),
                "Status": dict_safe_get(av, ["status"]),
            },
            "ThreatExtraction": {
                "Method": dict_safe_get(extraction, ["method"]),
                "ExtractResult": dict_safe_get(extraction, ["extract_result"]),
                "ExtractedFileDownloadId": dict_safe_get(extraction, ["extracted_file_download_id"]),
                "OutputFileName": dict_safe_get(extraction, ["output_file_name"]),
                "Time": dict_safe_get(extraction, ["time"]),
                "ExtractContent": dict_safe_get(extraction, ["extract_content"]),
                "TexProduct": dict_safe_get(extraction, ["tex_product"]),
                "Status": dict_safe_get(extraction, ["status"]),
                "ExtractionData": {
                    "InputExtension": dict_safe_get(extraction_data, ["input_extension"]),
                    "InputRealExtension": dict_safe_get(extraction_data, ["input_real_extension"]),
                    "Message": dict_safe_get(extraction_data, ["message"]),
                    "ProtectionName": dict_safe_get(extraction_data, ["protection_name"]),
                    "ProtectionType": dict_safe_get(extraction_data, ["protection_type"]),
                    "ProtocolVersion": dict_safe_get(extraction_data, ["protocol_version"]),
                    "RealExtension": dict_safe_get(extraction_data, ["real_extension"]),
                    "Risk": dict_safe_get(extraction_data, ["risk"]),
                    "ScrubActivity": dict_safe_get(extraction_data, ["scrub_activity"]),
                    "ScrubMethod": dict_safe_get(extraction_data, ["scrub_method"]),
                    "ScrubResult": dict_safe_get(extraction_data, ["scrub_result"]),
                    "ScrubTime": dict_safe_get(extraction_data, ["scrub_time"]),
                    "ScrubbedContent": dict_safe_get(extraction_data, ["scrubbed_content"]),
                },
            },
            "ThreatEmulation": {
                "Trust": dict_safe_get(te, ["trust"]),
                "Score": dict_safe_get(te, ["score"]),
                "CombinedVerdict": dict_safe_get(te, ["combined_verdict"]),
                "Images": dict_safe_get(te, ["images"]),
                "Status": dict_safe_get(te, ["status"]),
            },
        }
    )


def get_analysis_readable_output(features: list[str], output: dict[str, Any], command: str) -> Any:
    """
    Get a response outputs and set them to be readable outputs with tableToMarkdown.

    Args:
        features (Dict[str, Any]): Features in the HTTP response.
        output (Dict[str, Any]): HTTP response outputs which will be processed.
        command (str): Name of the calling command.

    Returns:
        Any: Readable outputs which have been set to Markdown
    """
    readable_output = f"{command} Results\n"
    status_label = dict_safe_get(output, ["status", "label"])

    output_file_info = {
        "FileName": dict_safe_get(output, ["file_name"]),
        "FileType": dict_safe_get(output, ["file_type"]),
        "Label": status_label,
        "Message": dict_safe_get(output, ["status", "message"]),
        "MD5": dict_safe_get(output, ["md5"]),
        "SHA1": dict_safe_get(output, ["sha1"]),
        "SHA256": dict_safe_get(output, ["sha256"]),
    }
    headers_file_info = [
        "FileName",
        "FileType",
        "Label",
        "Message",
        "MD5",
        "SHA1",
        "SHA256",
    ]
    readable_output += tableToMarkdown(
        "File Info",
        output_file_info,
        headers=headers_file_info,
        headerTransform=string_to_table_header,
        removeNull=True,
    )

    if status_label not in ("FOUND", "PARTIALLY_FOUND"):
        return readable_output

    if "te" in features:
        output_te = {
            "CombinedVerdict": dict_safe_get(output, ["te", "combined_verdict"]),
            "Severity": dict_safe_get(output, ["te", "severity"]),
            "Confidence": dict_safe_get(output, ["te", "confidence"]),
            "Verdict": dict_safe_get(output, ["te", "verdict"]),
        }
        headers_te = [
            "CombinedVerdict",
            "Severity",
            "Confidence",
            "Verdict",
        ]
        readable_output += tableToMarkdown(
            "Threat Emulation",
            output_te,
            headers=headers_te,
            headerTransform=string_to_table_header,
            removeNull=True,
        )

    if "av" in features:
        output_av = {
            "SignatureName": dict_safe_get(output, ["av", "malware_info", "signature_name"]),
            "MalwareFamily": dict_safe_get(output, ["av", "malware_info", "malware_family"]),
            "MalwareType": dict_safe_get(output, ["av", "malware_info", "malware_type"]),
            "Confidence": dict_safe_get(output, ["av", "malware_info", "confidence"]),
            "Severity": dict_safe_get(output, ["av", "malware_info", "severity"]),
        }
        headers_av = [
            "SignatureName",
            "MalwareFamily",
            "MalwareType",
            "Confidence",
            "Severity",
        ]
        readable_output += tableToMarkdown(
            "Anti-Virus",
            output_av,
            headers=headers_av,
            headerTransform=string_to_table_header,
            removeNull=True,
        )

    if "extraction" in features:
        output_extraction = {
            "ExtractResult": dict_safe_get(output, ["extraction", "extract_result"]),
            "ExtractedFileDownloadId": dict_safe_get(output, ["extraction", "extracted_file_download_id"]),
            "Risk": dict_safe_get(output, ["extraction", "extraction_data", "risk"]),
        }
        headers_extraction = [
            "ExtractResult",
            "ExtractedFileDownloadId",
            "Risk",
        ]
        readable_output += tableToMarkdown(
            "Threat Extraction",
            output_extraction,
            headers=headers_extraction,
            headerTransform=string_to_table_header,
            removeNull=True,
        )

    return readable_output


def get_dbotscore(response: dict[str, Any]) -> int:
    """
    Response received from the API request which holds fields that will help indicate the DBotScore.

    Args:
        response (Dict[str, Any]): Response received from the API request.

    Returns:
        int: A score to represent the reputation of an indicator.
    """
    av_confidence = dict_safe_get(response, ["response", "av", "malware_info", "confidence"])
    av_severity = dict_safe_get(response, ["response", "av", "malware_info", "severity"])

    te_confidence = dict_safe_get(response, ["response", "te", "confidence"])
    te_severity = dict_safe_get(response, ["response", "te", "severity"])
    te_combined_verdict = dict_safe_get(response, ["response", "te", "combined_verdict"])
    if (
        av_confidence == 0
        and av_severity == 0
        and te_combined_verdict.lower() == "benign"
        and (te_severity == 0 or te_severity is None)
        and (te_confidence <= 1 or te_confidence is None)
    ):
        score = Common.DBotScore.GOOD

    elif te_severity == 1:
        score = Common.DBotScore.SUSPICIOUS

    else:
        score = Common.DBotScore.BAD

    return score


def get_file_indicator(file_hash: str, hash_type: str, response: dict[str, Any], reliability: str) -> Common.File:
    """
    Returns a file indicator that could potentially be malicious and will be checked for reputation.

    Args:
        file_hash (str): File hash value
        hash_type (str): File hash type.
        response (Dict[str, Any]): Response received from the API request.
        reliability (str): integration source reliability.

    Returns:
        Common.File: File indicator.
    """
    dbot_score = Common.DBotScore(
        indicator=file_hash,
        indicator_type=DBotScoreType.FILE,
        integration_name="CheckPointSandBlast",
        reliability=reliability,
        score=get_dbotscore(response),
    )

    file_name = dict_safe_get(response, ["response", "file_name"])

    if not file_name:
        file_type = None

    else:
        file_type = os.path.splitext(file_name)[1]

    file_indicator = Common.File(dbot_score=dbot_score, name=file_name, file_type=file_type, **{hash_type: file_hash})

    return file_indicator


def get_date_string(timestamp_string: str = "0") -> str:
    """
    Cast timestamp to int and convert it to a datetime string.

    Args:
        timestamp_string (str, optional): Holds a timestamp to be converted.
            Defaults to '0'.

    Returns:
        str: A string with the timestamp in datetime format.
    """
    timestamp = int(timestamp_string) * 1000
    return timestamp_to_datestring(timestamp)


def get_quota_context_output(outputs: dict[str, Any]) -> dict[str, Any]:
    """
    Convert outputs keys to PascalCase and convert any timestamp to date format.

    Args:
        outputs (Dict[str, Any]): API key quota information.

    Returns:
        Dict[str, Any]: outputs in a more readable form.
    """
    response_by_context = {
        "RemainQuotaHour": "remain_quota_hour",
        "RemainQuotaMonth": "remain_quota_month",
        "AssignedQuotaHour": "assigned_quota_hour",
        "AssignedQuotaMonth": "assigned_quota_month",
        "HourlyQuotaNextReset": "hourly_quota_next_reset",
        "MonthlyQuotaNextReset": "monthly_quota_next_reset",
        "QuotaId": "quota_id",
        "CloudMonthlyQuotaPeriodStart": "cloud_monthly_quota_period_start",
        "CloudMonthlyQuotaUsageForThisGw": "cloud_monthly_quota_usage_for_this_gw",
        "CloudHourlyQuotaUsageForThisGw": "cloud_hourly_quota_usage_for_this_gw",
        "CloudMonthlyQuotaUsageForQuotaId": "cloud_monthly_quota_usage_for_quota_id",
        "CloudHourlyQuotaUsageForQuotaId": "cloud_hourly_quota_usage_for_quota_id",
        "MonthlyExceededQuota": "monthly_exceeded_quota",
        "HourlyExceededQuota": "hourly_exceeded_quota",
        "CloudQuotaMaxAllowToExceedPercentage": "cloud_quota_max_allow_to_exceed_percentage",
        "PodTimeGmt": "pod_time_gmt",
        "QuotaExpiration": "quota_expiration",
        "Action": "action",
    }

    context_outputs_with_date = [
        "HourlyQuotaNextReset",
        "MonthlyQuotaNextReset",
        "CloudMonthlyQuotaPeriodStart",
        "PodTimeGmt",
        "QuotaExpiration",
    ]

    output: dict[str, Any] = {}

    for context_output, response in response_by_context.items():
        output[context_output] = outputs.get(response)

    for key in context_outputs_with_date:
        output[key] = get_date_string(output[key])

    return output


""" MAIN FUNCTION """


def main() -> None:
    """
    Getting data from instance setting and setting up the class Client with an API key.
    Checking user input command with if statements and a dictionary.
    """
    params: dict[str, Any] = demisto.params()
    args: dict[str, Any] = demisto.args()
    command = demisto.command()

    api_key = params["credentials"]["password"]
    host = params["url"]
    verify_certificate = not params.get("insecure", False)
    proxy = params.get("proxy", False)
    reliability = params.get("integrationReliability", "C - Fairly reliable")

    commands = {
        "sandblast-query": query_command,
        "sandblast-upload": setup_upload_polling_command,
        "sandblast-download": download_command,
        "sandblast-quota": quota_command,
        "file": file_command,
    }

    demisto.debug(f"Command being called is {command}")

    try:
        client = Client(
            host=host,
            api_key=api_key,
            reliability=reliability,
            verify=verify_certificate,
            proxy=proxy,
        )

        if command == "test-module":
            return_results(test_module(client))

        elif command in commands:
            return_results(commands[command](client, args))

        else:
            raise NotImplementedError(f"Command doesn't exist - {command}")

    except Exception as e:
        demisto.error(traceback.format_exc())
        return_error(f"Failed to execute {command} command.\nError:\n{str(e)}")


if __name__ in ("__main__", "__builtin__", "builtins"):
    main()