GoogleThreatIntelligence
Analyzes suspicious hashes, URLs, domains, and IP addresses.
Data Enrichment & Threat Intelligence · GoogleThreatIntelligence
Details
| ID | GoogleThreatIntelligence |
|---|---|
| Provider | |
| Category | Data Enrichment & Threat Intelligence |
| From Version | 6.10.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM |
README
Google Threat Intelligence
This integration analyzes suspicious hashes, URLs, domains, and IP addresses.
Configure Google Threat Intelligence in Cortex
| Parameter | Description | Required |
|---|---|---|
| API Key | See Acquiring your API key | True |
| Use system proxy settings | False | |
| Trust any certificate (not secure) | False | |
| Source Reliability | Reliability of the source providing the intelligence data | |
| GTI Malicious Verdict. Check Google Threat Intelligence verdict to consider the file malicious. | False | |
| GTI Suspicious Verdict. Check Google Threat Intelligence verdict to consider the file suspicious. | False | |
| File Malicious Threshold. Minimum number of positive results from GoogleThreatIntelligence scanners to consider the file malicious. | See Indicator Thresholds. | False |
| File Suspicious Threshold. Minimum number of positive and suspicious results from GoogleThreatIntelligence scanners to consider the file suspicious. | See Indicator Thresholds. | False |
| IP Malicious Threshold. Minimum number of positive results from GoogleThreatIntelligence scanners to consider the IP malicious. | See Indicator Thresholds. | False |
| IP Suspicious Threshold. Minimum number of positive and suspicious results from GoogleThreatIntelligence scanners to consider the IP suspicious. | See Indicator Thresholds. | False |
| Disable reputation lookups for private IP addresses | To reduce the number of lookups made to the GoogleThreatIntelligence API, this option can be selected to gracefully skip enrichment of any IP addresses allocated for private networks. | False |
| URL Malicious Threshold. Minimum number of positive results from GoogleThreatIntelligence scanners to consider the URL malicious. | See Indicator Thresholds. | False |
| URL Suspicious Threshold. Minimum number of positive and suspicious results from GoogleThreatIntelligence scanners to consider the URL suspicious. | See Indicator Thresholds. | False |
| Domain Malicious Threshold. Minimum number of positive results from GoogleThreatIntelligence scanners to consider the domain malicious. | See Indicator Thresholds. | False |
| Domain Suspicious Threshold. Minimum number of positive and suspicious results from GoogleThreatIntelligence scanners to consider the domain suspicious. | See Indicator Thresholds. | False |
| Preferred Vendors List. CSV list of vendors who are considered more trustworthy. | See Indicator Thresholds. | False |
| Preferred Vendor Threshold. The minimum number of highly trusted vendors required to consider a domain, IP address, URL, or file as malicious. | See Indicator Thresholds. | False |
| Enable score analyzing by Crowdsourced Yara Rules, Sigma, and IDS | See Rules Threshold. | False |
| Crowdsourced Yara Rules Threshold | See Rules Threshold. | False |
| Sigma and Intrusion Detection Rules Threshold | See Rules Threshold. | False |
| Domain Popularity Ranking Threshold | See Rules Threshold. | False |
Acquiring your API key
Your API key can be found in your GoogleThreatIntelligence account user menu, clicking on your avatar:

Your API key carries all your privileges, so keep it secure and don’t share it with anyone.
DBot Score / Reputation scores
The following information describes DBot Score which is new for this version.
Indicator Thresholds
Configure the default threshold for each indicator type in the instance settings.
You can also specify the threshold as an argument when running relevant commands.
- Indicators with positive results from preferred vendors equal to or higher than the threshold will be considered malicious.
- Indicators with positive results equal to or higher than the malicious threshold will be considered malicious.
- Indicators with positive results equal to or higher than the suspicious threshold value will be considered suspicious.
- Domain popularity ranks: GoogleThreatIntelligence is returning a popularity ranks for each vendor. The integration will calculate its average and will compare it to the threshold.
Rules Threshold
If the YARA rules analysis threshold is enabled:
- Indicators with positive results, the number of found YARA rules results, Sigma analysis, or IDS equal to or higher than the threshold, will be considered suspicious.
- If both the the basic analysis and the rules analysis is suspicious, the indicator will be considered as malicious.
If the indicator was found to be suspicious only by the rules thresholds, the indicator will be considered suspicious. - Domain popularity ranks: GoogleThreatIntelligence is returning a popularity ranks for each vendor. The integration will calculate its average and will compare it to the threshold.
The DbotScore calculation process can be seen on the “description” field in any malicious/suspicious DBot score.
You can aquire those calculation on all of the indicators also from the debug log.
Example of a GoogleThreatIntelligence DBot score log:
Basic analyzing of "<domain>"
Found popularity ranks. Analyzing.
The average of the ranks is 809009.0 and the threshold is 10000
Indicator is good by popularity ranks.
Analyzing by get_domain_communicating_files
Found safe by relationship files. total_malicious=0 >= 3
Analyzing by get_url_downloaded_files
Found safe by relationship files. total_malicious=0 >= 3
Analyzing by get_url_referrer_files
Found safe by relationship files. total_malicious=0 >= 3
Reputation commands (ip, url, domain, and file)
- Removed output paths: Due to changes in GoogleThreatIntelligence, the following output paths are no longer supported:
- IP.GoogleThreatIntelligence
- Domain.GoogleThreatIntelligence
- URL.GoogleThreatIntelligence
- File.GoogleThreatIntelligence
Instead, you can use the following output paths that return concrete indicator reputations.
- GoogleThreatIntelligence.IP
- GoogleThreatIntelligence.Domain
- GoogleThreatIntelligence.File
- GoogleThreatIntelligence.URL
- The following commands will no longer analyze the file/url sent to it, but will get the information stored in GoogleThreatIntelligence.
- GoogleThreatIntelligence.Domain
- GoogleThreatIntelligence.IP
To analyze (detonate) the indicator, you can use the following playbooks:
- Detonate File - GoogleThreatIntelligence
- Detonate URL - GoogleThreatIntelligence
- Each reputation command will use at least 1 API call. For advanced reputation commands, use the Premium API flag.
- For each reputation command there is the new extended_data argument . When set to “true”, the results returned by the commands will contain
additional information as last_analysis_results which contains the service name and its specific analysis. -
Reputation commands can return relationships of the indicator.
The relationships that are supported are defined as part of the instance configuration.
For more information regarding URL relationships, see: https://gtidocs.virustotal.com/reference/url-info
For more information regarding IP relationships, see: https://gtidocs.virustotal.com/reference/ip-info
For more information regarding Domain relationships, see: https://gtidocs.virustotal.com/reference/domain-info
For more information regarding File relationships, see: https://gtidocs.virustotal.com/reference/file-info - Starting with XSOAR version 6.9.0, You may monitor API usage via the GoogleThreatIntelligence Execution Metrics dashboard.
Comments
In GoogleThreatIntelligence you can now add comments to all indicator types (IP, Domain, File and URL) so each command now has the resource_type argument.
If supplied, the command will use the resource type to add a comment. If not, the command will determine if the given input is a hash or a URL.
This arguments is available in the following commands:
- gti-comments-get
- gti-comments-add
gti-comments-get
- Added the resource_type argument. If not supplied, will try to determine if the resource argument is a hash or a URL.
- Added the limit argument. Gets the latest comments within the given limit.
- New output path: GoogleThreatIntelligence.Comments.
Detonation (scan) Commands
Removed the gtiLink output from all commands as it does no longer return from the API.
To easily use the scan commands we suggest using the following playbooks:
- Detonate File - GoogleThreatIntelligence
- Detonate URL - GoogleThreatIntelligence
Use the gti-analysis-get command to get the report from the scans.
file
Checks the file reputation of the specified hash.
Base Command
file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | Hash of the file to query. Supports MD5, SHA1, and SHA256. | Required |
| extended_data | Whether to return extended data (last_analysis_results). Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.MD5 | String | Bad MD5 hash. |
| File.SHA1 | String | Bad SHA1 hash. |
| File.SHA256 | String | Bad SHA256 hash. |
| File.Relationships.EntityA | String | The source of the relationship. |
| File.Relationships.EntityB | String | The destination of the relationship. |
| File.Relationships.Relationship | String | The name of the relationship. |
| File.Relationships.EntityAType | String | The type of the source of the relationship. |
| File.Relationships.EntityBType | String | The type of the destination of the relationship. |
| File.Malicious.Vendor | String | For malicious files, the vendor that made the decision. |
| File.Malicious.Detections | Number | For malicious files, the total number of detections. |
| File.Malicious.TotalEngines | Number | For malicious files, the total number of engines that checked the file hash. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.File.attributes.type_description | String | Description of the type of the file. |
| GoogleThreatIntelligence.File.attributes.tlsh | String | The locality-sensitive hashing. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEType | String | MIME type of the file. |
| GoogleThreatIntelligence.File.attributes.names | String | Names of the file. |
| GoogleThreatIntelligence.File.attributes.javascript_info.tags | String | Tags of the JavaScript. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileType | String | The file type. |
| GoogleThreatIntelligence.File.attributes.exiftool.WordCount | String | Total number of words in the file. |
| GoogleThreatIntelligence.File.attributes.exiftool.LineCount | String | Total number of lines in file. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.info | Number | Number of IDS that marked the file as “info”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.high | Number | Number of IDS that marked the file as “high”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.medium | Number | Number of IDS that marked the file as “medium”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.low | Number | Number of IDS that marked the file as “low”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.critical | Number | Number of Sigma analysis that marked the file as “critical”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.high | Number | Number of Sigma analysis that marked the file as “high”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.medium | Number | Number of Sigma analysis that marked the file as “medium”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.low | Number | Number of Sigma analysis that marked the file as “low”. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEEncoding | String | The MIME encoding. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileTypeExtension | String | The file type extension. |
| GoogleThreatIntelligence.File.attributes.exiftool.Newlines | String | Number of newlines signs. |
| GoogleThreatIntelligence.File.attributes.trid.file_type | String | The TrID file type. |
| GoogleThreatIntelligence.File.attributes.trid.probability | Number | The TrID probability. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.description | String | Description of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.source | String | Source of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.author | String | Author of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_name | String | Rule set name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.rule_name | String | Name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_id | String | ID of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.names | String | Name of the file. |
| GoogleThreatIntelligence.File.attributes.last_modification_date | Number | The last modification date in epoch format. |
| GoogleThreatIntelligence.File.attributes.type_tag | String | Tag of the type. |
| GoogleThreatIntelligence.File.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.File.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.File.attributes.size | Number | Size of the file. |
| GoogleThreatIntelligence.File.attributes.popular_threat_classification.suggested_threat_label | String | Suggested thread label. |
| GoogleThreatIntelligence.File.attributes.popular_threat_classification.popular_threat_name | Number | The popular thread name. |
| GoogleThreatIntelligence.File.attributes.times_submitted | Number | Number of times the file was submitted. |
| GoogleThreatIntelligence.File.attributes.last_submission_date | Number | Last submission date in epoch format. |
| GoogleThreatIntelligence.File.attributes.downloadable | Boolean | Whether the file is downloadable. |
| GoogleThreatIntelligence.File.attributes.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.File.attributes.type_extension | String | Extension of the type. |
| GoogleThreatIntelligence.File.attributes.tags | String | File tags. |
| GoogleThreatIntelligence.File.attributes.last_analysis_date | Number | Last analysis date in epoch format. |
| GoogleThreatIntelligence.File.attributes.unique_sources | Number | Unique sources. |
| GoogleThreatIntelligence.File.attributes.first_submission_date | Number | First submission date in epoch format. |
| GoogleThreatIntelligence.File.attributes.ssdeep | String | SSDeep hash of the file. |
| GoogleThreatIntelligence.File.attributes.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.File.attributes.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.File.attributes.magic | String | Identification of file by the magic number. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.harmless | Number | The number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.type-unsupported | Number | The number of engines that found the indicator to be of type unsupported. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.confirmed-timeout | Number | The number of engines that confirmed the timeout of the indicator. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.failure | Number | The number of failed analysis engines. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.File.attributes.meaningful_name | String | Meaningful name of the file. |
| GoogleThreatIntelligence.File.attributes.reputation | Number | The reputation of the file. |
| GoogleThreatIntelligence.File.type | String | Type of the indicator (file). |
| GoogleThreatIntelligence.File.id | String | Type ID of the indicator. |
| GoogleThreatIntelligence.File.links.self | String | Link to the response. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.verdict.value | String | GTI verdict of the file. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.severity.value | String | GTI severity of the file. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the file. |
Command Example
!file file=0000000000000000000000000000000000000000000000000000000000000000
Context Example
{
"DBotScore": {
"Indicator": "0000000000000000000000000000000000000000000000000000000000000000",
"Reliability": "A - Completely reliable",
"Score": 2,
"Type": "file",
"Vendor": "GoogleThreatIntelligence"
},
"File": {
"Extension": "txt",
"MD5": "00000000000000000000000000000000",
"SHA1": "0000000000000000000000000000000000000000",
"SHA256": "0000000000000000000000000000000000000000000000000000000000000000",
"SSDeep": "3:AIO9AJraNvsgzsVqSwHqiUZ:AeJuOgzskwZ",
"Size": 103,
"Tags": [
"text"
],
"Type": "text/plain"
},
"GoogleThreatIntelligence": {
"File": {
"attributes": {
"capabilities_tags": [],
"crowdsourced_yara_results": [
{
"author": "Marc Rivero | McAfee ATR Team",
"description": "Rule to detect the EICAR pattern",
"rule_name": "malw_eicar",
"ruleset_id": "0019ab4291",
"ruleset_name": "MALW_Eicar",
"source": "https://github.com/advanced-threat-research/Yara-Rules"
}
],
"downloadable": true,
"exiftool": {
"FileType": "TXT",
"FileTypeExtension": "txt",
"LineCount": "1",
"MIMEEncoding": "us-ascii",
"MIMEType": "text/plain",
"Newlines": "(none)",
"WordCount": "7"
},
"first_submission_date": 1613356237,
"last_analysis_date": 1617088893,
"last_analysis_stats": {
"confirmed-timeout": 0,
"failure": 0,
"harmless": 0,
"malicious": 7,
"suspicious": 0,
"timeout": 1,
"type-unsupported": 16,
"undetected": 50
},
"last_modification_date": 1617088964,
"last_submission_date": 1613356237,
"magic": "ASCII text, with no line terminators",
"md5": "00000000000000000000000000000000",
"meaningful_name": "brokencert.exe",
"names": [
"brokencert.exe"
],
"popular_threat_classification": {
"popular_threat_name": [
[
"eicar",
7
]
],
"suggested_threat_label": "eicar/test"
},
"reputation": 0,
"sha1": "0000000000000000000000000000000000000000",
"sha256": "0000000000000000000000000000000000000000000000000000000000000000",
"size": 103,
"ssdeep": "3:AIO9AJraNvsgzsVqSwHqiUZ:AeJuOgzskwZ",
"tags": [
"text"
],
"times_submitted": 1,
"tlsh": "T1AEB01208274FFB1ED10738340431F8F14428434D1CD4697414911174887614512D8354",
"total_votes": {
"harmless": 0,
"malicious": 0
},
"type_description": "Text",
"type_extension": "txt",
"type_tag": "text",
"unique_sources": 1
},
"id": "0000000000000000000000000000000000000000000000000000000000000000",
"links": {
"self": "https://www.virustotal.com/api/v3/files/0000000000000000000000000000000000000000000000000000000000000000"
},
"type": "file"
}
}
}
Human Readable Output
Results of file hash 0000000000000000000000000000000000000000000000000000000000000000
Sha1 Sha256 Md5 MeaningfulName TypeExtension Last Modified Reputation Positives 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000 brokencert.exe txt 2021-03-30 07:22:44Z 0 7/74
url-scan
- New output path: GoogleThreatIntelligence.Submission
- Preserved output: gtiScanID
- Removed output path: gtiLink - The V3 API does not returns a link to the GUI anymore.
gti-file-scan-upload-url
- New output path: GoogleThreatIntelligence.FileUploadURL
- Preserved output: gtiUploadURL
New Commands
- gti-search
- gti-ip-passive-dns-data
- gti-file-sandbox-report
- gti-comments-get-by-id
- gti-analysis-get
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.
ip
Checks the reputation of an IP address.
Base Command
ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | IP address to check. | Required |
| extended_data | Whether to return extended data (last_analysis_results). Possible values are: true, false. | Optional |
| override_private_lookup | When set to “true”, enrichment of private IP addresses will be conducted even if it has been disabled at the integration level. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| IP.Address | unknown | Bad IP address. |
| IP.ASN | unknown | Bad IP ASN. |
| IP.Geo.Country | unknown | Bad IP country. |
| IP.Relationships.EntityA | string | The source of the relationship. |
| IP.Relationships.EntityB | string | The destination of the relationship. |
| IP.Relationships.Relationship | string | The name of the relationship. |
| IP.Relationships.EntityAType | string | The type of the source of the relationship. |
| IP.Relationships.EntityBType | string | The type of the destination of the relationship. |
| IP.Malicious.Vendor | unknown | For malicious IPs, the vendor that made the decision. |
| IP.Malicious.Description | unknown | For malicious IPs, the reason that the vendor made the decision. |
| IP.ASOwner | String | The autonomous system owner of the IP. |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.IP.attributes.regional_internet_registry | String | Regional internet registry (RIR). |
| GoogleThreatIntelligence.IP.attributes.jarm | String | JARM data. |
| GoogleThreatIntelligence.IP.attributes.network | String | Network data. |
| GoogleThreatIntelligence.IP.attributes.country | String | The country where the IP is located. |
| GoogleThreatIntelligence.IP.attributes.as_owner | String | IP owner. |
| GoogleThreatIntelligence.IP.attributes.last_analysis_stats.harmless | Number | The number of engines that found the domain to be harmless. |
| GoogleThreatIntelligence.IP.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.IP.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.IP.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.IP.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.IP.attributes.asn | Number | ASN data. |
| GoogleThreatIntelligence.IP.attributes.whois_date | Number | Date of the last update of the whois record. |
| GoogleThreatIntelligence.IP.attributes.reputation | Number | IP reputation. |
| GoogleThreatIntelligence.IP.attributes.last_modification_date | Number | Last modification date in epoch format. |
| GoogleThreatIntelligence.IP.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.IP.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.IP.attributes.continent | String | The continent where the IP is located. |
| GoogleThreatIntelligence.IP.attributes.whois | String | whois data. |
| GoogleThreatIntelligence.IP.type | String | Indicator IP type. |
| GoogleThreatIntelligence.IP.id | String | ID of the IP. |
| GoogleThreatIntelligence.IP.attributes.gti_assessment.verdict.value | String | GTI verdict of the IP address. |
| GoogleThreatIntelligence.IP.attributes.gti_assessment.severity.value | String | GTI severity of the IP address. |
| GoogleThreatIntelligence.IP.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the IP address. |
Command example
!ip ip=1.1.1.1
Context Example
{
"DBotScore": {
"Indicator": "1.1.1.1",
"Reliability": "C - Fairly reliable",
"Score": 1,
"Type": "ip",
"Vendor": "GoogleThreatIntelligence"
},
"IP": {
"ASN": 13335,
"ASOwner": "CLOUDFLARENET",
"Address": "1.1.1.1",
"DetectionEngines": 94,
"PositiveDetections": 4,
"Relationships": [
{
"EntityA": "1.1.1.1",
"EntityAType": "IP",
"EntityB": "00000cd773f456da710fa334507f8303e87ee228a0c42e365b0250a9a267e734",
"EntityBType": "File",
"Relationship": "communicates-with"
},
{
"EntityA": "1.1.1.1",
"EntityAType": "IP",
"EntityB": "0000703e66fe64992425a5a6231671c08a6c3382a28d0efacc7efd3fb289a143",
"EntityBType": "File",
"Relationship": "communicates-with"
}
]
},
"GoogleThreatIntelligence": {
"IP": {
"attributes": {
"as_owner": "CLOUDFLARENET",
"asn": 13335,
"jarm": "27d3ed3ed0003ed1dc42d43d00041d6183ff1bfae51ebd88d70384363d525c",
"last_analysis_stats": {
"harmless": 80,
"malicious": 4,
"suspicious": 0,
"timeout": 0,
"undetected": 10
},
"last_https_certificate": {
"cert_signature": {
"signature": "3064023024c2cf6cbdf6aed1c9d51f4a742e3c3dd1c03edcd71bd394715bfea5861626820122d30a6efc98b5d2e2b9e5076977960230457b6f82a67db662c33185d5b5355d4f4c8488ac1a003d0c8440dcb0a7ca1c1327151e37f946c3aed9fdf9b9238b7f2a",
"signature_algorithm": "1.2.840.10045.4.3.3"
},
"extensions": {
"**exten**": "0481f200f00076002979bef09e393921f056739f63a577e5be577d9c600af8f9",
"CA": true,
"authority_key_identifier": {
"keyid": "0abc0829178ca5396d7a0ece33c72eb3edfbc37a"
},
"ca_information_access": {
"CA Issuers": "http://cacerts.example.com/exampleTLSHybridECCSHA3842020CA1.crt",
"OCSP": "http://ocsp.example.com"
},
"certificate_policies": [
"**policy**"
],
"crl_distribution_points": [
"http://crl3.example.com/exampleTLSHybridECCSHA3842020CA1.crl",
"http://crl4.example.com/exampleTLSHybridECCSHA3842020CA1.crl"
],
"extended_key_usage": [
"serverAuth",
"clientAuth"
],
"key_usage": [
"ff"
],
"subject_alternative_name": [
"cloudflare-dns.com",
"*.cloudflare-dns.com",
"one.one.one.one",
"\u0001\u0001\u0001\u0001",
"\u0001\u0001",
"\\xa2\\x9f$\\x01",
"\\xa2\\x9f.\\x01",
"&\u0006GG\u0011\u0011",
"&\u0006GG\u0010\u0001",
"GGd",
"GGd"
],
"subject_key_identifier": "19451b2318f874da2214cb466be213b360158240",
"tags": []
},
"issuer": {
"C": "US",
"CN": "example TLS Hybrid ECC SHA384 2020 CA1",
"O": "example Inc"
},
"public_key": {
"algorithm": "EC",
"ec": {
"oid": "secp256r1",
"pub": "0417ad1fe835af70d38d9c9e64fd471e5b970c0ad110a826321136664d1299c3e131bbf5216373dda5c1c1a0f06da4c45ee1c2dbdaf90d34801af7b9e03af2d574"
}
},
"serial_number": "5076f66d11b692256ccacd546ffec53",
"signature_algorithm": "1.2.840.10045.4.3.3",
"size": 1418,
"subject": {
"C": "US",
"CN": "cloudflare-dns.com",
"L": "San Francisco",
"O": "Cloudflare, Inc.",
"ST": "California"
},
"tags": [],
"thumbprint": "f1b38143b992645497cf452f8c1ac84249794282",
"thumbprint_sha256": "fb444eb8e68437bae06232b9f5091bccff62a768ca09e92eb5c9c2cf9d17c426",
"validity": {
"not_after": "2022-10-25 23:59:59",
"not_before": "2021-10-25 00:00:00"
},
"version": "V3"
},
"last_https_certificate_date": 1617041198,
"last_modification_date": 1617083545,
"network": "1.1.1.0/24",
"reputation": 134,
"tags": [],
"total_votes": {
"harmless": 63,
"malicious": 8
},
"whois": "**whois string**",
"whois_date": 1631599972
},
"id": "1.1.1.1",
"links": {
"self": "https://www.virustotal.com/api/v3/ip_addresses/1.1.1.1"
},
"relationships": {
"communicating_files": {
"data": [
{
"id": "00000cd773f456da710fa334507f8303e87ee228a0c42e365b0250a9a267e734",
"type": "file"
},
{
"id": "0000703e66fe64992425a5a6231671c08a6c3382a28d0efacc7efd3fb289a143",
"type": "file"
}
],
"links": {
"next": "https://www.virustotal.com/api/v3/ip_addresses/1.1.1.1/relationships/communicating_files?cursor=eyJsaW1pdCI6IDIwLCAib2Zmc2V0IjogMjB9&limit=20",
"related": "https://www.virustotal.com/api/v3/ip_addresses/1.1.1.1/communicating_files",
"self": "https://www.virustotal.com/api/v3/ip_addresses/1.1.1.1/relationships/communicating_files?limit=20"
},
"meta": {
"cursor": "eyJsaW1pdCI6IDIwLCAib2Zmc2V0IjogMjB9"
}
}
},
"type": "ip_address"
}
}
}
Human Readable Output
IP reputation of 1.1.1.1
Id Network Country AsOwner LastModified Reputation Positives 1.1.1.1 1.1.1.0/24 CLOUDFLARENET 2022-08-29 15:15:41Z 134 4/94
url
Checks the reputation of a URL.
Base Command
url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL to check. | Required |
| extended_data | Whether to return extended data (last_analysis_results). Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| URL.Data | unknown | Bad URLs found. |
| URL.Relationships.EntityA | String | The source of the relationship. |
| URL.Relationships.EntityB | String | The destination of the relationship. |
| URL.Relationships.Relationship | String | The name of the relationship. |
| URL.Relationships.EntityAType | String | The type of the source of the relationship. |
| URL.Relationships.EntityBType | String | The type of the destination of the relationship. |
| URL.Malicious.Vendor | unknown | For malicious URLs, the vendor that made the decision. |
| URL.Malicious.Description | unknown | For malicious URLs, the reason that the vendor made the decision. |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.URL.attributes.favicon.raw_md5 | String | The MD5 hash of the URL. |
| GoogleThreatIntelligence.URL.attributes.favicon.dhash | String | Difference hash. |
| GoogleThreatIntelligence.URL.attributes.last_modification_date | Number | Last modification date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.times_submitted | Number | The number of times the url has been submitted. |
| GoogleThreatIntelligence.URL.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.URL.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.URL.attributes.threat_names | String | Name of the threats found. |
| GoogleThreatIntelligence.URL.attributes.last_submission_date | Number | The last submission date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_length | Number | The last HTTPS response length. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.date | Date | The last response header date. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.x-sinkhole | String | DNS sinkhole from last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-length | String | The content length of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-type | String | The content type of the last response. |
| GoogleThreatIntelligence.URL.attributes.reputation | Number | Reputation of the indicator. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_date | Number | The date of the last analysis in epoch format. |
| GoogleThreatIntelligence.URL.attributes.has_content | Boolean | Whether the url has content in it. |
| GoogleThreatIntelligence.URL.attributes.first_submission_date | Number | The first submission date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_sha256 | String | The SHA-256 hash of the content of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_code | Number | Last response status code. |
| GoogleThreatIntelligence.URL.attributes.last_final_url | String | Last final URL. |
| GoogleThreatIntelligence.URL.attributes.url | String | The URL itself. |
| GoogleThreatIntelligence.URL.attributes.title | String | Title of the page. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.harmless | Number | The number of engines that found the domain to be harmless. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.URL.attributes.outgoing_links | String | Outgoing links of the URL page. |
| GoogleThreatIntelligence.URL.type | String | Type of the indicator (url). |
| GoogleThreatIntelligence.URL.id | String | ID of the indicator. |
| GoogleThreatIntelligence.URL.links.self | String | Link to the response. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.verdict.value | String | GTI verdict of the URL. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.severity.value | String | GTI severity of the URL. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the URL. |
Command Example
!url url=https://example.com
Context Example
{
"DBotScore": {
"Indicator": "https://example.com",
"Reliability": "A - Completely reliable",
"Score": 2,
"Type": "url",
"Vendor": "GoogleThreatIntelligence"
},
"URL": {
"Category": {
"Dr.Web": "known infection source",
"Forcepoint ThreatSeeker": "information technology",
"alphaMountain.ai": "Malicious",
"sophos": "malware callhome, command and control"
},
"Data": "https://example.com",
"DetectionEngines": 86,
"PositiveDetections": 8
},
"GoogleThreatIntelligence": {
"URL": {
"attributes": {
"categories": {
"Dr.Web": "known infection source"
},
"first_submission_date": 1554509044,
"has_content": false,
"html_meta": {},
"last_analysis_date": 1615900309,
"last_analysis_stats": {
"harmless": 71,
"malicious": 8,
"suspicious": 0,
"timeout": 0,
"undetected": 7
},
"last_final_url": "https://example.com/dashboard/",
"last_http_response_code": 200,
"last_http_response_content_length": 1671,
"last_http_response_content_sha256": "f2ddbc5b5468c2cd9c28ae820420d32c4f53d088e4a1cc31f661230e4893104a",
"last_http_response_headers": {
"content-length": "1671",
"content-type": "text/html; charset=utf-8",
"date": "Tue, 16 Mar 2021 13:16:50 GMT",
"x-sinkhole": "Malware"
},
"last_modification_date": 1615900620,
"last_submission_date": 1615900309,
"outgoing_links": [
"http://www.example.com",
"http://www.example.com"
],
"reputation": 0,
"tags": [],
"targeted_brand": {},
"threat_names": [
"C2/Generic-A"
],
"times_submitted": 5,
"title": "Welcome page",
"total_votes": {
"harmless": 0,
"malicious": 0
},
"trackers": {},
"url": "https://example.com/"
},
"id": "84eb1485254266e093683024b3bd172abde615fc6a37498707ca912964a108a9",
"links": {
"self": "https://www.virustotal.com/api/v3/urls/84eb1485254266e093683024b3bd172abde615fc6a37498707ca912964a108a9"
},
"type": "url"
}
}
}
Human Readable Output
URL data of “https://example.com”
Url Title LastModified HasContent LastHttpResponseContentSha256 Positives Reputation https://example.com Welcome page 2021-03-16 13:17:00Z false f2ddbc5b5468c2cd9c28ae820420d32c4f53d088e4a1cc31f661230e4893104a 8/86 0
domain
Checks the reputation of a domain.
Base Command
domain\
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Domain name to check. | Required |
| extended_data | Whether to return extended data (last_analysis_results). Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| Domain.Name | unknown | Bad domain found. |
| Domain.Relationships.EntityA | String | The source of the relationship. |
| Domain.Relationships.EntityB | String | The destination of the relationship. |
| Domain.Relationships.Relationship | String | The name of the relationship. |
| Domain.Relationships.EntityAType | String | The type of the source of the relationship. |
| Domain.Relationships.EntityBType | String | The type of the destination of the relationship. |
| Domain.Malicious.Vendor | unknown | For malicious domains, the vendor that made the decision. |
| Domain.Malicious.Description | unknown | For malicious domains, the reason that the vendor made the decision. |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.Domain.attributes.last_dns_records.type | String | The type of the last DNS records. |
| GoogleThreatIntelligence.Domain.attributes.last_dns_records.value | String | The value of the last DNS records. |
| GoogleThreatIntelligence.Domain.attributes.last_dns_records.ttl | Number | The time To live (ttl) of the last DNS records. |
| GoogleThreatIntelligence.Domain.attributes.jarm | String | JARM data. |
| GoogleThreatIntelligence.Domain.attributes.whois | String | whois data. |
| GoogleThreatIntelligence.Domain.attributes.last_dns_records_date | Number | The last DNS records date in epoch format. |
| GoogleThreatIntelligence.Domain.attributes.last_analysis_stats.harmless | Number | The number of engines that found the domain to be harmless. |
| GoogleThreatIntelligence.Domain.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.Domain.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.Domain.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.Domain.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.Domain.attributes.favicon.raw_md5 | String | MD5 hash of the domain. |
| GoogleThreatIntelligence.Domain.attributes.favicon.dhash | String | Difference hash. |
| GoogleThreatIntelligence.Domain.attributes.reputation | Number | Reputation of the indicator. |
| GoogleThreatIntelligence.Domain.attributes.registrar | String | Registrar information. |
| GoogleThreatIntelligence.Domain.attributes.last_update_date | Number | Last updated date in epoch format. |
| GoogleThreatIntelligence.Domain.attributes.last_modification_date | Number | Last modification date in epoch format. |
| GoogleThreatIntelligence.Domain.attributes.creation_date | Number | Creation date in epoch format. |
| GoogleThreatIntelligence.Domain.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.Domain.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.Domain.type | String | Type of indicator (domain). |
| GoogleThreatIntelligence.Domain.id | String | ID of the domain. |
| GoogleThreatIntelligence.Domain.links.self | String | Link to the domain investigation. |
| GoogleThreatIntelligence.Domain.attributes.gti_assessment.verdict.value | String | GTI verdict of the domain. |
| GoogleThreatIntelligence.Domain.attributes.gti_assessment.severity.value | String | GTI severity of the domain. |
| GoogleThreatIntelligence.Domain.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the domain. |
Command Example
!domain domain=example.com
Context Example
{
"DBotScore": {
"Indicator": "example.com",
"Reliability": "A - Completely reliable",
"Score": 2,
"Type": "domain",
"Vendor": "GoogleThreatIntelligence"
},
"Domain": {
"Admin": {
"Country": " PA",
"Email": " [REDACTED]@whoisguard.com",
"Name": " WhoisGuard, Inc.",
"Phone": null
},
"CreationDate": [
" 2017-01-21T16:26:19.0Z"
],
"ExpirationDate": " 2018-01-21T23:59:59.0Z",
"Name": "example.com",
"NameServers": [
" PDNS1.REGISTRAR-SERVERS.COM"
],
"Registrant": {
"Country": " PA",
"Email": " [REDACTED]@whoisguard.com",
"Name": null,
"Phone": null
},
"Registrar": {
"AbuseEmail": " abuse@namecheap.com",
"AbusePhone": " +1.6613102107",
"Name": [
" Namecheap",
" NAMECHEAP INC"
]
},
"UpdatedDate": [
"2017-03-06T21:52:39.0Z"
],
"WHOIS": {
"Admin": {
"Country": " PA",
"Email": " [REDACTED]@whoisguard.com",
"Name": " WhoisGuard, Inc.",
"Phone": null
},
"CreationDate": [
"2017-01-21T16:26:19.0Z"
],
"ExpirationDate": " 2018-01-21T23:59:59.0Z",
"NameServers": [
" PDNS1.REGISTRAR-SERVERS.COM"
],
"Registrant": {
"Country": " PA",
"Email": " [REDACTED]@whoisguard.com",
"Name": null,
"Phone": null
},
"Registrar": {
"AbuseEmail": " abuse@namecheap.com",
"AbusePhone": " +1.6613102107",
"Name": [
" Namecheap",
" NAMECHEAP INC"
]
},
"UpdatedDate": [
" 2017-03-06T21:52:39.0Z"
]
}
},
"GoogleThreatIntelligence": {
"Domain": {
"attributes": {
"categories": {
"Dr.Web": "known infection source",
"Forcepoint ThreatSeeker": "information technology",
"alphaMountain.ai": "Malicious",
"sophos": "malware callhome, command and control"
},
"creation_date": 1485015979,
"favicon": {
"dhash": "f4cca89496a0ccb2",
"raw_md5": "6eb4a43cb64c97f76562af703893c8fd"
},
"jarm": "29d21b20d29d29d21c41d21b21b41d494e0df9532e75299f15ba73156cee38",
"last_analysis_stats": {
"harmless": 66,
"malicious": 8,
"suspicious": 0,
"timeout": 0,
"undetected": 8
},
"last_dns_records": [
{
"ttl": 3599,
"type": "A",
"value": "value"
}
],
"last_dns_records_date": 1615900633,
"last_modification_date": 1615900633,
"last_update_date": 1488837159,
"popularity_ranks": {},
"registrar": "Namecheap",
"reputation": 0,
"tags": [],
"total_votes": {
"harmless": 0,
"malicious": 0
},
"whois": "**whoisstring**"
},
"id": "example.com",
"links": {
"self": "https://www.virustotal.com/api/v3/domains/example.com"
},
"type": "domain"
}
}
}
Human Readable Output
Domain data of example.com
Id Registrant Country LastModified LastAnalysisStats example.com PA 2021-03-16 13:17:13Z harmless: 66malicious: 8
suspicious: 0
undetected: 8
timeout: 0
cve
Retrieves CVE information from Google Threat Intelligence.
Base Command
cve
Input
| Argument Name | Description | Required |
|---|---|---|
| cve | Provide CVE ID. Supports comma-separated values. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CVE.CVSS.Score | Number | CVSS score indicating the severity of the vulnerability. |
| CVE.CVSS.Vector | String | CVSS vector string representing attack metrics and impact. |
| CVE.Description | String | Full textual description of the CVE, including affected components and exploitation details. |
| CVE.ID | String | Unique identifier for the CVE (e.g., CVE-2025-14205). |
| CVE.Modified | Date | Timestamp when the CVE record was last modified (e.g., 1766963614). |
| CVE.Published | Date | Timestamp when the CVE was originally published (e.g., 1766963614). |
| CVE.Relationships.EntityA | String | First entity in the relationship (usually the CVE ID). |
| CVE.Relationships.EntityAType | String | Type of the first entity (e.g., CVE). |
| CVE.Relationships.EntityB | String | Second entity in the relationship (e.g., file, IP, domain). |
| CVE.Relationships.EntityBType | String | Type of the second entity (e.g., File, Domain, IP). |
| CVE.Relationships.Relationship | String | Nature of the relationship between EntityA and EntityB (e.g., related-to). |
| CVE.Relationships.STIXID | String | STIX ID associated with the CVE relationship. |
| DBotScore.Indicator | String | The indicator that was tested. |
| DBotScore.Reliability | String | Reliability rating of the threat intelligence source (e.g., A - Completely reliable, B - Usually reliable). |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Type | String | The indicator type. |
| DBotScore.Vendor | String | The vendor used to calculate the score. |
| GoogleThreatIntelligence.CVE.id | String | ID of the CVE. |
| GoogleThreatIntelligence.CVE.type | String | Data type returned (usually ‘cve’). |
| GoogleThreatIntelligence.CVE.links.self | String | API link to the detailed CVE resource. |
| GoogleThreatIntelligence.CVE.attributes.urls_count | Number | Number of URLs associated with the CVE. |
| GoogleThreatIntelligence.CVE.attributes.is_content_translated | Boolean | Indicates if the CVE content has been machine-translated. |
| GoogleThreatIntelligence.CVE.attributes.autogenerated_tags | List | Tags automatically generated for this CVE. |
| GoogleThreatIntelligence.CVE.attributes.subscribers_count | Number | Number of GTI users subscribed to updates for this CVE. |
| GoogleThreatIntelligence.CVE.attributes.risk_rating | String | GTI-assigned risk rating (e.g., Low/Medium/High/Critical). |
| GoogleThreatIntelligence.CVE.attributes.sources.title | String | Title of the external reference source. |
| GoogleThreatIntelligence.CVE.attributes.sources.name | String | Name of the external reference source. |
| GoogleThreatIntelligence.CVE.attributes.sources.url | String | URL of the external reference source. |
| GoogleThreatIntelligence.CVE.attributes.sources.source_description | String | Description of the reference source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv2_0.base_score | Number | CVSS v2 base score from the source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv2_0.temporal_score | Number | CVSS v2 temporal score from the source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv2_0.vector | String | CVSS v2 vector string. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x.base_score | Number | CVSS v3 base score from the source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x.temporal_score | Number | CVSS v3 temporal score from the source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x.vector | String | CVSS v3 vector string. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv4_x.score | Number | CVSS v4 base score from the source. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv4_x.vector | String | CVSS v4 vector string. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv4_x.threat.exploit_maturity | String | Threat metrics associated with CVSS v4. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x_translated.temporal_score | Number | Machine-translated CVSS v3 metrics. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x_translated.base_score | Number | Machine-translated CVSS v3 metrics. |
| GoogleThreatIntelligence.CVE.attributes.sources.cvss.cvssv3_x_translated.vector | String | Machine-translated CVSS v3 metrics. |
| GoogleThreatIntelligence.CVE.attributes.sources.published_date | String | Source publication date for the CVE information. |
| GoogleThreatIntelligence.CVE.attributes.sources.md5 | String | MD5 hash associated with the source content. |
| GoogleThreatIntelligence.CVE.attributes.sources.unique_id | String | Unique identifier for the source entry. |
| GoogleThreatIntelligence.CVE.attributes.name | String | Name/title of the CVE entry inside GTI. |
| GoogleThreatIntelligence.CVE.attributes.capabilities | List | Attacker capabilities related to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.technologies | List | Technologies impacted by the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.files | Number | Number of malicious files associated with the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.domains | Number | Number of domains associated with the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.ip_addresses | Number | Number of IP addresses linked to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.urls | Number | Number of URLs related to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.iocs | Number | Total indicator count associated with the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.subscribers | Number | Number of subscribers following the CVE. |
| GoogleThreatIntelligence.CVE.attributes.counters.attack_techniques | Number | Count of associated attack techniques (MITRE etc.). |
| GoogleThreatIntelligence.CVE.attributes.cve_id | String | The CVE identifier (e.g., CVE-2024-12345). |
| GoogleThreatIntelligence.CVE.attributes.domains_count | Number | Number of domains involved in CVE activity. |
| GoogleThreatIntelligence.CVE.attributes.version_history.date | Number | Date when the version entry was updated. |
| GoogleThreatIntelligence.CVE.attributes.version_history.version_notes | String | Notes about changes in CVE version history. |
| GoogleThreatIntelligence.CVE.attributes.alt_names | List | Alternate names or aliases for the CVE. |
| GoogleThreatIntelligence.CVE.attributes.recent_activity_summary | Number | Recent activity score or summary related to exploitation. |
| GoogleThreatIntelligence.CVE.attributes.exploitation.exploit_release_date | String | Date when exploit code was released. |
| GoogleThreatIntelligence.CVE.attributes.exploitation.first_exploitation | String | Date when the CVE was first exploited. |
| GoogleThreatIntelligence.CVE.attributes.exploitation.tech_details_release_date | String | Date technical details were publicly released. |
| GoogleThreatIntelligence.CVE.attributes.mitigations | List | Mitigation steps for the CVE. |
| GoogleThreatIntelligence.CVE.attributes.top_icon_md5 | List | MD5 hash of the top-listed malicious sample. |
| GoogleThreatIntelligence.CVE.attributes.description | String | Full CVE description. |
| GoogleThreatIntelligence.CVE.attributes.targeted_regions | List | Geographic regions targeted by exploitation. |
| GoogleThreatIntelligence.CVE.attributes.detection_names | List | Security vendor detection names linked to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.vendor_fix_references | List | Vendor-published fix or patch references. |
| GoogleThreatIntelligence.CVE.attributes.malware_roles | List | Malware roles (dropper, loader, etc.) related to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.collection_links | List | Related collection or reference links from GTI. |
| GoogleThreatIntelligence.CVE.attributes.source_regions_hierarchy | List | Hierarchy of affected regions sourced by GTI. |
| GoogleThreatIntelligence.CVE.attributes.references_count | Number | Number of references for the CVE. |
| GoogleThreatIntelligence.CVE.attributes.creation_date | Number | Date when the CVE entry was created in GTI. |
| GoogleThreatIntelligence.CVE.attributes.risk_factors | String | List of risk factors contributing to severity. |
| GoogleThreatIntelligence.CVE.attributes.exploit_availability | String | Availability status of exploit (e.g., Available/None). |
| GoogleThreatIntelligence.CVE.attributes.merged_actors | List | Threat actors linked to this vulnerability. |
| GoogleThreatIntelligence.CVE.attributes.first_seen_details | List | Details on when this CVE was first observed. |
| GoogleThreatIntelligence.CVE.attributes.available_mitigation | List | Available mitigations for exploitation prevention. |
| GoogleThreatIntelligence.CVE.attributes.last_modification_date | Number | Last updated timestamp for the CVE in GTI. |
| GoogleThreatIntelligence.CVE.attributes.mve_id | String | MVE (Multi-Vulnerability Event) ID for grouping related issues. |
| GoogleThreatIntelligence.CVE.attributes.tags | List | Tags associated with the CVE inside GTI. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv2_0.base_score | Number | CVSS v2 base score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv2_0.temporal_score | Number | CVSS v2 temporal score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv2_0.vector | String | CVSS v2 vector notation. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x.base_score | Number | CVSS v3 base score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x.temporal_score | Number | CVSS v3 temporal score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x.vector | String | CVSS v3 vector string. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.score | Number | CVSS v4 score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.provider_urgency | String | Provider urgency supplemental metric. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.response_effort | String | Response effort supplemental metric. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.recovery | String | Recovery supplemental metric. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.safety | String | Safety supplemental metric. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.value_density | String | Value density supplemental metric. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.supplemental.automatable | String | Indicates if exploitation can be automated. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.vector | String | CVSS v4 vector string. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv4_x.threat.exploit_maturity | String | Exploit maturity level (e.g., High/Functional/Proof of Concept). |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x_translated.base_score | Number | Machine-translated CVSS v3 base score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x_translated.temporal_score | Number | Machine-translated CVSS v3 temporal score. |
| GoogleThreatIntelligence.CVE.attributes.cvss.cvssv3_x_translated.vector | String | Machine-translated CVSS v3 vector. |
| GoogleThreatIntelligence.CVE.attributes.collection_type | String | Type of GTI collection this CVE belongs to. |
| GoogleThreatIntelligence.CVE.attributes.targeted_industries | List | Industries targeted by exploitation of this CVE. |
| GoogleThreatIntelligence.CVE.attributes.cwe.title | String | Title of the mapped CWE (root cause). |
| GoogleThreatIntelligence.CVE.attributes.cwe.id | String | CWE identifier linked to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.affected_systems | List | Systems or platforms affected by the vulnerability. |
| GoogleThreatIntelligence.CVE.attributes.tags_details | List | Detailed metadata for GTI tags. |
| GoogleThreatIntelligence.CVE.attributes.executive_summary | String | High-level summary of the vulnerability impact. |
| GoogleThreatIntelligence.CVE.attributes.priority | String | GTI-assigned priority score/category. |
| GoogleThreatIntelligence.CVE.attributes.alt_names_details | List | Additional details about alternate CVE names. |
| GoogleThreatIntelligence.CVE.attributes.targeted_regions_hierarchy | List | Hierarchy of targeted regions for exploitation. |
| GoogleThreatIntelligence.CVE.attributes.epss.percentile | Number | EPSS percentile (Exploit Prediction Scoring System). |
| GoogleThreatIntelligence.CVE.attributes.epss.score | Number | EPSS score indicating exploitation likelihood. |
| GoogleThreatIntelligence.CVE.attributes.date_of_disclosure | Number | Date when the vulnerability was publicly disclosed. |
| GoogleThreatIntelligence.CVE.attributes.days_to_report | Number | Time taken from discovery to reporting. |
| GoogleThreatIntelligence.CVE.attributes.targeted_industries_tree | List | Hierarchical breakdown of targeted industries. |
| GoogleThreatIntelligence.CVE.attributes.status | String | Current vulnerability status (e.g., Active, Resolved). |
| GoogleThreatIntelligence.CVE.attributes.intended_effects | List | Intent or malicious outcomes achieved by exploiting the CVE. |
| GoogleThreatIntelligence.CVE.attributes.private | Boolean | Whether the CVE entry is private in GTI. |
| GoogleThreatIntelligence.CVE.attributes.targeted_informations | List | Types of information targeted by attackers. |
| GoogleThreatIntelligence.CVE.attributes.ip_addresses_count | Number | Number of IPs related to the vulnerability. |
| GoogleThreatIntelligence.CVE.attributes.mati_genids_dict.report_id | String | MATI report ID linked to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.mati_genids_dict.cve_id | String | CVE ID mapped within MATI dataset. |
| GoogleThreatIntelligence.CVE.attributes.mati_genids_dict.mve_id | String | MVE ID mapped within MATI dataset. |
| GoogleThreatIntelligence.CVE.attributes.exploitation_state | String | Current exploitation state (Known Exploited / No Evidence). |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.sources | List | Source list for specific enriched fields. |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.source_url | String | URL of the field’s data source. |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.field_type | String | Type of field data (e.g., text, reference). |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.source_name | String | Name of the field’s data source provider. |
| GoogleThreatIntelligence.CVE.attributes.field_sources.field | String | Field name being sourced. |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.sources.source_names | String | Names of the sources contributing to this field. |
| GoogleThreatIntelligence.CVE.attributes.field_sources.source.sources.source_urls | List | URLs of the sources contributing to this field. |
| GoogleThreatIntelligence.CVE.attributes.exploitation_vectors | String | Methods or vectors used to exploit the vulnerability. |
| GoogleThreatIntelligence.CVE.attributes.threat_scape | String | Threat landscape and context around the CVE. |
| GoogleThreatIntelligence.CVE.attributes.operating_systems | List | Operating systems impacted by the CVE. |
| GoogleThreatIntelligence.CVE.attributes.last_seen_details | List | Last observed exploitation activity details. |
| GoogleThreatIntelligence.CVE.attributes.workarounds | List | Workarounds available to mitigate the vulnerability. |
| GoogleThreatIntelligence.CVE.attributes.motivations | List | Attacker motivations behind exploiting this CVE. |
| GoogleThreatIntelligence.CVE.attributes.predicted_risk_rating | String | AI-generated predicted risk rating. |
| GoogleThreatIntelligence.CVE.attributes.files_count | Number | Number of files linked to the CVE. |
| GoogleThreatIntelligence.CVE.attributes.exploitation_consequence | String | Possible consequences of exploitation. |
| GoogleThreatIntelligence.CVE.attributes.origin | String | Origin/source of the CVE data. |
| GoogleThreatIntelligence.CVE.attributes.aggregations | List | Aggregated threat or metadata information. |
| GoogleThreatIntelligence.CVE.context_attributes.shared_with_me | Boolean | Indicates if the CVE is shared with the user. |
| GoogleThreatIntelligence.CVE.context_attributes.role | String | User role for viewing this CVE in GTI. |
Command Example
!cve cve=CVE-2022-30190
Context Example
{
"CVE": {
"CVSS": {
"Score": 7.8,
"Vector": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:F/RL:O/RC:C"
},
"Description": "google has provided the follow description: \n*A remote code execution vulnerability exists when MSDT is called using the URL protocol from a calling application such as Word.",
"ID": "CVE-2022-30190",
"Modified": "2025-10-29T18:46:49.000Z",
"Published": "2022-05-27T00:00:00.000Z",
"Relationships": [
{
"EntityA": "CVE-2022-30190",
"EntityAType": "CVE",
"EntityB": "test_md5_001",
"EntityBType": "File",
"Relationship": "related-to"
},
{
"EntityA": "CVE-2022-30190",
"EntityAType": "CVE",
"EntityB": "test_md5_002",
"EntityBType": "File",
"Relationship": "related-to"
}
],
"STIXID": "CVE-2022-30190",
"Tags": [
"observed_in_the_wild",
"has_exploits",
"was_zero_day",
"media_attention"
]
},
"DBotScore": {
"Indicator": "CVE-2022-30190",
"Reliability": "C - Fairly reliable",
"Score": 2,
"Type": "cve",
"Vendor": "GoogleThreatIntelligence"
},
"GoogleThreatIntelligence": {
"CVE": {
"id": "vulnerability--cve-2022-30190",
"type": "collection",
"links": {
"self": "https://www.virustotal.com/api/v3/collections/vulnerability--cve-2022-30190"
},
"attributes": {
"description": "google has provided the following description: \n*A remote code execution vulnerability exists when MSDT is called using the URL protocol from a calling application such as Word.",
"risk_factors": [
"User Interaction Required"
],
"predicted_risk_rating": "",
"exploitation_state": "Confirmed",
"version_history": [
{
"date": 1761763609,
"version_notes": [
"cisa_known_exploited.ransomware_use: Unknown -> Known"
]
}
],
"recent_activity_relative_change": 0.0714285714285714,
"cisa_known_exploited": {
"added_date": 1655164800,
"due_date": 1656979200,
"ransomware_use": "Known"
},
"origin": "Google Threat Intelligence",
"exploitation": {
"tech_details_release_date": 1689120000,
"first_exploitation": 1651276800,
"exploit_release_date": 1653868800
},
"available_mitigation": [
"Workaround",
"Patch"
],
"alt_names_details": [
{
"value": "Follina",
"confidence": "possible"
}
],
"mve_id": "MVE-2022-4552",
"tags": [
"observed_in_the_wild",
"has_exploits",
"was_zero_day",
"media_attention"
],
"executive_summary": "* An Improper Control of Generation of Code ('Code Injection') vulnerability exists that, when exploited, allows a remote attacker to execute arbitrary code.",
"autogenerated_tags": [
"cve-2021-40444"
],
"workarounds": [
"<p>google recommends disabling the MSDT URL Protocol as a method to mitigate the chance of exploitation. For more information see their advisory."
],
"date_of_disclosure": 1653609600,
"vendor_fix_references": [
{
"url": "https://portal.msrc.google.com/en-US/security-guidance/advisory/CVE-2022-30190",
"name": "google Corp.",
"published_date": 1653894000,
"title": "google Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability (CVE-2022-30190)"
}
],
"cpes": [
{
"start_cpe": {
"version": "R2",
"uri": "cpe:2.3:o:google:windows_server_2012:r2:*:*:*:*:*:*:*",
"product": "Windows Server 2012 (OS)",
"vendor": "google"
},
"start_rel": "="
}
],
"field_sources": [
{
"field": "cvss.cvssv3_x",
"source": {
"field_type": "Ranked",
"source_name": "Google Threat Intelligence Group (GTIG)",
"source_url": ""
}
}
],
"ip_addresses_count": 0,
"private": true,
"cve_id": "CVE-2022-30190",
"sources": [
{
"md5": "test_md5_001",
"url": "https://github.com/cisagov/vulnrichment/blob/develop/2022/30xxx/test_CVE_2022_30190.json",
"name": "Cybersecurity and Infrastructure Security Agency (CISA)",
"published_date": 1654114217,
"title": "google Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability",
"cvss": {
"cvssv3_x": {
"base_score": 7.8,
"vector": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C"
}
}
},
{
"md5": "test_md5_002",
"url": "https://github.com/CVEProject/cvelistV5/blob/main/cves/2022/30xxx/test_CVE_2022_30190.json",
"name": "Mitre Corporation",
"published_date": 1654114217,
"title": "google Windows Support Diagnostic Tool (MSDT) Remote Code Execution Vulnerability",
"cvss": {
"cvssv3_x": {
"base_score": 7.8,
"vector": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C"
}
}
}
],
"alt_names": [
"Follina"
],
"exploitation_consequence": "Code Execution",
"name": "CVE-2022-30190",
"tags_details": [
{
"value": "has_exploits",
"confidence": "possible"
}
],
"analysis": "An attacker could exploit this vulnerability to execute arbitrary code. An attacker would need to create a specially url calling MSDT and cause a user to open it on a vulnerable system.",
"summary_stats": {
"first_submission_date": {
"min": 0,
"max": 1746722000,
"avg": 733834342.875
},
"last_submission_date": {
"min": 0,
"max": 1746722000,
"avg": 735827136.25
},
"files_detections": {
"min": 0,
"max": 48,
"avg": 16.5625
}
},
"files_count": 18,
"creation_date": 1653927632,
"exploitation_vectors": [
"File Share",
"Web",
"Email",
"Malicious File"
],
"recent_activity_summary": [],
"days_to_report": 3,
"last_modification_date": 1761763609,
"is_content_translated": false,
"risk_rating": "MEDIUM",
"exploit_availability": "Publicly Available",
"vulnerable_products": "",
"references_count": 0,
"urls_count": 0,
"days_to_patch": 3,
"collection_type": "vulnerability",
"counters": {
"files": 18,
"domains": 0,
"ip_addresses": 0,
"urls": 0,
"iocs": 18,
"subscribers": 0,
"attack_techniques": 0
},
"status": "COMPUTED",
"epss": {
"score": 0.93187,
"percentile": 0.99784
},
"mati_genids_dict": {
"mve_id": "vulnerability--test_mve_id",
"cve_id": "vulnerability--test_cve_id",
"report_id": "report--test_report_id"
},
"cvss": {
"cvssv3_x": {
"base_score": 7.8,
"vector": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:F/RL:O/RC:C",
"temporal_score": 7.2
},
"cvssv2_0": {
"base_score": 6.8,
"vector": "AV:N/AC:M/Au:N/C:P/I:P/A:P/E:F/RL:OF/RC:C",
"temporal_score": 5.6
}
},
"domains_count": 0,
"subscribers_count": 0,
"priority": "P1",
"cwe": {
"title": "Improper Control of Generation of Code ('Code Injection')",
"id": "CWE-94"
}
},
"context_attributes": {
"shared_with_me": false,
"role": "viewer"
}
}
}
}
Human Readable Output
CVE Information: CVE-2022-30190
CVE ID Risk Rating Priority Exploitation State Exploit Availability CVSS v3.x Score CVSS v4.x Score CVSS v3.x Vector Date Of Disclosure Creation Date Last Modified Sources Description Related Files Related Domains Related IPs Related URLs Executive Summary CVE-2022-30190 MEDIUM P1 Confirmed Publicly Available 7.8 0 CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:F/RL:O/RC:C 2022-05-27T00:00:00.000Z 2022-05-30T16:20:32.000Z 2025-10-29T18:46:49.000Z 2 google has provided the following description:
*A remote code execution vulnerability exists when MSDT is called using the URL protocol from a calling application such as Word.2 0 0 0 * An Improper Control of Generation of Code (‘Code Injection’) vulnerability exists that, when exploited, allows a remote attacker to execute arbitrary code.
url-scan
Scans a specified URL. Use the gti-analysis-get command to get the scan results.
Base Command
url-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to scan. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Submission.Type | String | The type of the submission (analysis). |
| GoogleThreatIntelligence.Submission.id | String | The ID of the submission. |
| GoogleThreatIntelligence.Submission.hash | String | The indicator sent to rescan. |
Command Example
!url-scan url=https://example.com
Context Example
{
"GoogleThreatIntelligence": {
"Submission": {
"id": "u-0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7-1617088890",
"type": "analysis",
"url": "https://example.com"
}
},
"gtiScanID": "u-0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7-1617088890"
}
Human Readable Output
New url submission
id url u-0f115db062b7c0dd030b16878c99dea5c354b49dc37b38eb8846179c7783e9d7-1617088890 https://example.com
gti-comments-add
Adds comments to files and URLs.
Base Command
gti-comments-add
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, orSHA256), Domain, URL or IP on which you’re commenting on. If not supplied, will try to determine if it’s a hash or a url. | Required |
| resource_type | The type of the resource on which you’re commenting. Possible values are: ip, url, domain, hash. | Optional |
| comment | The actual review that you can tag by using the “#” twitter-like syntax, for example, #disinfection #zbot, and reference users using the “@” syntax, for example, @GoogleThreatIntelligenceTeam. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Comments.comments.attributes.date | Number | The date of the comment in epoch format. |
| GoogleThreatIntelligence.Comments.comments.attributes.text | String | The text of the comment. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.positive | Number | Number of positive votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.abuse | Number | Number of abuse votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.negative | Number | Number of negative votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.html | String | The HTML content. |
| GoogleThreatIntelligence.Comments.comments.type | String | The type of the comment. |
| GoogleThreatIntelligence.Comments.comments.id | String | ID of the comment. |
| GoogleThreatIntelligence.Comments.comments.links.self | String | Link to the request. |
Command Example
!gti-comments-add resource=paloaltonetworks.com resource_type=domain comment="this is a comment"
Context Example
{
"GoogleThreatIntelligence": {
"Comments": {
"comments": {
"attributes": {
"date": 1617088894,
"html": "this is a comment",
"tags": [],
"text": "this is a comment",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "d-paloaltonetworks.com-e757b16b",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/d-paloaltonetworks.com-e757b16b"
},
"type": "comment"
}
}
}
}
Human Readable Output
Comment has been added
Date Text Positive Votes Abuse Votes Negative Votes 2021-03-30 07:21:34Z this is a comment 0 0 0
gti-file-scan-upload-url
Premium API. Get a special URL for files larger than 32 MB.
Base Command
gti-file-scan-upload-url
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.FileUploadURL | unknown | The special upload URL for large files. |
Command Example
#### Context Example
```json
{
"GoogleThreatIntelligence": {
"FileUploadURL": "https://www.virustotal.com/_ah/upload/**upload-hash**"
},
"gtiUploadURL": "https://www.virustotal.com/_ah/upload/**upload-hash**"
}
Human Readable Output
New upload url acquired
Upload url https://www.virustotal.com/_ah/upload/**upload-hash**/
gti-comments-delete
Delete a comment.
Base Command
gti-comments-delete
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Comment ID. | Required |
Context Output
There is no context output for this command.
Command Example
!gti-comments-delete id=d-paloaltonetworks.com-7886a33c
Human Readable Output
Comment d-paloaltonetworks.com-7886a33c has been deleted!
gti-comments-get
Retrieves comments for a given resource.
Base Command
gti-comments-get
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, orSHA256), Domain, URL or IP on which you’re commenting on. If not supplied, will try to determine if it’s a hash or a url. | Required |
| resource_type | The type of the resource on which you’re commenting. If not supplied, will determine if it’s a url or a file. Possible values are: ip, url, domain, file. | Optional |
| limit | Maximum comments to fetch. Default is 10. | Optional |
| before | Fetch only comments before the given time. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Comments.id | String | ID that contains the comment (the given hash, domain, url, or ip). |
| GoogleThreatIntelligence.Comments.comments.attributes.date | Number | The date of the comment in epoch format. |
| GoogleThreatIntelligence.Comments.comments.attributes.text | String | The text of the comment. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.positive | Number | Number of positive votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.abuse | Number | Number of abuse votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.negative | Number | Number of negative votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.html | String | The HTML content. |
| GoogleThreatIntelligence.Comments.comments.type | String | The type of the comment. |
| GoogleThreatIntelligence.Comments.comments.id | String | ID of the commented. |
| GoogleThreatIntelligence.Comments.comments.links.self | String | Link to the request |
Command Example
!gti-comments-get resource=https://paloaltonetworks.com
Context Example
{
"GoogleThreatIntelligence": {
"Comments": {
"comments": [
{
"attributes": {
"date": 1616325673,
"html": "another comment",
"tags": [],
"text": "another comment",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-fe2d6a9e",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-fe2d6a9e"
},
"type": "comment"
},
{
"attributes": {
"date": 1616325673,
"html": "another comment",
"tags": [],
"text": "another comment",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-d63782a9",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-d63782a9"
},
"type": "comment"
},
{
"attributes": {
"date": 1616313101,
"html": "a new comment",
"tags": [],
"text": "a new comment",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-97a331a3",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-97a331a3"
},
"type": "comment"
},
{
"attributes": {
"date": 1616313067,
"html": "a comment",
"tags": [],
"text": "a comment",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-ae0de9fc",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/u-c5fad1f7084153e328563fbacdb07a9ad6428dc3f0a88e756266efb7c0553d9d-ae0de9fc"
},
"type": "comment"
}
],
"indicator": "https://paloaltonetworks.com"
}
}
}
Human Readable Output
GoogleThreatIntelligence comments of url: “https://paloaltonetworks.com”
Date Text Positive Votes Abuse Votes Negative Votes 2021-03-21 11:21:13Z another comment 0 0 0 2021-03-21 11:21:13Z another comment 0 0 0 2021-03-21 07:51:41Z a new comment 0 0 0 2021-03-21 07:51:07Z a comment 0 0 0
gti-comments-get-by-id
Retrieves a comment by comment ID.
Base Command
gti-comments-get-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The comment’s ID. Can be retrieved using the gti-comments-get command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Comments.comments.id | String | ID of the comment. |
| GoogleThreatIntelligence.Comments.comments.attributes.date | Number | The date of the comment in epoch format. |
| GoogleThreatIntelligence.Comments.comments.attributes.text | String | The text of the comment. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.positive | Number | Number of positive votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.abuse | Number | Number of abuse votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.votes.negative | Number | Number of negative votes. |
| GoogleThreatIntelligence.Comments.comments.attributes.html | String | The HTML content. |
| GoogleThreatIntelligence.Comments.comments.type | String | The type of the comment. |
| GoogleThreatIntelligence.Comments.comments.links.self | String | Link to the request. |
Command Example
!gti-comments-get-by-id id=d-paloaltonetworks.com-64591897
Context Example
{
"GoogleThreatIntelligence": {
"Comments": {
"comments": {
"attributes": {
"date": 1615195751,
"html": "a new comment!",
"tags": [],
"text": "a new comment!",
"votes": {
"abuse": 0,
"negative": 0,
"positive": 0
}
},
"id": "d-paloaltonetworks.com-64591897",
"links": {
"self": "https://www.virustotal.com/api/v3/comments/d-paloaltonetworks.com-64591897"
},
"type": "comment"
}
}
}
}
Human Readable Output
Comment of ID d-paloaltonetworks.com-64591897
Date Text Positive Votes Abuse Votes Negative Votes 2021-03-08 09:29:11Z a new comment! 0 0 0
gti-search
Search for an indicator in GoogleThreatIntelligence.
Base Command
gti-search
Input
| Argument Name | Description | Required |
|---|---|---|
| query | This endpoint searches any of the following: A file hash, URL, domain, IP address, tag comments. | Required |
| extended_data | Whether to return extended data (last_analysis_results). Possible values are: true, false. | Optional |
| limit | Maximum number of results to fetch. Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.SearchResults.attributes.last_analysis_stats.harmless | Number | Number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.SearchResults.attributes.last_analysis_stats.malicious | Number | Number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.SearchResults.attributes.last_analysis_stats.suspicious | Number | Number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.SearchResults.attributes.last_analysis_stats.undetected | Number | Number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.SearchResults.attributes.last_analysis_stats.timeout | Number | Number of engines that timed out. |
| GoogleThreatIntelligence.SearchResults.attributes.reputation | Number | The indicator’s reputation |
| GoogleThreatIntelligence.SearchResults.attributes.last_modification_date | Number | The last modification date in epoch format. |
| GoogleThreatIntelligence.SearchResults.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.SearchResults.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.SearchResults.type | String | The type of the indicator (ip, domain, url, file). |
| GoogleThreatIntelligence.SearchResults.id | String | ID of the indicator. |
| GoogleThreatIntelligence.SearchResults.links.self | String | Link to the response. |
Command Example
!gti-search query=paloaltonetworks.com
Context Example
{
"GoogleThreatIntelligence": {
"SearchResults": {
"attributes": {
"categories": {
"BitDefender": "marketing",
"Forcepoint ThreatSeeker": "information technology",
"alphaMountain.ai": "Business/Economy, Information Technology",
"sophos": "information technology"
},
"creation_date": 1108953730,
"favicon": {
"dhash": "02e9ecb69ac869a8",
"raw_md5": "920c3c89139c32d356fa4b8b61616f37"
},
"jarm": "29d3fd00029d29d00042d43d00041d598ac0c1012db967bb1ad0ff2491b3ae",
"last_analysis_stats": {
"harmless": 75,
"malicious": 0,
"suspicious": 0,
"timeout": 0,
"undetected": 7
},
"last_dns_records": [
{
"ttl": 14399,
"type": "TXT",
"value": "atlassian-domain-verification=WeW32v7AwYQEviMzlNjYyXNMUngcnmIMtNZKJ69TuQUoda5T6DFFV/A6rRvOzwvs"
}
],
"last_dns_records_date": 1616986415,
"last_https_certificate": {
"cert_signature": {
"signature": "signature",
"signature_algorithm": "sha256RSA"
},
"extensions": {
"**exten**": "0482016a0168007600a4b90990b418581487bb13a2cc67700a3c359804f91bdf",
"CA": true,
"authority_key_identifier": {
"keyid": "40c2bd278ecc348330a233d7fb6cb3f0b42c80ce"
},
"ca_information_access": {
"CA Issuers": "http://certificates.example.com/repository/gdig2.crt",
"OCSP": "http://ocsp.example.com/"
},
"certificate_policies": [
"**policy**"
],
"crl_distribution_points": [
"http://example.com/gdig2s1-1677.crl"
],
"extended_key_usage": [
"serverAuth",
"clientAuth"
],
"key_usage": [
"ff"
],
"subject_alternative_name": [
"www.paloaltonetworks.com"
],
"subject_key_identifier": "ed89d4b918aab2968bd1dfde421a179c51445be0",
"tags": []
},
"issuer": {
"C": "US",
"CN": "Go Daddy Secure Certificate Authority - G2",
"L": "Scottsdale",
"O": "example.com, Inc.",
"OU": "http://certs.example.com/repository/",
"ST": "Arizona"
},
"public_key": {
"algorithm": "RSA",
"rsa": {
"exponent": "010001",
"key_size": 2048,
"modulus": "modulus"
}
},
"serial_number": "f5fa379466d9884a",
"signature_algorithm": "sha256RSA",
"size": 1963,
"subject": {
"CN": "www.paloaltonetworks.com",
"OU": "Domain Control Validated"
},
"tags": [],
"thumbprint": "0296c20e3a4a607b8d9e2af86155cde04594535e",
"thumbprint_sha256": "17bb7bda507abc602bdf1b160d7f51edaccac39fd34f8dab1e793c3612cfc8c2",
"validity": {
"not_after": "2022-01-27 16:52:24",
"not_before": "2020-01-27 16:52:24"
},
"version": "V3"
},
"last_https_certificate_date": 1616986415,
"last_modification_date": 1617084294,
"last_update_date": 1594825871,
"popularity_ranks": {
"Alexa": {
"rank": 32577,
"timestamp": 1617032161
}
},
"registrar": "MarkMonitor Inc.",
"reputation": 0,
"tags": [],
"total_votes": {
"harmless": 0,
"malicious": 0
},
"whois": "whois string",
"whois_date": 1615321176
},
"id": "paloaltonetworks.com",
"links": {
"self": "https://www.virustotal.com/api/v3/domains/paloaltonetworks.com"
},
"type": "domain"
}
}
}
Human Readable Output
Search result of query paloaltonetworks.com
Categories CreationDate LastAnalysisStats Forcepoint ThreatSeeker: information technology
sophos: information technology
BitDefender: marketing
alphaMountain.ai: Business/Economy, Information Technology1108953730 harmless: 75
malicious: 0
suspicious: 0
undetected: 7
timeout: 01615321176
gti-file-sandbox-report
Retrieves a behavioral relationship of the given file hash.
Base Command
gti-file-sandbox-report
Input
| Argument Name | Description | Required |
|---|---|---|
| file | Hash of the file to query. Supports MD5, SHA1, and SHA256. | Required |
| limit | Maximum number of results to fetch. Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| SandboxReport.attributes.analysis_date | Number | The date of the analysis in epoch format. |
| SandboxReport.attributes.behash | String | Behash of the attribute. |
| SandboxReport.attributes.command_executions | String | Which command were executed. |
| SandboxReport.attributes.dns_lookups.hostname | String | Host names found in the lookup. |
| SandboxReport.attributes.dns_lookups.resolved_ips | String | The IPs that were resolved. |
| SandboxReport.attributes.files_attribute_changed | String | The file attributes that were changed. |
| SandboxReport.attributes.has_html_report | Boolean | Whether there is an HTML report. |
| SandboxReport.attributes.has_pcap | Boolean | Whether the IP has a PCAP file. |
| SandboxReport.attributes.http_conversations.request_method | String | The request method of the HTTP conversation. |
| SandboxReport.attributes.http_conversations.response_headers.Cache-Control | String | The cache-control method of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Connection | String | The connection of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Content-Length | String | THe Content-Length of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Content-Type | String | The Content-Type of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Pragma | String | The pragma of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Server | String | The server of the response header. |
| SandboxReport.attributes.http_conversations.response_headers.Status-Line | String | The Status-Line of the response header. |
| SandboxReport.attributes.http_conversations.response_status_code | Number | The response status code. |
| SandboxReport.attributes.http_conversations.url | String | The conversation URL. |
| SandboxReport.attributes.last_modification_date | Number | Last modified data in epoch format. |
| SandboxReport.attributes.modules_loaded | String | Loaded modules. |
| SandboxReport.attributes.mutexes_created | String | The mutexes that were created. |
| SandboxReport.attributes.mutexes_opened | String | The mutexes that were opened. |
| SandboxReport.attributes.processes_created | String | The processes that were created. |
| SandboxReport.attributes.processes_tree.name | String | The name of the process tree. |
| SandboxReport.attributes.processes_tree.process_id | String | The ID of the process. |
| SandboxReport.attributes.registry_keys_deleted | String | Deleted registry keys. |
| SandboxReport.attributes.registry_keys_set.key | String | Key of the registry key. |
| SandboxReport.attributes.registry_keys_set.value | String | Value of the registry key. |
| SandboxReport.attributes.sandbox_name | String | The name of the sandbox. |
| SandboxReport.attributes.services_started | String | The services that were started. |
| SandboxReport.attributes.verdicts | String | The verdicts. |
| SandboxReport.id | String | The IP analyzed. |
| SandboxReport.links.self | String | Link to the response. |
| SandboxReport.attributes.files_dropped.path | String | Path of the file dropped. |
| SandboxReport.attributes.files_dropped.sha256 | String | SHA-256 hash of the dropped files. |
| SandboxReport.attributes.files_opened | String | The files that were opened. |
| SandboxReport.attributes.files_written | String | The files that were written. |
| SandboxReport.attributes.ip_traffic.destination_ip | String | Destination IP in the traffic. |
| SandboxReport.attributes.ip_traffic.destination_port | Number | Destination port in the traffic. |
| SandboxReport.attributes.ip_traffic.transport_layer_protocol | String | Transport layer protocol in the traffic. |
| SandboxReport.attributes.registry_keys_opened | String | The registry keys that were opened. |
| SandboxReport.attributes.tags | String | The tags of the DNS data. |
| SandboxReport.attributes.files_copied.destination | String | Destination of the files copied. |
| SandboxReport.attributes.files_copied.source | String | Source of the files copied. |
| SandboxReport.attributes.permissions_requested | String | The permissions that where requested. |
| SandboxReport.attributes.processes_injected | String | The processes that were injected. |
| SandboxReport.attributes.processes_terminated | String | The processes that were terminated. |
| SandboxReport.attributes.processes_tree.children.name | String | The name of the children of the process. |
| SandboxReport.attributes.processes_tree.children.process_id | String | The ID of the children of the process. |
| SandboxReport.attributes.services_opened | String | The services that were opened. |
| SandboxReport.attributes.text_highlighted | String | The text that was highlighted. |
| SandboxReport.attributes.calls_highlighted | String | The calls that were highlighted. |
| SandboxReport.attributes.processes_tree.children.time_offset | Number | The time offset of the children in the process. |
| SandboxReport.links.self | String | The link to the response. |
| SandboxReport.meta.count | Number | The number of objects that were found in the attributes. |
Command Example
!gti-file-sandbox-report file=2b294b3499d1cce794badffc959b7618
Context Example
{
"GoogleThreatIntelligence": {
"SandboxReport": [
{
"attributes": {
"analysis_date": 1558429832,
"behash": "079386becc949a2aafdcd2c6042cf0a9",
"command_executions": [
"C:\\DOCUME~1\\Miller\\LOCALS~1\\Temp\\Win32.AgentTesla.exe",
],
"dns_lookups": [
{
"hostname": "checkip.dyndns.org",
"resolved_ips": [
"**ip**"
]
},
{
"hostname": "checkip.dyndns.org",
"resolved_ips": [
"**ip**"
]
}
],
"files_attribute_changed": [
"C:\\Documents and Settings\\Miller\\Local Settings\\Temp\\xws\\xws.exe"
],
"has_html_report": false,
"has_pcap": false,
"http_conversations": [
{
"request_method": "GET",
"response_headers": {
"Cache-Control": "no-cache",
"Connection": "close",
"Content-Length": "107",
"Content-Type": "text/html",
"Pragma": "no-cache",
"Server": "DynDNS-CheckIP/1.0.1",
"Status-Line": "HTTP/1.1 200"
},
"response_status_code": 200,
"url": "http://checkip.dyndns.org/"
},
{
"request_method": "GET",
"response_headers": {
"Cache-Control": "no-cache",
"Connection": "close",
"Content-Length": "105",
"Content-Type": "text/html",
"Pragma": "no-cache",
"Server": "DynDNS-CheckIP/1.0.1",
"Status-Line": "HTTP/1.1 200"
},
"response_status_code": 200,
"url": "http://checkip.dyndns.org/"
}
],
"last_modification_date": 1588377117,
"modules_loaded": [
"c:\\windows\\system32\\imm32.dll"
],
"mutexes_created": [
"CTF.Compart.MutexDefaultS-1-5-21-1229272821-1563985344-1801674531-1003"
],
"mutexes_opened": [
"ShimCacheMutex"
],
"processes_created": [
"C:\\DOCUME~1\\Miller\\LOCALS~1\\Temp\\Win32.AgentTesla.exe"
],
"processes_tree": [
{
"name": "C:\\DOCUME~1\\Miller\\LOCALS~1\\Temp\\Win32.AgentTesla.exe",
"process_id": "272"
}
],
"registry_keys_deleted": [
"HKU\\S-1-5-21-3712457824-2419000099-45725732-1005\\SOFTWARE\\CLASSES\\MSCFILE\\SHELL\\OPEN\\COMMAND"
],
"registry_keys_set": [
{
"key": "HKU\\S-1-5-21-1229272821-1563985344-1801674531-1003\\SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN",
"value": "xws"
}
],
"sandbox_name": "Lastline",
"services_started": [
"RASMAN",
"WinHttpAutoProxySvc"
],
"verdicts": [
"MALWARE",
"TROJAN"
]
},
"id": "699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_Lastline",
"links": {
"self": "https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_Lastline"
},
"type": "file_behaviour"
},
{
"attributes": {
"analysis_date": 1561405459,
"files_dropped": [
{
"path": "\\Users\\Petra\\AppData\\Local\\Temp\\xws\\xws.exe",
"sha256": "699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3"
}
],
"files_opened": [
"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\config\\machine.config"
],
"files_written": [
"C:\\Users\\<USER>\\AppData\\Local\\Temp\\xws\\xws.exe"
],
"has_html_report": false,
"has_pcap": false,
"ip_traffic": [
{
"destination_ip": "**ip**",
"destination_port": 80,
"transport_layer_protocol": "TCP"
}
],
"last_modification_date": 1563272815,
"processes_tree": [
{
"name": "1526312897-2b294b349.pe32",
"process_id": "2624"
}
],
"registry_keys_opened": [
"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\OLE",
],
"registry_keys_set": [
{
"key": "\\REGISTRY\\USER\\S-1-5-21-1119815420-2032815650-2779196966-1000\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
"value": "xws"
}
],
"sandbox_name": "SNDBOX",
"tags": [
"PERSISTENCE"
]
},
"id": "699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_SNDBOX",
"links": {
"self": "https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_SNDBOX"
},
"type": "file_behaviour"
},
{
"attributes": {
"analysis_date": 1601545446,
"behash": "7617055bb3994dea99c19877fd7ec55a",
"command_executions": [
"\"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\EB93A6\\996E.exe\"",
"Shutdown -r -t 5"
],
"dns_lookups": [
{
"hostname": "checkip.dyndns.org"
}
],
"files_copied": [
{
"destination": "C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\xws\\xws.exe ",
"source": "C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\EB93A6\\996E.exe "
}
],
"files_opened": [
"C:\\WINDOWS\\system32\\winime32.dll"
],
"files_written": [
"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\xws\\xws.exe",
"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\Ktx.exe"
],
"has_html_report": true,
"has_pcap": false,
"last_modification_date": 1601545448,
"modules_loaded": [
"ADVAPI32.dll"
],
"mutexes_created": [
"CTF.LBES.MutexDefaultS-1-5-21-1482476501-1645522239-1417001333-500",
],
"mutexes_opened": [
"ShimCacheMutex"
],
"permissions_requested": [
"SE_DEBUG_PRIVILEGE"
],
"processes_created": [
"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\EB93A6\\996E.exe"
],
"processes_injected": [
"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\EB93A6\\996E.exe"
],
"processes_terminated": [
"C:\\Documents and Settings\\Administrator\\Local Settings\\Temp\\EB93A6\\996E.exe"
],
"processes_tree": [
{
"children": [
{
"children": [
{
"name": "shutdown.exe",
"process_id": "2336"
}
],
"name": "****.exe",
"process_id": "1024"
}
],
"name": "****.exe",
"process_id": "628"
}
],
"registry_keys_opened": [
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\996E.exe"
],
"registry_keys_set": [
{
"key": "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\xws",
"value": "C:\\Users\\<USER>\\AppData\\Local\\Temp\\xws\\xws.exe"
}
],
"sandbox_name": "GoogleThreatIntelligence Jujubox",
"tags": [
"DIRECT_CPU_CLOCK_ACCESS"
],
"text_highlighted": [
"C:\\Windows\\system32\\cmd.exe"
]
},
"id": "699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_GoogleThreatIntelligence Jujubox",
"links": {
"self": "https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_GoogleThreatIntelligence Jujubox"
},
"type": "file_behaviour"
}
]
}
}
Human Readable Output
Sandbox Reports for file hash: 2b294b3499d1cce794badffc959b7618
AnalysisDate LastModificationDate SandboxName Link 1558429832 1588377117 Lastline https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_Lastline 1561405459 1563272815 SNDBOX https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_SNDBOX 1601545446 1601545448 Tencent HABO https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_Tencent HABO 1592373137 1592373137 GoogleThreatIntelligence Jujubox https://www.virustotal.com/api/v3/file_behaviours/699ec052ecc898bdbdafea0027c4ab44c3d01ae011c17745dd2b7fbddaa077f3_GoogleThreatIntelligence Jujubox
gti-passive-dns-data
Returns passive DNS records by indicator.
Base Command
gti-passive-dns-data
Input
| Argument Name | Description | Required |
|---|---|---|
| id | IP or domain for which to get its DNS data. | Optional |
| ip | IP for which to get its DNS data. | Optional |
| domain | Domain for which to get its DNS data. | Optional |
| limit | Maximum number of results to fetch. Default is 10. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.PassiveDNS.attributes.date | Number | Date of the DNS analysis in epoch format. |
| GoogleThreatIntelligence.PassiveDNS.attributes.host_name | String | The DNS host name. |
| GoogleThreatIntelligence.PassiveDNS.attributes.ip_address | String | The DNS IP address. |
| GoogleThreatIntelligence.PassiveDNS.attributes.resolver | String | The name of the resolver. |
| GoogleThreatIntelligence.PassiveDNS.id | String | The ID of the resolution. |
| GoogleThreatIntelligence.PassiveDNS.links.self | String | The link to the resolution. |
| GoogleThreatIntelligence.PassiveDNS.type | String | The type of the resolution. |
Command Example
!gti-passive-dns-data ip=1.1.1.1
Context Example
{
"GoogleThreatIntelligence": {
"PassiveDNS": [
{
"attributes": {
"date": 1617085962,
"host_name": "muhaha.xyz",
"ip_address": "1.1.1.1",
"resolver": "GoogleThreatIntelligence"
},
"id": "1.1.1.1muhaha.xyz",
"links": {
"self": "https://www.virustotal.com/api/v3/resolutions/1.1.1.1muhaha.xyz"
},
"type": "resolution"
}
]
}
}
Human Readable Output
Passive DNS data for IP 1.1.1.1
Id Date HostName IpAddress Resolver 1.1.1.1muhaha.xyz 1617085962 muhaha.xyz 1.1.1.1 GoogleThreatIntelligence
gti-analysis-get
Retrieves resolutions of the given IP.
Base Command
gti-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the analysis (from file-scan, file-rescan, or url-scan). | Required |
| extended_data | Whether to return extended data (last_analysis_results). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.harmless | Number | Number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.malicious | Number | Number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.suspicious | Number | Number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.timeout | Number | he number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.undetected | Number | Number of engines the found the indicator to be undetected. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (analysis). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha256 | String | SHA-256 hash of the file (if it is a file). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha1 | String | SHA-1 hash of the file (if it is a file). |
| GoogleThreatIntelligence.Analysis.meta.file_info.md5 | String | MD5 hash of the file (if it is a file). |
| GoogleThreatIntelligence.Analysis.meta.file_info.name | unknown | Name of the file (if it is a file). |
| GoogleThreatIntelligence.Analysis.meta.file_info.size | String | Size of the file (if it is a file). |
| GoogleThreatIntelligence.Analysis.meta.url_info.id | String | ID of the url (if it is a URL). |
| GoogleThreatIntelligence.Analysis.meta.url_info.url | String | The URL (if it is a URL). |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
Command Example
!gti-analysis-get id=u-20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853-1613980758
Context Example
{
"GoogleThreatIntelligence": {
"Analysis": {
"data": {
"attributes": {
"date": 1613980758,
"results": {
"ADMINUSLabs": {
"category": "harmless",
"engine_name": "ADMINUSLabs",
"method": "blacklist",
"result": "clean"
}
},
"stats": {
"harmless": 69,
"malicious": 7,
"suspicious": 0,
"timeout": 0,
"undetected": 7
},
"status": "completed"
},
"id": "u-20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853-1613980758",
"links": {
"self": "https://www.virustotal.com/api/v3/analyses/u-20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853-1613980758"
},
"type": "analysis"
},
"id": "u-20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853-1613980758",
"meta": {
"url_info": {
"id": "20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853"
}
}
}
}
}
Human Readable Output
Analysis results
Id Stats Status u-20694f234fbac92b1dcc16f424aa1c85e9dd7af75b360745df6484dcae410853-1613980758 harmless: 69
malicious: 7
suspicious: 0
undetected: 7
timeout: 0completed
gti-file-sigma-analysis
Retrieves result of the last Sigma analysis.
Base Command
gti-file-sigma-analysis
Input
| Argument Name | Description | Required |
|---|---|---|
| file | File hash (md5, sha1, sha256). | Required |
| only_stats | Print only Sigma analysis summary stats. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.last_modification_date | Number | Date of the last update in epoch format. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.analysis_date | Number | Date of the last update in epoch format. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.match_context | String | Matched strings from the log file. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_author | String | Rule authors separated by commas. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_description | String | Brief summary about what the rule detects. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_id | String | Rule ID in GoogleThreatIntelligence’s database. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_level | String | Rule severity. Can be “low”, “medium”, “high” or “critical”. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_source | String | Ruleset where the rule belongs. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.rule_matches.rule_title | String | Rule title. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.severity_stats.critical | Number | Number of matched rules having a “critical” severity. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.severity_stats.high | Number | Number of matched rules having a “high” severity. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.severity_stats.low | Number | Number of matched rules having a “low” severity. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.severity_stats.medium | Number | Number of matched rules having a “medium” severity. |
| GoogleThreatIntelligence.SigmaAnalysis.data.attributes.stats.source_severity_stats | unknown | Same as severity_stats but grouping stats by ruleset. Keys are ruleset names as string and values are stats in a dictionary. |
| GoogleThreatIntelligence.SigmaAnalysis.data.id | String | ID of the analysis. |
Command Example
!gti-file-sigma-analysis file=f912398cb3542ab704fe917af4a60d4feee21ac577535b10453170f10c6fd6de
Context Example
{
"GoogleThreatIntelligence": {
"SigmaAnalysis": {
"meta": {
"count": 1
},
"data": {
"attributes": {
"last_modification_date": 1650970667,
"analysis_date": 1650968852,
"rule_matches": [
{
"match_context": "$EventID: '1117'",
"rule_level": "high",
"rule_description": "Detects all actions taken by Windows Defender malware detection engines",
"rule_source": "Sigma Integrated Rule Set (GitHub)",
"rule_title": "Windows Defender Threat Detected",
"rule_id": "cf90b923dcb2c8192e6651425886607684aac6680bf25b20c39ae3f8743aebf1",
"rule_author": "Ján Trenčanský"
},
{
"match_context": "$EventID: '2002'",
"rule_level": "low",
"rule_description": "Setting have been change in Windows Firewall",
"rule_source": "Sigma Integrated Rule Set (GitHub)",
"rule_title": "Setting Change in Windows Firewall with Advanced Security",
"rule_id": "693c36f61ac022fd66354b440464f490058c22b984ba1bef05ca246aba210ed1",
"rule_author": "frack113"
}
],
"source_severity_stats": {
"Sigma Integrated Rule Set (GitHub)": {
"high": 1,
"medium": 0,
"critical": 0,
"low": 1
},
},
"severity_stats": {
"high": 1,
"medium": 0,
"critical": 0,
"low": 1
}
},
"type": "sigma_analysis",
"id": "f912398cb3542ab704fe917af4a60d4feee21ac577535b10453170f10c6fd6de",
"links": {
"self": "https://www.virustotal.com/api/v3/sigma_analyses/f912398cb3542ab704fe917af4a60d4feee21ac577535b10453170f10c6fd6de"
}
},
"links": {
"self": "https://www.virustotal.com/api/v3/files/f912398cb3542ab704fe917af4a60d4feee21ac577535b10453170f10c6fd6de/sigma_analysis"
}
}
}
}
Human Readable Output
Last Sigma analysis results
MatchContext RuleLevel RuleDescription RuleSource RuleTitle RuleId RuleAuthor $EventID: ‘1117’ high Detects all actions taken by Windows Defender malware detection engines Sigma Integrated Rule Set (GitHub) Windows Defender Threat Detected 693c36f61ac022fd66354b440464f490058c22b984ba1bef05ca246aba210ed1 Ján Trenčanský
gti-privatescanning-file
Checks the file reputation of the specified private hash.
See files through the eyes of GoogleThreatIntelligence without uploading them to the main threat corpus, keeping them entirely private. Static, dynamic, network and similarity analysis included, as well as automated threat intel enrichment, but NOT multi-antivirus analysis.
Base Command
gti-privatescanning-file
Input
| Argument Name | Description | Required |
|---|---|---|
| file | File hash (md5, sha1, sha256). | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.File.attributes.type_description | String | Description of the type of the file. |
| GoogleThreatIntelligence.File.attributes.tlsh | String | The locality-sensitive hashing. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEType | String | MIME type of the file. |
| GoogleThreatIntelligence.File.attributes.names | String | Names of the file. |
| GoogleThreatIntelligence.File.attributes.javascript_info.tags | String | Tags of the JavaScript. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileType | String | The file type. |
| GoogleThreatIntelligence.File.attributes.exiftool.WordCount | Number | Total number of words in the file. |
| GoogleThreatIntelligence.File.attributes.exiftool.LineCount | Number | Total number of lines in file. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEEncoding | String | The MIME encoding. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileTypeExtension | String | The file type extension. |
| GoogleThreatIntelligence.File.attributes.exiftool.Newlines | Number | Number of newlines signs. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.info | Number | Number of IDS that marked the file as “info”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.high | Number | Number of IDS that marked the file as “high”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.medium | Number | Number of IDS that marked the file as “medium”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.low | Number | Number of IDS that marked the file as “low”. |
| GoogleThreatIntelligence.File.attributes.trid.file_type | String | The TrID file type. |
| GoogleThreatIntelligence.File.attributes.trid.probability | Number | The TrID probability. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.description | String | Description of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.source | String | Source of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.author | String | Author of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_name | String | Rule set name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.rule_name | String | Name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_id | String | ID of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.names | String | Name of the file. |
| GoogleThreatIntelligence.File.attributes.type_tag | String | Tag of the type. |
| GoogleThreatIntelligence.File.attributes.size | Number | Size of the file. |
| GoogleThreatIntelligence.File.attributes.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.File.attributes.type_extension | String | Extension of the type. |
| GoogleThreatIntelligence.File.attributes.tags | String | File tags. |
| GoogleThreatIntelligence.File.attributes.last_analysis_date | Number | Last analysis date in epoch format. |
| GoogleThreatIntelligence.File.attributes.ssdeep | String | SSDeep hash of the file. |
| GoogleThreatIntelligence.File.attributes.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.File.attributes.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.File.attributes.magic | String | Identification of file by the magic number. |
| GoogleThreatIntelligence.File.attributes.meaningful_name | String | Meaningful name of the file. |
| GoogleThreatIntelligence.File.attributes.threat_severity.threat_severity_level | String | Threat severity level of the file. |
| GoogleThreatIntelligence.File.attributes.threat_severity.threat_severity_data.popular_threat_category | String | Popular threat category of the file. |
| GoogleThreatIntelligence.File.attributes.threat_verdict | String | Threat verdict of the file. |
| GoogleThreatIntelligence.File.type | String | Type of the file. |
| GoogleThreatIntelligence.File.id | String | ID of the file. |
| GoogleThreatIntelligence.File.links.self | String | Link to the response. |
Command Example
!gti-privatescanning-file file=example-file-hash
Context Example
{
"GoogleThreatIntelligence": {
"File": {
"attributes": {
"type_description": "ELF",
"tlsh": "Example tlsh",
"vhash": "Example vhash",
"exiftool": {
"MIMEType": "application/octet-stream",
"CPUByteOrder": "Little endian",
"ObjectFileType": "Executable file",
"CPUArchitecture": "32 bit",
"CPUType": "i386",
"FileType": "ELF executable"
},
"trid": [
{
"file_type": "ELF Executable and Linkable format (Linux)",
"probability": 55
},
{
"file_type": "ELF Executable and Linkable format (generic)",
"probability": 45
}
],
"crowdsourced_yara_results": [
{
"description": "Detects a suspicious ELF binary with UPX compression",
"source": "https://www.example.com",
"author": "Author X",
"ruleset_name": "gen_elf_file_anomalies",
"rule_name": "SUSP_ELF_LNX_UPX_Compressed_File",
"ruleset_id": "0224a54ba7"
}
],
"threat_severity": {
"threat_severity_level": "SEVERITY_HIGH",
"threat_severity_data": {
"has_dropped_files_with_detections": true,
"type_tag": "elf",
"has_execution_parents_with_detections": true,
"can_be_detonated": true,
"popular_threat_category": "trojan"
},
"last_analysis_date": "1681045097",
"version": 1
},
"names": [
"private",
"/usr/lib/sample.so",
"private_sample.bin",
],
"owner": "virustotal",
"type_tag": "elf",
"elf_info": {
"header": {
"hdr_version": "1 (current)",
"type": "EXEC (Executable file)",
"obj_version": "0x1",
"data": "2's complement, little endian",
"machine": "Intel 80386",
"num_section_headers": 0,
"os_abi": "UNIX - Linux",
"abi_version": 0,
"entrypoint": 4633,
"num_prog_headers": 2,
"class": "ELF32"
},
"packers": [
"upx"
],
"segment_list": [
{
"segment_type": "LOAD"
}
]
},
"size": 255510,
"type_extension": "so",
"threat_verdict": "VERDICT_MALICIOUS",
"detectiteasy": {
"filetype": "ELF32",
"values": [
{
"info": "EXEC 386-32",
"version": "3.05",
"type": "Packer",
"name": "UPX"
}
]
},
"crowdsourced_ids_stats": {
"high": 0,
"info": 0,
"medium": 1,
"low": 1
},
"type_tags": [
"executable",
"linux",
"elf"
],
"sandbox_verdicts": {
"Zenbox Linux": {
"category": "malicious",
"confidence": 81,
"sandbox_name": "Zenbox Linux",
"malware_classification": [
"MALWARE",
"TROJAN",
"EVADER"
],
"malware_names": [
"MalwareName"
]
}
},
"sha256": "Example_sha256",
"tags": [
"elf",
"upx"
],
"crowdsourced_ids_results": [
{
"rule_category": "Misc Attack",
"alert_severity": "medium",
"rule_msg": "Known Compromised or Hostile Host Traffic",
"rule_raw": "alert ip [8.8.8.8] any -> $HOME_NET any"
},
{
"rule_category": "Misc Attack",
"alert_severity": "low",
"rule_msg": "Poor Reputation IP",
"rule_raw": "alert ip [1.1.1.1] any -> $HOME_NET any)"
},
],
"last_analysis_date": 1681386314,
"ssdeep": "Example ssdeep",
"packers": {
"Gandelf": "upx"
},
"md5": "Example_md5",
"sha1": "Example_sha1",
"magic": "ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, stripped",
"meaningful_name": "private"
},
"type": "private_file",
"id": "Example_sha256",
"links": {
"self": "https://www.virustotal.com/api/v3/private/files/Example_sha256"
}
}
}
}
Human Readable Output
Results of file hash Example_sha256
Sha1 Sha256 Md5 Meaningful Name Threat Severity Level Popular Threat Category Threat Verdict Example_sha1 Example_sha256 Example_md5 private HIGH trojan MALICIOUS
gti-privatescanning-file-scan
Submits a file for private scanning. Use the gti-privatescanning-analysis-get command to get the scan results.
Base Command
gti-privatescanning-file-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| entryID | The file entry ID to submit. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Submission.type | String | The type of the submission (analysis). |
| GoogleThreatIntelligence.Submission.id | String | The ID of the submission. |
| GoogleThreatIntelligence.Submission.EntryID | String | The entry ID of the file detonated. |
| GoogleThreatIntelligence.Submission.Extension | String | File extension. |
| GoogleThreatIntelligence.Submission.Info | String | File info. |
| GoogleThreatIntelligence.Submission.MD5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.Submission.Name | String | Name of the file. |
| GoogleThreatIntelligence.Submission.SHA1 | String | SHA-1 of the file. |
| GoogleThreatIntelligence.Submission.SHA256 | String | SHA-256 of the file. |
| GoogleThreatIntelligence.Submission.SHA512 | String | SHA-512 of the file. |
| GoogleThreatIntelligence.Submission.SSDeep | String | SSDeep of the file. |
| GoogleThreatIntelligence.Submission.Size | String | Size of the file. |
| GoogleThreatIntelligence.Submission.Type | String | Type of the file. |
Command Example
!gti-privatescanning-file-scan entryID=example-entry-id
Context Example
{
"GoogleThreatIntelligence": {
"Submission": {
"type": "private_analysis",
"id": "example-analysis-id",
"EntryID": "example-entry-id",
"Extension": "txt",
"Info": "ASCII text, with no line terminators",
"MD5": "Example_md5",
"Name": "Testing.txt",
"SHA1": "Example_sha1",
"SHA256": "Example_sha256",
"SHA512": "Example_sha512",
"SSDeep": "Example ssdeep",
"Size": "71 bytes",
"Type": "text/plain; charset=utf-8"
}
}
}
Human Readable Output
The file has been submitted “Testing.txt”
id EntryID MD5 SHA1 SHA256 example-analysis-id example-entry-id Example_md5 Example_sha1 Example_sha256
gti-privatescanning-analysis-get
Get analysis of a private file or URL submitted to GoogleThreatIntelligence.
Base Command
gti-privatescanning-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| id | ID of the analysis. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.attributes.sha256 | String | SHA-256 hash of the private file. |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_severity_level | String | Threat severity level of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.popular_threat_category | String | Popular threat category of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_verdict | String | Threat verdict of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.url | String | URL submitted. |
| GoogleThreatIntelligence.Analysis.data.attributes.title | String | Title of the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.last_http_response_content_sha256 | String | Last HTTP response content SHA-256 hash of the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.positives | String | Ratio of malicious detections to the total number of engines that scanned the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (private_analysis). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.size | Number | Size of the file. |
| GoogleThreatIntelligence.Analysis.meta.url_info.id | String | ID of the URL. |
| GoogleThreatIntelligence.Analysis.meta.url_info.url | String | URL submitted. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-curated-threat-actors-get
Retrieves GTI curated threat actors for a given resource.
Base Command
gti-curated-threat-actors-get
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, or SHA256), Domain, URL or IP. | Required |
| resource_type | The type of the resource. If not supplied, will determine it’s a file. Possible values are: ip, url, domain, file, hash. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Collection.id | String | ID that contains the assessment (the given hash, domain, url, or ip). |
| GoogleThreatIntelligence.Collection.collections.id | String | ID of the curated threat actors. |
| GoogleThreatIntelligence.Collection.collections.attributes.name | String | Name of the curated threat actors. |
| GoogleThreatIntelligence.Collection.collections.attributes.description | String | Description of the curated threat actors. |
| GoogleThreatIntelligence.Collection.collections.attributes.last_modification_date | String | Last modification date of the curated threat actors. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_regions | list | Targeted regions of the curated threat actors. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_industries | list | Targeted industries of the curated threat actors. |
gti-curated-malware-families-get
Retrieves GTI curated malware families for a given resource.
Base Command
gti-curated-malware-families-get
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, or SHA256), Domain, URL or IP. | Required |
| resource_type | The type of the resource. If not supplied, will determine it’s a file. Possible values are: ip, url, domain, file, hash. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Collection.id | String | ID that contains the assessment (the given hash, domain, url, or ip). |
| GoogleThreatIntelligence.Collection.collections.id | String | ID of the curated malware families. |
| GoogleThreatIntelligence.Collection.collections.attributes.name | String | Name of the curated malware families. |
| GoogleThreatIntelligence.Collection.collections.attributes.description | String | Description of the curated malware families. |
| GoogleThreatIntelligence.Collection.collections.attributes.last_modification_date | String | Last modification date of the curated malware families. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_regions | list | Targeted regions of the curated malware families. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_industries | list | Targeted industries of the curated malware families. |
gti-curated-campaigns-get
Retrieves GTI curated campaigns for a given resource.
Base Command
gti-curated-campaigns-get
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, or SHA256), Domain, URL or IP. | Required |
| resource_type | The type of the resource. If not supplied, will determine it’s a file. Possible values are: ip, url, domain, file, hash. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Collection.id | String | ID that contains the assessment (the given hash, domain, url, or ip). |
| GoogleThreatIntelligence.Collection.collections.id | String | ID of the curated campaign. |
| GoogleThreatIntelligence.Collection.collections.attributes.name | String | Name of the curated campaign. |
| GoogleThreatIntelligence.Collection.collections.attributes.description | String | Description of the curated campaign. |
| GoogleThreatIntelligence.Collection.collections.attributes.last_modification_date | String | Last modification date of the curated campaign. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_regions | list | Targeted regions of the curated campaign. |
| GoogleThreatIntelligence.Collection.collections.attributes.targeted_industries | list | Targeted industries of the curated campaign. |
gti-url-scan-and-analysis-get
Scan and get the analysis of a URL submitted to GoogleThreatIntelligence.
Base Command
gti-url-scan-and-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to scan. | Required |
| id | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| extended_data | Whether to return extended data. Possible values are: true, false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. Default is 60. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| URL.Data | unknown | Bad URLs found. |
| URL.Malicious.Vendor | unknown | For malicious URLs, the vendor that made the decision. |
| URL.Malicious.Description | unknown | For malicious URLs, the reason that the vendor made the decision. |
| URL.Relationships.EntityA | string | The source of the relationship. |
| URL.Relationships.EntityB | string | The destination of the relationship. |
| URL.Relationships.Relationship | string | The name of the relationship. |
| URL.Relationships.EntityAType | string | The type of the source of the relationship. |
| URL.Relationships.EntityBType | string | The type of the destination of the relationship. |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.URL.attributes.favicon.raw_md5 | String | The MD5 hash of the URL. |
| GoogleThreatIntelligence.URL.attributes.favicon.dhash | String | Difference hash. |
| GoogleThreatIntelligence.URL.attributes.last_modification_date | Number | Last modification date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.times_submitted | Number | The number of times the url has been submitted. |
| GoogleThreatIntelligence.URL.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.URL.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.URL.attributes.threat_names | String | Name of the threats found. |
| GoogleThreatIntelligence.URL.attributes.last_submission_date | Number | The last submission date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_length | Number | The last HTTPS response length. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.date | Date | The last response header date. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.x-sinkhole | String | DNS sinkhole from last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-length | String | The content length of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-type | String | The content type of the last response. |
| GoogleThreatIntelligence.URL.attributes.reputation | Number | Reputation of the indicator. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_date | Number | The date of the last analysis in epoch format. |
| GoogleThreatIntelligence.URL.attributes.has_content | Boolean | Whether the url has content in it. |
| GoogleThreatIntelligence.URL.attributes.first_submission_date | Number | The first submission date in epoch format. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_sha256 | String | The SHA-256 hash of the content of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_code | Number | Last response status code. |
| GoogleThreatIntelligence.URL.attributes.last_final_url | String | Last final URL. |
| GoogleThreatIntelligence.URL.attributes.url | String | The URL itself. |
| GoogleThreatIntelligence.URL.attributes.title | String | Title of the page. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.harmless | Number | The number of engines that found the domain to be harmless. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.URL.attributes.outgoing_links | String | Outgoing links of the URL page. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the URL. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.severity.value | String | GTI severity of the URL. |
| GoogleThreatIntelligence.URL.attributes.gti_assessment.verdict.value | String | GTI verdict of the URL. |
| GoogleThreatIntelligence.URL.type | String | Type of the indicator (url). |
| GoogleThreatIntelligence.URL.id | String | ID of the indicator. |
| GoogleThreatIntelligence.URL.links.self | String | Link to the response. |
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.harmless | Number | Number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.malicious | Number | Number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.suspicious | Number | Number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.timeout | Number | he number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.undetected | Number | Number of engines the found the indicator to be undetected. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (analysis). |
| GoogleThreatIntelligence.Analysis.meta.url_info.id | String | ID of the URL. |
| GoogleThreatIntelligence.Analysis.meta.url_info.url | String | The URL. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-file-scan-and-analysis-get
Scan and get the analysis of a file submitted to GoogleThreatIntelligence.
Base Command
gti-file-scan-and-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| entryID | The file entry ID to submit. | Required |
| uploadURL | Special upload URL for files larger than 32 MB. Can be acquired from the gti-file-scan-upload-url command. | Optional |
| id | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| file | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| extended_data | Whether to return extended data. Possible values are: true, false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. Default is 60. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| File.MD5 | unknown | Bad MD5 hash. |
| File.SHA1 | unknown | Bad SHA1 hash. |
| File.SHA256 | unknown | Bad SHA256 hash. |
| File.Relationships.EntityA | string | The source of the relationship. |
| File.Relationships.EntityB | string | The destination of the relationship. |
| File.Relationships.Relationship | string | The name of the relationship. |
| File.Relationships.EntityAType | string | The type of the source of the relationship. |
| File.Relationships.EntityBType | string | The type of the destination of the relationship. |
| File.Malicious.Vendor | unknown | For malicious files, the vendor that made the decision. |
| File.Malicious.Detections | unknown | For malicious files, the total number of detections. |
| File.Malicious.TotalEngines | unknown | For malicious files, the total number of engines that checked the file hash. |
| DBotScore.Indicator | unknown | The indicator that was tested. |
| DBotScore.Type | unknown | The indicator type. |
| DBotScore.Vendor | unknown | The vendor used to calculate the score. |
| DBotScore.Score | Number | The actual score. |
| DBotScore.Reliability | String | Reliability of the source providing the intelligence data. |
| GoogleThreatIntelligence.File.attributes.type_description | String | Description of the type of the file. |
| GoogleThreatIntelligence.File.attributes.tlsh | String | The locality-sensitive hashing. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEType | String | MIME type of the file. |
| GoogleThreatIntelligence.File.attributes.names | String | Names of the file. |
| GoogleThreatIntelligence.File.attributes.javascript_info.tags | String | Tags of the JavaScript. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileType | String | The file type. |
| GoogleThreatIntelligence.File.attributes.exiftool.WordCount | String | Total number of words in the file. |
| GoogleThreatIntelligence.File.attributes.exiftool.LineCount | String | Total number of lines in file. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.info | Number | Number of IDS that marked the file as “info”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.high | Number | Number of IDS that marked the file as “high”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.medium | Number | Number of IDS that marked the file as “medium”. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_ids_stats.low | Number | Number of IDS that marked the file as “low”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.critical | Number | Number of Sigma analysis that marked the file as “critical”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.high | Number | Number of Sigma analysis that marked the file as “high”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.medium | Number | Number of Sigma analysis that marked the file as “medium”. |
| GoogleThreatIntelligence.File.attributes.sigma_analysis_stats.low | Number | Number of Sigma analysis that marked the file as “low”. |
| GoogleThreatIntelligence.File.attributes.exiftool.MIMEEncoding | String | The MIME encoding. |
| GoogleThreatIntelligence.File.attributes.exiftool.FileTypeExtension | String | The file type extension. |
| GoogleThreatIntelligence.File.attributes.exiftool.Newlines | String | Number of newlines signs. |
| GoogleThreatIntelligence.File.attributes.trid.file_type | String | The TrID file type. |
| GoogleThreatIntelligence.File.attributes.trid.probability | Number | The TrID probability. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.description | String | Description of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.source | String | Source of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.author | String | Author of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_name | String | Rule set name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.rule_name | String | Name of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.crowdsourced_yara_results.ruleset_id | String | ID of the YARA rule. |
| GoogleThreatIntelligence.File.attributes.names | String | Name of the file. |
| GoogleThreatIntelligence.File.attributes.last_modification_date | Number | The last modification date in epoch format. |
| GoogleThreatIntelligence.File.attributes.type_tag | String | Tag of the type. |
| GoogleThreatIntelligence.File.attributes.total_votes.harmless | Number | Total number of harmless votes. |
| GoogleThreatIntelligence.File.attributes.total_votes.malicious | Number | Total number of malicious votes. |
| GoogleThreatIntelligence.File.attributes.size | Number | Size of the file. |
| GoogleThreatIntelligence.File.attributes.popular_threat_classification.suggested_threat_label | String | Suggested thread label. |
| GoogleThreatIntelligence.File.attributes.popular_threat_classification.popular_threat_name | Number | The popular thread name. |
| GoogleThreatIntelligence.File.attributes.times_submitted | Number | Number of times the file was submitted. |
| GoogleThreatIntelligence.File.attributes.last_submission_date | Number | Last submission date in epoch format. |
| GoogleThreatIntelligence.File.attributes.downloadable | Boolean | Whether the file is downloadable. |
| GoogleThreatIntelligence.File.attributes.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.File.attributes.type_extension | String | Extension of the type. |
| GoogleThreatIntelligence.File.attributes.tags | String | File tags. |
| GoogleThreatIntelligence.File.attributes.last_analysis_date | Number | Last analysis date in epoch format. |
| GoogleThreatIntelligence.File.attributes.unique_sources | Number | Unique sources. |
| GoogleThreatIntelligence.File.attributes.first_submission_date | Number | First submission date in epoch format. |
| GoogleThreatIntelligence.File.attributes.ssdeep | String | SSDeep hash of the file. |
| GoogleThreatIntelligence.File.attributes.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.File.attributes.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.File.attributes.magic | String | Identification of file by the magic number. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.harmless | Number | The number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.type-unsupported | Number | The number of engines that found the indicator to be of type unsupported. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.confirmed-timeout | Number | The number of engines that confirmed the timeout of the indicator. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.failure | Number | The number of failed analysis engines. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.File.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.File.attributes.meaningful_name | String | Meaningful name of the file. |
| GoogleThreatIntelligence.File.attributes.reputation | Number | The reputation of the file. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.threat_score.value | Number | GTI threat score of the file. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.severity.value | String | GTI severity of the file. |
| GoogleThreatIntelligence.File.attributes.gti_assessment.verdict.value | String | GTI verdict of the file. |
| GoogleThreatIntelligence.File.type | String | Type of the indicator (file). |
| GoogleThreatIntelligence.File.id | String | Type ID of the indicator. |
| GoogleThreatIntelligence.File.links.self | String | Link to the response. |
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.harmless | Number | Number of engines that found the indicator to be harmless. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.malicious | Number | Number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.suspicious | Number | Number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.timeout | Number | he number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.Analysis.data.attributes.stats.undetected | Number | Number of engines the found the indicator to be undetected. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (analysis). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.name | unknown | Name of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.size | Number | Size of the file. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-private-file-scan-and-analysis-get
Scan and get the analysis of a private file submitted to GoogleThreatIntelligence.
Base Command
gti-private-file-scan-and-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| entryID | The file entry ID to submit. | Required |
| id | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| extended_data | Whether to return extended data. Possible values are: true, false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. Default is 60. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.attributes.sha256 | String | SHA-256 hash of the private file. |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_severity_level | String | Threat severity level of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.popular_threat_category | String | Popular threat category of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_verdict | String | Threat verdict of the private file (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (private_analysis). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.size | Number | Size of the file. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-private-file-scan-and-analysis-get
Scan and get the analysis of a private file submitted to GoogleThreatIntelligence.
Base Command
gti-private-file-scan-and-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| entryID | The file entry ID to submit. | Required |
| id | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| extended_data | Whether to return extended data. Possible values are: true, false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. Default is 60. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_severity_level | String | Threat severity level of the private file. |
| GoogleThreatIntelligence.Analysis.data.attributes.popular_threat_category | String | Popular threat category of the private file. |
| GoogleThreatIntelligence.Analysis.data.attributes.threat_verdict | String | Threat verdict of the private file. |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (analysis). |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha256 | String | SHA-256 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.sha1 | String | SHA-1 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.md5 | String | MD5 hash of the file. |
| GoogleThreatIntelligence.Analysis.meta.file_info.size | Number | Size of the file. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-assessment-get
Retrieves GTI assessment for a given resource.
Base Command
gti-assessment-get
Input
| Argument Name | Description | Required |
|---|---|---|
| resource | The file hash (MD5, SHA1, or SHA256), Domain, URL or IP. | Required |
| resource_type | The type of the resource. If not supplied, will determine it’s a file. Possible values are: ip, url, domain, file, hash. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Assessment.id | String | ID that contains the assessment (the given hash, domain, url, or ip). |
| GoogleThreatIntelligence.Assessment.attributes.gti_assessment.threat_score.value | Number | The threat score of the assessment. |
| GoogleThreatIntelligence.Assessment.attributes.gti_assessment.severity.value | String | The severity of the assessment. |
| GoogleThreatIntelligence.Assessment.attributes.gti_assessment.verdict.value | String | The verdict of the assessment. |
gti-private-url-scan-and-analysis-get
Scan and get the analysis of a private URL submitted to GoogleThreatIntelligence.
Base Command
gti-private-url-scan-and-analysis-get
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to scan. | Required |
| id | This is an internal argument used for the polling process, not to be used by the user. | Optional |
| extended_data | Whether to return extended data. Possible values are: true, false. | Optional |
| interval_in_seconds | Interval in seconds between each poll. Default is 60. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Analysis.data.attributes.date | Number | Date of the analysis in epoch format. |
| GoogleThreatIntelligence.Analysis.data.attributes.status | String | Status of the analysis. |
| GoogleThreatIntelligence.Analysis.data.attributes.url | String | URL submitted. |
| GoogleThreatIntelligence.Analysis.data.attributes.title | String | Title of the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.last_http_response_content_sha256 | String | Last HTTP response content SHA-256 hash of the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.attributes.positives | String | Ratio of malicious detections to the total number of engines that scanned the private URL (if analysis is completed). |
| GoogleThreatIntelligence.Analysis.data.id | String | ID of the analysis. |
| GoogleThreatIntelligence.Analysis.data.type | String | Type of object (private_analysis). |
| GoogleThreatIntelligence.Analysis.meta.url_info.id | String | ID of the URL. |
| GoogleThreatIntelligence.Analysis.meta.url_info.url | String | URL submitted. |
| GoogleThreatIntelligence.Analysis.id | String | The analysis ID. |
gti-privatescanning-url-scan
Base Command
gti-privatescanning-url-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The private URL to scan. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.Submission.Type | String | The type of the submission (private_analysis). |
| GoogleThreatIntelligence.Submission.id | String | The ID of the submission. |
gti-privatescanning-url
Checks the reputation of a private URL.
Base Command
gti-privatescanning-url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | Private URL to check. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| GoogleThreatIntelligence.URL.attributes.favicon.raw_md5 | String | The MD5 hash of the URL. |
| GoogleThreatIntelligence.URL.attributes.favicon.dhash | String | Difference hash. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_length | Number | The last HTTPS response length. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.date | Date | The last response header date. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.x-sinkhole | String | DNS sinkhole from last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-length | String | The content length of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_headers.content-type | String | The content type of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_content_sha256 | String | The SHA-256 hash of the content of the last response. |
| GoogleThreatIntelligence.URL.attributes.last_http_response_code | Number | Last response status code. |
| GoogleThreatIntelligence.URL.attributes.last_final_url | String | Last final URL. |
| GoogleThreatIntelligence.URL.attributes.url | String | The URL itself. |
| GoogleThreatIntelligence.URL.attributes.title | String | Title of the page. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.harmless | Number | The number of engines that found the domain to be harmless. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.malicious | Number | The number of engines that found the indicator to be malicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.suspicious | Number | The number of engines that found the indicator to be suspicious. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.undetected | Number | The number of engines that could not detect the indicator. |
| GoogleThreatIntelligence.URL.attributes.last_analysis_stats.timeout | Number | The number of engines that timed out for the indicator. |
| GoogleThreatIntelligence.URL.attributes.outgoing_links | String | Outgoing links of the URL page. |
| GoogleThreatIntelligence.URL.type | String | Type of the indicator (private_url). |
| GoogleThreatIntelligence.URL.id | String | ID of the indicator. |
| GoogleThreatIntelligence.URL.links.self | String | Link to the response. |
Configuration parameters
credentials— API Key (leave empty. Fill in the API key in the password field.) (required)feedReliability— Source Reliabilitygti_malicious— GTI Malicious Verdict. Check Google Threat Intelligence verdict to consider the file malicious.gti_suspicious— GTI Suspicious Verdict. Check Google Threat Intelligence verdict to consider the file suspicious.fileThreshold— File Malicious Threshold. Minimum number of positive results from VT scanners to consider the file malicious.fileSuspiciousThreshold— File Suspicious Threshold. Minimum number of positive and suspicious results from VT scanners to consider the file suspicious.ipThreshold— IP Malicious Threshold. Minimum number of positive results from VT scanners to consider the IP malicious.ipSuspiciousThreshold— IP Suspicious Threshold. Minimum number of positive and suspicious results from VT scanners to consider the IP suspicious.disable_private_ip_lookup— Disable reputation lookups for private IP addressesurlThreshold— URL Malicious Threshold. Minimum number of positive results from VT scanners to consider the URL malicious.urlSuspiciousThreshold— URL Suspicious Threshold. Minimum number of positive and suspicious results from VT scanners to consider the URL suspicious.domainThreshold— Domain Malicious Threshold. Minimum number of positive results from VT scanners to consider the Domain malicious.domainSuspiciousThreshold— Domain Suspicious Threshold. Minimum number of positive and suspicious results from VT scanners to consider the Domain suspicious.preferredVendors— Preferred Vendors List. CSV list of vendors who are considered more trustworthy.preferredVendorsThreshold— Preferred Vendor Threshold. The minimum number of highly trusted vendors required to consider a domain, IP address, URL, or file as malicious.crowdsourced_yara_rules_enabled— Enable score analyzing by Crowdsourced Yara Rules, Sigma, and IDS.yaraRulesThreshold— Crowdsourced Yara Rules ThresholdSigmaIDSThreshold— Sigma and Intrusion Detection Rules Thresholddomain_popularity_ranking— Domain Popularity Ranking Thresholdip_relationships— IP Relationshipsdomain_relationships— Domain Relationshipsurl_relationships— URL Relationshipsfile_relationships— File Relationshipsproxy— Use system proxy settingsinsecure— Trust any certificate (not secure)
Commands (31)
-
cveRetrieves CVE information from Google Threat Intelligence.
-
domainChecks the reputation of a domain.
-
fileChecks the file reputation of the specified hash.
-
file-rescanRescans an already submitted file. This avoids having to upload the file again. Use the gti-analysis-get command to get the scan results.
-
file-scanSubmits a file for scanning. Use the gti-analysis-get command to get the scan results.
-
gti-analysis-getScan and get the analysis of a file submitted to GoogleThreatIntelligence.
-
gti-assessment-getRetrieves GTI assessment for a given resource.
-
gti-comments-addAdds comments to files and URLs.
-
gti-comments-deleteDelete a comment.
-
gti-comments-getRetrieves comments for a given resource.
-
gti-comments-get-by-idRetrieves a comment by comment ID.
-
gti-curated-campaigns-getRetrieves GTI curated campaigns for a given resource.
-
gti-curated-malware-families-getRetrieves GTI curated malware families for a given resource.
-
gti-curated-threat-actors-getRetrieves GTI curated threat actors for a given resource.
-
gti-file-sandbox-reportRetrieves a behavioral relationship of the given file hash.
-
gti-file-scan-and-analysis-getScan and get the analysis of a file submitted to GoogleThreatIntelligence.
-
gti-file-scan-upload-urlGet a special URL for files larger than 32 MB.
-
gti-file-sigma-analysisResult of the last Sigma analysis in markdown format.
-
gti-passive-dns-dataReturns passive DNS records by indicator.
-
gti-private-file-scan-and-analysis-getScan and get the analysis of a private file submitted to GoogleThreatIntelligence.
-
gti-private-url-scan-and-analysis-getScan and get the analysis of a private URL submitted to GoogleThreatIntelligence.
-
gti-privatescanning-analysis-getGet analysis of a private file or URL submitted to GoogleThreatIntelligence.
-
gti-privatescanning-fileChecks the file reputation of the specified private hash.
-
gti-privatescanning-file-scanSubmits a file for private scanning. Use the gti-privatescanning-analysis-get command to get the scan results.
-
gti-privatescanning-urlChecks the reputation of a private URL.
-
gti-privatescanning-url-scanSubmits an URL for private scanning. Use the gti-privatescanning-analysis-get command to get the scan results.
-
gti-searchSearch for an indicator in Google Threat Intelligence.
-
gti-url-scan-and-analysis-getScan and get the analysis of a URL submitted to GoogleThreatIntelligence.
-
ipChecks the reputation of an IP address.
-
urlChecks the reputation of a URL.
-
url-scanScans a specified URL. Use the gti-analysis-get command to get the scan results.
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 """ An integration module for the Google Threat Intelligence API. API Documentation: https://gtidocs.virustotal.com/reference """ import ipaddress import re from collections import defaultdict from typing import cast from dateparser import parse INTEGRATION_NAME = "GoogleThreatIntelligence" COMMAND_PREFIX = "gti" INTEGRATION_ENTRY_CONTEXT = INTEGRATION_NAME INDICATOR_TYPE = { "ip": FeedIndicatorType.IP, "ip_address": FeedIndicatorType.IP, "domain": FeedIndicatorType.Domain, "file": FeedIndicatorType.File, "url": FeedIndicatorType.URL, "cve": FeedIndicatorType.CVE, } SEVERITY_LEVELS = { "SEVERITY_UNKNOWN": "UNKNOWN", "SEVERITY_LOW": "LOW", "SEVERITY_MEDIUM": "MEDIUM", "SEVERITY_HIGH": "HIGH", } VERDICTS = { "VERDICT_UNKNOWN": "UNKNOWN", "VERDICT_UNDETECTED": "UNDETECTED", "VERDICT_SUSPICIOUS": "SUSPICIOUS", "VERDICT_MALICIOUS": "MALICIOUS", } TYPE_TO_ENDPOINT = { "file": "files", "hash": "files", "domain": "domains", "url": "urls", "ip": "ip_addresses", } """RELATIONSHIP TYPE""" RELATIONSHIP_TYPE = { "file": { "carbonblack_children": EntityRelationship.Relationships.CREATES, "carbonblack_parents": EntityRelationship.Relationships.CREATED_BY, "compressed_parents": EntityRelationship.Relationships.BUNDLED_IN, "contacted_domains": EntityRelationship.Relationships.COMMUNICATES_WITH, "contacted_ips": EntityRelationship.Relationships.COMMUNICATES_WITH, "contacted_urls": EntityRelationship.Relationships.COMMUNICATES_WITH, "dropped_files": EntityRelationship.Relationships.DROPPED_BY, "email_attachments": EntityRelationship.Relationships.ATTACHES, "email_parents": EntityRelationship.Relationships.ATTACHMENT_OF, "embedded_domains": EntityRelationship.Relationships.EMBEDDED_IN, "embedded_ips": EntityRelationship.Relationships.EMBEDDED_IN, "embedded_urls": EntityRelationship.Relationships.EMBEDDED_IN, "execution_parents": EntityRelationship.Relationships.EXECUTED_BY, "itw_domains": EntityRelationship.Relationships.DOWNLOADS_FROM, "itw_ips": EntityRelationship.Relationships.DOWNLOADS_FROM, "overlay_children": EntityRelationship.Relationships.BUNDLES, "overlay_parents": EntityRelationship.Relationships.BUNDLED_IN, "pcap_children": EntityRelationship.Relationships.BUNDLES, "pcap_parents": EntityRelationship.Relationships.BUNDLED_IN, "pe_resource_children": EntityRelationship.Relationships.EXECUTED, "pe_resource_parents": EntityRelationship.Relationships.EXECUTED_BY, "similar_files": EntityRelationship.Relationships.SIMILAR_TO, }, "domain": { "cname_records": EntityRelationship.Relationships.IS_ALSO, "caa_records": EntityRelationship.Relationships.RELATED_TO, "communicating_files": EntityRelationship.Relationships.DROPS, "downloaded_files": EntityRelationship.Relationships.DROPS, "immediate_parent": EntityRelationship.Relationships.SUB_DOMAIN_OF, "mx_records": EntityRelationship.Relationships.RELATED_TO, "ns_records": EntityRelationship.Relationships.DROPS, "parent": EntityRelationship.Relationships.SUB_DOMAIN_OF, "referrer_files": EntityRelationship.Relationships.RELATED_TO, "resolutions": EntityRelationship.Relationships.RESOLVED_FROM, "siblings": EntityRelationship.Relationships.SUPRA_DOMAIN_OF, "soa_records": EntityRelationship.Relationships.IS_ALSO, "subdomains": EntityRelationship.Relationships.SUPRA_DOMAIN_OF, "urls": EntityRelationship.Relationships.HOSTS, }, "ip": { "communicating_files": EntityRelationship.Relationships.COMMUNICATES_WITH, "downloaded_files": EntityRelationship.Relationships.DROPS, "referrer_files": EntityRelationship.Relationships.RELATED_TO, "resolutions": EntityRelationship.Relationships.RESOLVES_TO, "urls": EntityRelationship.Relationships.RELATED_TO, }, "url": { "contacted_domains": EntityRelationship.Relationships.RELATED_TO, "contacted_ips": EntityRelationship.Relationships.RELATED_TO, "downloaded_files": EntityRelationship.Relationships.DROPS, "last_serving_ip_address": EntityRelationship.Relationships.RESOLVED_FROM, "network_location": EntityRelationship.Relationships.RESOLVED_FROM, "redirecting_urls": EntityRelationship.Relationships.DUPLICATE_OF, "redirects_to": EntityRelationship.Relationships.DUPLICATE_OF, "referrer_files": EntityRelationship.Relationships.EMBEDDED_IN, "referrer_urls": EntityRelationship.Relationships.RELATED_TO, }, "cve": {"referrer_cve": EntityRelationship.Relationships.RELATED_TO}, } class Client(BaseClient): """Client for Google Threat Intelligence API.""" reliability: DBotScoreReliability def __init__(self, params: dict): self.reliability = DBotScoreReliability.get_dbot_score_reliability_from_str(params["feedReliability"]) super().__init__( "https://www.virustotal.com/api/v3/", verify=not argToBoolean(params.get("insecure")), proxy=argToBoolean(params.get("proxy")), headers={ "x-apikey": params["credentials"]["password"], "x-tool": "CortexGTI", }, ) # region Reputation calls def ip(self, ip: str, relationships: str = "") -> dict: """ See Also: https://gtidocs.virustotal.com/reference/ip-info """ return self._http_request("GET", f"ip_addresses/{ip}?relationships={relationships}", ok_codes=(404, 429, 200)) def file(self, file: str, relationships: str = "") -> dict: """ See Also: https://gtidocs.virustotal.com/reference/file-info """ return self._http_request("GET", f"files/{file}?relationships={relationships}", ok_codes=(404, 429, 200)) # It is not a Reputation call def private_file(self, file: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/private-files-info """ return self._http_request("GET", f"private/files/{file}", ok_codes=(404, 429, 200)) def url(self, url: str, relationships: str = ""): """ See Also: https://gtidocs.virustotal.com/reference/url-info """ return self._http_request( "GET", f"urls/{encode_url_to_base64(url)}?relationships={relationships}", ok_codes=(404, 429, 200) ) def private_url(self, url: str): """ See Also: https://gtidocs.virustotal.com/reference/get-a-private-url-analysis-report """ return self._http_request("GET", f"private/urls/{encode_url_to_base64(url)}", ok_codes=(404, 429, 200)) def domain(self, domain: str, relationships: str = "") -> dict: """ See Also: https://gtidocs.virustotal.com/reference/domain-info """ return self._http_request("GET", f"domains/{domain}?relationships={relationships}", ok_codes=(404, 429, 200)) def cve(self, cve_id: str) -> dict: """ Get CVE (vulnerability) information from Google Threat Intelligence. Args: cve_id: CVE identifier (e.g., "CVE-2025-62173") Returns: dict: CVE information from the collections endpoint See Also: https://gtidocs.virustotal.com/reference/get-vulnerability """ # Format: vulnerability--cve-2025-62173 object_id = f"vulnerability--{cve_id.lower()}" return self._http_request("GET", f"collections/{object_id}", ok_codes=(404, 429, 200)) # endregion # region Comments call def delete_comment(self, id_: str): """ See Also: https://gtidocs.virustotal.com/reference/comment-id-delete """ self._http_request("DELETE", f"comments/{id_}", resp_type="response") def get_ip_comments(self, ip: str, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/ip-comments-get """ return self._http_request("GET", f"ip_addresses/{ip}/comments", params={"limit": limit}) def get_url_comments(self, url: str, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/urls-comments-get """ return self._http_request("GET", f"urls/{encode_url_to_base64(url)}/comments", params={"limit": limit}) def get_hash_comments(self, file_hash: str, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-comments-get """ return self._http_request("GET", f"files/{file_hash}/comments", params={"limit": limit}) def get_domain_comments(self, domain: str, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/domains-comments-get """ return self._http_request("GET", f"domains/{domain}/comments", params={"limit": limit}) def get_comment_by_id(self, comment_id: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/get-comment """ return self._http_request("GET", f"comments/{comment_id}") def add_comment(self, suffix: str, comment: str) -> dict: """Sending POST HTTP request to comment Args: suffix: suffix of the comment comment: the comment itself Returns: json of response """ return self._http_request("POST", suffix, json_data={"data": {"type": "comment", "attributes": {"text": comment}}}) def add_comment_to_ip(self, ip: str, comment: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/ip-comments-post """ return self.add_comment(f"ip_addresses/{ip}/comments", comment) def add_comment_to_url(self, url: str, comment: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/urls-comments-post """ return self.add_comment(f"urls/{encode_url_to_base64(url)}/comments", comment) def add_comment_to_domain(self, domain: str, comment: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/domains-comments-post """ return self.add_comment(f"domains/{domain}/comments", comment) def add_comment_to_file(self, resource: str, comment: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-comments-post """ return self.add_comment(f"files/{resource}/comments", comment) # endregion # region Scan calls def file_rescan(self, file_hash: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-analyse """ return self._http_request("POST", f"/files/{file_hash}/analyse") def file_scan(self, file_path: str, /, upload_url: Optional[str]) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-analyse """ response: requests.Response with open(file_path, "rb") as file: if upload_url or os.stat(file_path).st_size / (1024 * 1024) >= 32: if not upload_url: raw_response = self.get_upload_url() upload_url = raw_response["data"] response = self._http_request("POST", full_url=upload_url, files={"file": file}, resp_type="response") else: response = self._http_request("POST", url_suffix="/files", files={"file": file}, resp_type="response") demisto.debug(f"scan_file response:\n{response.status_code=!s}, {response.headers=!s}, {response.content!s}") return response.json() def private_file_scan(self, file_path: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/post_files-1 """ response: requests.Response with open(file_path, "rb") as file: if os.stat(file_path).st_size / (1024 * 1024) >= 32: raw_response = self.get_private_upload_url() upload_url = raw_response["data"] response = self._http_request("POST", full_url=upload_url, files={"file": file}, resp_type="response") else: response = self._http_request("POST", url_suffix="/private/files", files={"file": file}, resp_type="response") demisto.debug(f"scan_private_file response:\n{response.status_code=!s}, {response.headers=!s}, {response.content!s}") return response.json() def get_upload_url(self) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-upload-url """ return self._http_request("GET", "files/upload_url") def get_private_upload_url(self) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/private-files-upload-url """ return self._http_request("GET", "private/files/upload_url") def url_scan(self, url: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/urls-analyse """ return self._http_request("POST", "urls", data={"url": url}) def private_url_scan(self, url: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/private-scan-url """ return self._http_request("POST", "/private/urls", data={"url": url}) # endregion def file_sandbox_report(self, file_hash: dict, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-relationships """ return self._http_request("GET", f"files/{file_hash}/behaviours", params={"limit": limit}, ok_codes=(404, 429, 200)) def passive_dns_data(self, id: dict, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/ip-relationships """ return self._http_request( "GET", f'{"ip_addresses" if id["type"] == "ip" else "domains"}/{id["value"]}/resolutions', params={"limit": limit} ) def search(self, query: str, limit: int) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/intelligence-search """ return self._http_request("GET", "search", params={"query": query, "limit": limit}) def get_analysis(self, analysis_id: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/analysis """ return self._http_request("GET", f"/analyses/{analysis_id}") def get_private_analysis(self, analysis_id: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/private-analysis """ return self._http_request("GET", f"private/analyses/{analysis_id}") def get_private_item_from_analysis(self, analysis_id: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/analysesidrelationship """ return self._http_request("GET", f"private/analyses/{analysis_id}/item") def get_file_sigma_analysis(self, file_hash: str) -> dict: """ See Also: https://gtidocs.virustotal.com/reference/files-relationships """ return self._http_request( "GET", f"files/{file_hash}/sigma_analysis", ) def curated_collections(self, resource_id: str, resource_type: str, collection_type: str) -> dict: """Returns curated collections.""" if resource_type not in TYPE_TO_ENDPOINT: raise DemistoException(f'Could not find resource type of "{resource_type}"') if collection_type not in ("campaign", "malware-family", "threat-actor"): raise DemistoException(f'Could not find collection type of "{collection_type}"') if resource_type == "url": resource_id = encode_url_to_base64(resource_id) collection_type_filter = f"collection_type:{collection_type}" if collection_type == "malware-family": collection_type_filter = f"({collection_type_filter} OR collection_type:software-tookit)" return self._http_request( "GET", f"{TYPE_TO_ENDPOINT[resource_type]}/{resource_id}/associations", params={ "filter": f"owner:Mandiant {collection_type_filter}", "exclude_attributes": "aggregations", }, ok_codes=(404, 429, 200), ) class ScoreCalculator: """ Calculating DBotScore of files, ip, etc. """ DEFAULT_SUSPICIOUS_THRESHOLD = 5 DEFAULT_RELATIONSHIP_SUSPICIOUS_THRESHOLD = 2 GTI_MALICIOUS_VERDICT = "VERDICT_MALICIOUS" GTI_SUSPICIOUS_VERDICT = "VERDICT_SUSPICIOUS" logs: List[str] # General trusted_vendors_threshold: int trusted_vendors: List[str] gti_malicious: bool gti_suspicious: bool # IP ip_threshold: dict[str, int] # URL url_threshold: dict[str, int] # Domain domain_threshold: dict[str, int] domain_popularity_ranking: int # File file_threshold: dict[str, int] sigma_ids_threshold: int crowdsourced_yara_rules_enabled: bool crowdsourced_yara_rules_threshold: int def __init__(self, params: dict): self.trusted_vendors = argToList(params["preferredVendors"]) self.trusted_vendors_threshold = arg_to_number_must_int( params["preferredVendorsThreshold"], arg_name="Preferred Vendor Threshold", required=True ) self.file_threshold = { "malicious": arg_to_number_must_int(params["fileThreshold"], arg_name="File Malicious Threshold", required=True), "suspicious": arg_to_number_must_int( params["fileSuspiciousThreshold"] or self.DEFAULT_SUSPICIOUS_THRESHOLD, arg_name="File Suspicious Threshold", required=True, ), } self.ip_threshold = { "malicious": arg_to_number_must_int(params["ipThreshold"], arg_name="IP Malicious Threshold", required=True), "suspicious": arg_to_number_must_int( params["ipSuspiciousThreshold"] or self.DEFAULT_SUSPICIOUS_THRESHOLD, arg_name="IP Suspicious Threshold", required=True, ), } self.url_threshold = { "malicious": arg_to_number_must_int(params["urlThreshold"], arg_name="URL Malicious Threshold", required=True), "suspicious": arg_to_number_must_int( params["urlSuspiciousThreshold"] or self.DEFAULT_SUSPICIOUS_THRESHOLD, arg_name="URL Suspicious Threshold", required=True, ), } self.domain_threshold = { "malicious": arg_to_number_must_int(params["domainThreshold"], arg_name="Domain Malicious Threshold", required=True), "suspicious": arg_to_number_must_int( params["domainSuspiciousThreshold"] or self.DEFAULT_SUSPICIOUS_THRESHOLD, arg_name="Domain Suspicious Threshold", required=True, ), } self.crowdsourced_yara_rules_enabled = argToBoolean(params["crowdsourced_yara_rules_enabled"]) self.crowdsourced_yara_rules_threshold = arg_to_number_must_int(params["yaraRulesThreshold"]) self.sigma_ids_threshold = arg_to_number_must_int( params["SigmaIDSThreshold"], arg_name="Sigma and Intrusion Detection Rules Threshold", required=True ) self.domain_popularity_ranking = arg_to_number_must_int( params["domain_popularity_ranking"], arg_name="Domain Popularity Ranking Threshold", required=True ) self.gti_malicious = argToBoolean(params.get("gti_malicious", False)) self.gti_suspicious = argToBoolean(params.get("gti_suspicious", False)) self.logs = [] def get_logs(self) -> str: """Returns the log string""" return "\n".join(self.logs) def _is_by_threshold(self, analysis_stats: dict, threshold: int, suspicious: bool = False) -> bool: """Determines whatever the indicator malicious/suspicious by threshold. if number of malicious (+ suspicious) >= threshold -> Malicious (Suspicious) Args: analysis_stats: the analysis stats from the response. threshold: the threshold of the indicator type. suspicious: whether suspicious is also added. Returns: Whatever the indicator is malicious/suspicious by threshold. """ total = analysis_stats.get("malicious", 0) if suspicious: total += analysis_stats.get("suspicious", 0) verdict = "suspicious" if suspicious else "malicious" self.logs.append(f"{total} vendors found {verdict}.\nThe {verdict} threshold is {threshold}.") if total >= threshold: self.logs.append(f"Found as {verdict}: {total} >= {threshold}.") return True self.logs.append(f"Not found {verdict} by threshold: {total} < {threshold}.") return False def is_suspicious_by_threshold(self, analysis_stats: dict, threshold: int) -> bool: """Determines whatever the indicator suspicious by threshold. if number of malicious + suspicious >= threshold -> Suspicious Args: analysis_stats: the analysis stats from the response threshold: the threshold of the indicator type. Returns: Whatever the indicator is suspicious by threshold. """ return self._is_by_threshold(analysis_stats, threshold, suspicious=True) def is_good_by_popularity_ranks(self, popularity_ranks: dict) -> Optional[bool]: """Analyzing popularity ranks. if popularity ranks exist and average rank is < threshold -> Good Args: popularity_ranks: the popularity ranks object from response Returns: Whatever the indicator is good or not by popularity rank. """ if popularity_ranks: self.logs.append("Found popularity ranks. Analyzing.") average = sum(rank.get("rank", 0) for rank in popularity_ranks.values()) / len(popularity_ranks) self.logs.append(f"The average of the ranks is {average} and the threshold is {self.domain_popularity_ranking}") if average <= self.domain_popularity_ranking: self.logs.append("Indicator is good by popularity ranks.") return True else: self.logs.append("Indicator might not be good by it's popularity ranks.") return False self.logs.append("Could not determine rank by popularity, No popularity ranks data.") return None def is_suspicious_by_rules(self, file_response: dict) -> bool: """Check if indicator is suspicious by rules analysis. crowdsourced_yara_results >= yara_rules_threshold || sigma_analysis_stats.high + critical >= sigma_id_threshold || crowdsourced_ids_stats.high + critical >= sigma_id_threshold -> suspicious Args: file_response: the file response Returns: Whatever the file is suspicious by rules analysis. """ data = file_response.get("data", {}) if self.crowdsourced_yara_rules_enabled: self.logs.append("Crowdsourced Yara Rules analyzing enabled.") if (total_yara_rules := len(data.get("crowdsourced_yara_results", []))) >= self.crowdsourced_yara_rules_threshold: self.logs.append( "Found malicious by finding more Crowdsourced Yara Rules than threshold. \n" f"{total_yara_rules} >= {self.crowdsourced_yara_rules_threshold}" ) return True if sigma_rules := data.get("sigma_analysis_stats"): self.logs.append("Found sigma rules, analyzing.") sigma_high, sigma_critical = sigma_rules.get("high", 0), sigma_rules.get("critical", 0) if (sigma_high + sigma_critical) >= self.sigma_ids_threshold: self.logs.append(f"Found malicious, {sigma_high + sigma_critical} >= {self.sigma_ids_threshold}. ") return True else: self.logs.append("Not found malicious by sigma. ") else: self.logs.append("Not found sigma analysis. Skipping. ") if crowdsourced_ids_stats := data.get("crowdsourced_ids_stats"): self.logs.append("Found crowdsourced IDS analysis, analyzing. ") ids_high, ids_critical = crowdsourced_ids_stats.get("high"), crowdsourced_ids_stats.get("critical") if (ids_high + ids_critical) >= self.sigma_ids_threshold: self.logs.append(f"Found malicious, {(ids_high + ids_critical) >= self.sigma_ids_threshold}.") return True else: self.logs.append("Not found malicious by sigma.") else: self.logs.append("Not found crowdsourced IDS analysis. Skipping.") else: self.logs.append("Crowdsourced Yara Rules analyzing is not enabled. Skipping.") return False def is_preferred_vendors_pass_malicious(self, analysis_results: dict) -> bool: """Is the indicator counts as malicious by predefined malicious vendors. trusted_vendors.malicious >= trusted_vendors_threshold -> Malicious The function takes only the latest 20 results. Args: analysis_results: The results of the analysis. Returns: Whatever the indicator is malicious or not by preferred vendors. """ recent = {key: analysis_results[key] for key in list(analysis_results.keys())[:20]} preferred_vendor_scores = {vendor: recent[vendor] for vendor in self.trusted_vendors if vendor in recent} malicious_trusted_vendors = [item for item in preferred_vendor_scores.values() if item.get("category") == "malicious"] if len(malicious_trusted_vendors) >= self.trusted_vendors_threshold: self.logs.append( f"{len(malicious_trusted_vendors)} trusted vendors found the hash malicious. \n" f"The trusted vendors threshold is {self.trusted_vendors_threshold}. \n" f"Malicious check: {(len(malicious_trusted_vendors) >= self.trusted_vendors_threshold)=}. " ) return True else: self.logs.append( f"Those preferred vendors found the hash malicious: {malicious_trusted_vendors}. " f"They do not pass the threshold {self.trusted_vendors_threshold}. " ) return False def is_malicious_by_threshold(self, analysis_stats: dict, threshold: int) -> bool: """Determines whatever the indicator malicious by threshold. if number of malicious >= threshold -> Malicious Args: analysis_stats: the analysis stats from the response threshold: the threshold of the indicator type. Returns: Whatever the indicator is malicious by threshold. """ return self._is_by_threshold(analysis_stats, threshold) def score_by_threshold(self, analysis_stats: dict, threshold: dict[str, int]) -> int: """Determines the DBOTSCORE of the indicator by threshold only. Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ if self.is_malicious_by_threshold(analysis_stats, threshold["malicious"]): return Common.DBotScore.BAD if self.is_suspicious_by_threshold(analysis_stats, threshold["suspicious"]): return Common.DBotScore.SUSPICIOUS return Common.DBotScore.GOOD def score_by_results_and_stats(self, indicator: str, raw_response: dict, threshold: dict[str, int]) -> int: """Determines indicator score by popularity preferred vendors and threshold. Args: indicator: The indicator we analyzing. raw_response: The raw response from API. threshold: Threshold of the indicator. Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ self.logs.append(f'Basic analyzing of "{indicator}"') data = raw_response.get("data", {}) attributes = data.get("attributes", {}) popularity_ranks = attributes.get("popularity_ranks") last_analysis_results = attributes.get("last_analysis_results") last_analysis_stats = attributes.get("last_analysis_stats") if self.is_good_by_popularity_ranks(popularity_ranks): return Common.DBotScore.GOOD if self.is_preferred_vendors_pass_malicious(last_analysis_results): return Common.DBotScore.BAD return self.score_by_threshold(last_analysis_stats, threshold) def is_malicious_by_gti(self, gti_assessment: dict) -> bool: """Determines if an IoC is malicious according to its GTI assessment.""" if self.gti_malicious: return gti_assessment.get("verdict", {}).get("value") == self.GTI_MALICIOUS_VERDICT return False def is_suspicious_by_gti(self, gti_assessment: dict) -> bool: """Determines if an IoC is suspicious according to its GTI assessment.""" if self.gti_suspicious: return gti_assessment.get("verdict", {}).get("value") == self.GTI_SUSPICIOUS_VERDICT return False def file_score(self, given_hash: str, raw_response: dict) -> int: """Analyzing file score. The next parameters are analyzed: Preferred vendors Score by threshold Score by rules analysis (YARA, IDS and Sigma, if presents) Args: given_hash: The hash we're analyzing raw_response: The response from the API Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ self.logs.append(f"Analysing file hash {given_hash}.") data = raw_response.get("data", {}) attributes = data.get("attributes", {}) analysis_results = attributes.get("last_analysis_results", {}) analysis_stats = attributes.get("last_analysis_stats", {}) # GTI assessment if self.is_malicious_by_gti(attributes.get("gti_assessment", {})): return Common.DBotScore.BAD # Trusted vendors if self.is_preferred_vendors_pass_malicious(analysis_results): return Common.DBotScore.BAD score = self.score_by_threshold(analysis_stats, self.file_threshold) if score == Common.DBotScore.BAD: return Common.DBotScore.BAD suspicious_by_rules = self.is_suspicious_by_rules(raw_response) if score == Common.DBotScore.SUSPICIOUS and suspicious_by_rules: self.logs.append( f'Hash: "{given_hash}" was found malicious as the hash is suspicious both by threshold and rules analysis.' ) return Common.DBotScore.BAD elif suspicious_by_rules: self.logs.append(f'Hash: "{given_hash}" was found suspicious by rules analysis.') return Common.DBotScore.SUSPICIOUS elif score == Common.DBotScore.SUSPICIOUS: self.logs.append(f'Hash: "{given_hash}" was found suspicious by passing the threshold analysis.') return Common.DBotScore.SUSPICIOUS elif self.is_suspicious_by_gti(attributes.get("gti_assessment", {})): self.logs.append(f'Hash: "{given_hash}" was found suspicious by gti assessment.') return Common.DBotScore.SUSPICIOUS self.logs.append(f'Hash: "{given_hash}" was found good.') return Common.DBotScore.GOOD # Nothing caught def ip_score(self, indicator: str, raw_response: dict) -> int: """Determines indicator score by popularity preferred vendors and threshold. Args: indicator: The indicator we analyzing. raw_response: The response from the API Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ data = raw_response.get("data", {}) attributes = data.get("attributes", {}) # GTI assessment if self.is_malicious_by_gti(attributes.get("gti_assessment", {})): return Common.DBotScore.BAD score = self.score_by_results_and_stats(indicator, raw_response, self.ip_threshold) if score == Common.DBotScore.GOOD and self.is_suspicious_by_gti(attributes.get("gti_assessment", {})): score = Common.DBotScore.SUSPICIOUS return score def url_score(self, indicator: str, raw_response: dict) -> int: """Determines indicator score by popularity preferred vendors and threshold. Args: indicator: The indicator we analyzing. raw_response: The raw response from API. Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ data = raw_response.get("data", {}) attributes = data.get("attributes", {}) # GTI assessment if self.is_malicious_by_gti(attributes.get("gti_assessment", {})): return Common.DBotScore.BAD score = self.score_by_results_and_stats(indicator, raw_response, self.url_threshold) if score == Common.DBotScore.GOOD and self.is_suspicious_by_gti(attributes.get("gti_assessment", {})): score = Common.DBotScore.SUSPICIOUS return score def domain_score(self, indicator: str, raw_response: dict) -> int: """Determines indicator score by popularity preferred vendors and threshold. Args: indicator: The indicator we analyzing. raw_response: The raw response from API. Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ data = raw_response.get("data", {}) attributes = data.get("attributes", {}) if self.is_malicious_by_gti(attributes.get("gti_assessment", {})): return Common.DBotScore.BAD score = self.score_by_results_and_stats(indicator, raw_response, self.domain_threshold) if score == Common.DBotScore.GOOD and self.is_suspicious_by_gti(attributes.get("gti_assessment", {})): score = Common.DBotScore.SUSPICIOUS return score def calculate_cve_dbot_score(self, cvss_score) -> int: """Calculates the DBotScore for a CVE based on its CVSS score. Args: cvss_score: The CVSS score of the CVE. Returns: DBotScore of the indicator. Can by Common.DBotScore.BAD, Common.DBotScore.SUSPICIOUS or Common.DBotScore.GOOD """ try: score = float(cvss_score) except ValueError: return Common.DBotScore.NONE if not score: return Common.DBotScore.NONE elif 0.0 <= score <= 3.9: return Common.DBotScore.GOOD elif 3.9 < score <= 7.9: return Common.DBotScore.SUSPICIOUS elif 7.9 < score <= 10.0: return Common.DBotScore.BAD else: return Common.DBotScore.NONE # endregion # region Helper functions def create_relationships(entity_a: str, entity_a_type: str, relationships_response: dict, reliability): """ Create a list of entityRelationship object from the api result entity_a: (str) - source of the relationship entity_a_type: (str) - type of the source of the relationship relationships_response: (dict) - the relationship response from the api reliability: The reliability of the source. Returns a list of EntityRelationship objects. """ relationships_list: List[EntityRelationship] = [] for relationship_type, relationship_type_raw in relationships_response.items(): relationships_data = relationship_type_raw.get("data", []) if relationships_data: if isinstance(relationships_data, dict): relationships_data = [relationships_data] for relation in relationships_data: name = RELATIONSHIP_TYPE.get(entity_a_type.lower(), {}).get(relationship_type) entity_b = relation.get("id", "") entity_b_type = INDICATOR_TYPE.get(relation.get("type", "").lower()) if entity_b and entity_b_type and name: if entity_b_type == FeedIndicatorType.URL: entity_b = dict_safe_get(relation, ["context_attributes", "url"]) relationships_list.append( EntityRelationship( entity_a=entity_a, entity_a_type=entity_a_type, name=name, entity_b=entity_b, entity_b_type=entity_b_type, source_reliability=reliability, brand=INTEGRATION_NAME, ) ) else: demisto.info( f"WARNING: Relationships will not be created to entity A {entity_a} with relationship name {name}" ) return relationships_list def create_relationships_cve( entity_a: str, entity_a_type: str, relationships_response: dict, reliability: DBotScoreReliability ) -> List[EntityRelationship]: """ Create relationships between CVE and related files (MD5 hashes from sources) Args: entity_a (str): The source of the relationship entity_a_type (str): The type of the source of the relationship relationships_response (dict): The relationship response from the api reliability (DBotScoreReliability): The reliability of the source. Returns: List[EntityRelationship]: List of EntityRelationship objects """ relationships_list: List[EntityRelationship] = [] # Extract sources from CVE response sources = relationships_response.get("data", {}).get("attributes", {}).get("sources", []) for source in sources: md5_hash = source.get("md5") if md5_hash: # Only create relationship if MD5 exists relationships_list.append( EntityRelationship( entity_a=entity_a, entity_a_type=entity_a_type, name=RELATIONSHIP_TYPE.get("cve", {}).get("referrer_cve"), entity_b=md5_hash, entity_b_type=FeedIndicatorType.File, source_reliability=reliability, brand=INTEGRATION_NAME, ) ) return relationships_list def arg_to_number_must_int(arg: Any, arg_name: Optional[str] = None, required: bool = False): """Wrapper of arg_to_number that must return int For mypy fixes. """ arg_num = arg_to_number(arg, arg_name, required) assert isinstance(arg_num, int) return arg_num def epoch_to_timestamp(epoch: Union[int, str]) -> Optional[str]: """Converts epoch timestamp to a string. Args: epoch: Time to convert Returns: A formatted string if succeeded. if not, returns None. """ try: return datetime.utcfromtimestamp(int(epoch)).strftime("%Y-%m-%d %H:%M:%SZ") except (TypeError, OSError, ValueError): return None def decrease_data_size(data: Union[dict, list]) -> Union[dict, list]: """Minifying data size. Args: data: the data object from raw response Returns: the same data without: data['attributes']['last_analysis_results'] data['attributes']['pe_info'] data['attributes']['crowdsourced_ids_results'] data['attributes']['autostart_locations'] data['attributes']['sandbox_verdicts'] data['attributes']['sigma_analysis_summary'] """ attributes_to_remove = [ "last_analysis_results", "pe_info", "crowdsourced_ids_results", "autostart_locations", "sandbox_verdicts", "sigma_analysis_summary", ] if isinstance(data, list): data = [decrease_data_size(item) for item in data] else: for attribute in attributes_to_remove: data["attributes"].pop(attribute, None) return data def _get_error_result(client: Client, ioc_id: str, ioc_type: str, message: str) -> CommandResults: dbot_type = ioc_type.upper() assert dbot_type in ("FILE", "DOMAIN", "IP", "URL", "CVE") common_type = dbot_type if dbot_type in ("IP", "URL", "CVE") else dbot_type.capitalize() desc = f'{common_type} "{ioc_id}" {message}' dbot = Common.DBotScore( ioc_id, getattr(DBotScoreType, dbot_type), INTEGRATION_NAME, Common.DBotScore.NONE, desc, client.reliability ) options: dict[str, Common.DBotScore | str] = {"dbot_score": dbot} if dbot_type == "FILE": if (hash_type := get_hash_type(ioc_id)) != "Unknown": options[hash_type] = ioc_id elif dbot_type == "CVE": options.update({"id": ioc_id, "cvss": "0.0", "published": "", "modified": "", "description": desc}) else: options[dbot_type.lower()] = ioc_id return CommandResults(indicator=getattr(Common, common_type)(**options), readable_output=desc) def build_unknown_output(client: Client, ioc_id: str, ioc_type: str) -> CommandResults: return _get_error_result(client, ioc_id, ioc_type, "was not found in GoogleThreatIntelligence.") def build_quota_exceeded_output(client: Client, ioc_id: str, ioc_type: str) -> CommandResults: return _get_error_result(client, ioc_id, ioc_type, "was not enriched. Quota was exceeded.") def build_error_output(client: Client, ioc_id: str, ioc_type: str, error_msg: str = None) -> CommandResults: msg = "could not be processed." if error_msg: msg += f" Error: {error_msg}" return _get_error_result(client, ioc_id, ioc_type, msg) def build_unknown_file_output(client: Client, file: str) -> CommandResults: return build_unknown_output(client, file, "file") def build_quota_exceeded_file_output(client: Client, file: str) -> CommandResults: return build_quota_exceeded_output(client, file, "file") def build_error_file_output(client: Client, file: str, error_msg: str = None) -> CommandResults: return build_error_output(client, file, "file", error_msg) def build_unknown_domain_output(client: Client, domain: str) -> CommandResults: return build_unknown_output(client, domain, "domain") def build_quota_exceeded_domain_output(client: Client, domain: str) -> CommandResults: return build_quota_exceeded_output(client, domain, "domain") def build_error_domain_output(client: Client, domain: str, error_msg: str = None) -> CommandResults: return build_error_output(client, domain, "domain", error_msg) def build_unknown_url_output(client: Client, url: str) -> CommandResults: return build_unknown_output(client, url, "url") def build_quota_exceeded_url_output(client: Client, url: str) -> CommandResults: return build_quota_exceeded_output(client, url, "url") def build_error_url_output(client: Client, url: str, error_msg: str = None) -> CommandResults: return build_error_output(client, url, "url", error_msg) def build_unknown_ip_output(client: Client, ip: str) -> CommandResults: return build_unknown_output(client, ip, "ip") def build_quota_exceeded_ip_output(client: Client, ip: str) -> CommandResults: return build_quota_exceeded_output(client, ip, "ip") def build_error_ip_output(client: Client, ip: str, error_msg: str = None) -> CommandResults: return build_error_output(client, ip, "ip", error_msg) def build_skipped_enrichment_ip_output(client: Client, ip: str) -> CommandResults: return _get_error_result( client, ip, "ip", "was not enriched. Reputation lookups have been disabled for private IP addresses." ) def build_unknown_cve_output(client: Client, cve_id: str) -> CommandResults: return build_unknown_output(client, cve_id, "cve") def build_quota_exceeded_cve_output(client: Client, cve_id: str) -> CommandResults: return build_quota_exceeded_output(client, cve_id, "cve") def build_error_cve_output(client: Client, cve_id: str, error_msg: str = None) -> CommandResults: return build_error_output(client, cve_id, "cve", error_msg) def _get_domain_indicator(client: Client, score_calculator: ScoreCalculator, domain: str, raw_response: dict): data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) detection_engines = sum(last_analysis_stats.values()) positive_detections = last_analysis_stats.get("malicious", 0) whois = get_whois(attributes.get("whois", "")) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=domain, entity_a_type=FeedIndicatorType.Domain, relationships_response=relationships_response, reliability=client.reliability, ) score = score_calculator.domain_score(domain, raw_response) logs = score_calculator.get_logs() demisto.debug(logs) return Common.Domain( domain=domain, name_servers=whois["Name Server"], creation_date=whois["Creation Date"], updated_date=whois["Updated Date"], expiration_date=whois["Registry Expiry Date"], admin_name=whois["Admin Organization"], admin_email=whois["Admin Email"], admin_country=whois["Admin Country"], registrant_email=whois["Registrant Email"], registrant_country=whois["Registrant Country"], registrar_name=whois["Registrar"], registrar_abuse_email=whois["Registrar Abuse Contact Email"], registrar_abuse_phone=whois["Registrar Abuse Contact Phone"], detection_engines=detection_engines, positive_detections=positive_detections, dbot_score=Common.DBotScore( domain, DBotScoreType.DOMAIN, INTEGRATION_NAME, score=score, malicious_description=logs, reliability=client.reliability, ), relationships=relationships_list, ) def _get_url_indicator(client: Client, score_calculator: ScoreCalculator, url: str, raw_response: dict): data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) detection_engines = sum(last_analysis_stats.values()) positive_detections = last_analysis_stats.get("malicious", 0) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=url, entity_a_type=FeedIndicatorType.URL, relationships_response=relationships_response, reliability=client.reliability, ) score = score_calculator.url_score(url, raw_response) logs = score_calculator.get_logs() demisto.debug(logs) return Common.URL( url, category=attributes.get("categories"), detection_engines=detection_engines, positive_detections=positive_detections, relationships=relationships_list, dbot_score=Common.DBotScore( url, DBotScoreType.URL, INTEGRATION_NAME, score=score, reliability=client.reliability, malicious_description=logs ), ) def _get_ip_indicator(client: Client, score_calculator: ScoreCalculator, ip: str, raw_response: dict): data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) detection_engines = sum(last_analysis_stats.values()) positive_engines = last_analysis_stats.get("malicious", 0) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=ip, entity_a_type=FeedIndicatorType.IP, relationships_response=relationships_response, reliability=client.reliability, ) score = score_calculator.ip_score(ip, raw_response) logs = score_calculator.get_logs() demisto.debug(logs) return Common.IP( ip, asn=attributes.get("asn"), geo_country=attributes.get("country"), detection_engines=detection_engines, positive_engines=positive_engines, as_owner=attributes.get("as_owner"), relationships=relationships_list, dbot_score=Common.DBotScore( ip, DBotScoreType.IP, INTEGRATION_NAME, score=score, malicious_description=logs, reliability=client.reliability ), ) def _get_file_indicator(client: Client, score_calculator: ScoreCalculator, file_hash: str, raw_response: dict): data = raw_response.get("data", {}) attributes = data.get("attributes", {}) exiftool = attributes.get("exiftool", {}) signature_info = attributes.get("signature_info", {}) score = score_calculator.file_score(file_hash, raw_response) logs = score_calculator.get_logs() demisto.debug(logs) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=file_hash, entity_a_type=FeedIndicatorType.File, relationships_response=relationships_response, reliability=client.reliability, ) return Common.File( dbot_score=Common.DBotScore( file_hash, DBotScoreType.FILE, integration_name=INTEGRATION_NAME, score=score, malicious_description=logs, reliability=client.reliability, ), name=exiftool.get("OriginalFileName"), size=attributes.get("size"), sha1=attributes.get("sha1"), sha256=attributes.get("sha256"), file_type=exiftool.get("MIMEType"), md5=attributes.get("md5"), ssdeep=attributes.get("ssdeep"), extension=exiftool.get("FileTypeExtension"), company=exiftool.get("CompanyName"), product_name=exiftool.get("ProductName"), tags=attributes.get("tags"), signature=Common.FileSignature( authentihash=attributes.get("authentihash"), copyright=signature_info.get("copyright"), file_version=signature_info.get("file version"), description=signature_info.get("description"), internal_name=signature_info.get("internal name"), original_name=signature_info.get("original name"), ), relationships=relationships_list, ) def _extract_cve_data(raw_response: dict) -> dict: """ Extract and process CVE data from API response. Args: raw_response: Raw API response from CVE endpoint Returns: Dictionary containing processed CVE data """ data = raw_response.get("data", {}) attributes = data.get("attributes", {}) # Extract CVE-specific information description = attributes.get("description", "") executive_summary = attributes.get("executive_summary", "") # CVSS scores cvss = attributes.get("cvss", {}) cvss_v3 = cvss.get("cvssv3_x", {}) cvss_v4 = cvss.get("cvssv4_x", {}) cvss_v3_score = cvss_v3.get("base_score", 0) if cvss_v3 else 0 cvss_v4_score = cvss_v4.get("score", 0) if cvss_v4 else 0 cvss_v3_vector = cvss_v3.get("vector", "") if cvss_v3 else "" cvss_v4_vector = cvss_v4.get("vector", "") if cvss_v4 else "" # Risk and exploitation information risk_rating = attributes.get("risk_rating", "") exploitation_state = attributes.get("exploitation_state", "") exploit_availability = attributes.get("exploit_availability", "") priority = attributes.get("priority", "") # Process dates creation_date = attributes.get("creation_date") date_of_disclosure = attributes.get("date_of_disclosure") last_modification_date = attributes.get("last_modification_date") if creation_date: creation_date = timestamp_to_datestring(creation_date * 1000) if last_modification_date: last_modification_date = timestamp_to_datestring(last_modification_date * 1000) if date_of_disclosure: date_of_disclosure = timestamp_to_datestring(date_of_disclosure * 1000) # Sources and counters sources = attributes.get("sources", []) tags = attributes.get("tags", []) counters = attributes.get("counters", {}) extracted_data = { "description": description, "executive_summary": executive_summary, "cvss_v3_score": cvss_v3_score, "cvss_v4_score": cvss_v4_score, "cvss_v3_vector": cvss_v3_vector, "cvss_v4_vector": cvss_v4_vector, "risk_rating": risk_rating, "exploitation_state": exploitation_state, "exploit_availability": exploit_availability, "priority": priority, "creation_date": creation_date, "date_of_disclosure": date_of_disclosure, "last_modification_date": last_modification_date, "sources_count": len(sources), "tags": tags, "files_count": counters.get("files"), "domains_count": counters.get("domains"), "ip_addresses_count": counters.get("ip_addresses"), "urls_count": counters.get("urls"), } return extracted_data def _create_cve_indicator( client: Client, score_calculator: ScoreCalculator, cve_id: str, cve_data: dict, raw_response: dict ) -> tuple[Common.CVE, list]: """ Create CVE indicator with relationships and DBot score. Args: client: Client instance score_calculator: Score calculator instance cve_id: CVE identifier cve_data: Processed CVE data from _extract_cve_data raw_response: Raw API response Returns: Tuple of (CVE indicator, relationships list) """ # Calculate DBot score cvss_score = cve_data.get("cvss_v4_score") if cve_data.get("cvss_v4_score") else cve_data.get("cvss_v3_score") score = score_calculator.calculate_cve_dbot_score(cvss_score) dbot_score = Common.DBotScore( indicator=cve_id, indicator_type=DBotScoreType.CVE, integration_name=INTEGRATION_NAME, score=score, reliability=client.reliability, ) # Create relationships relationships = create_relationships_cve( entity_a=cve_id, entity_a_type=FeedIndicatorType.CVE, relationships_response=raw_response, reliability=client.reliability ) # Create CVE indicator cve_indicator = Common.CVE( id=cve_id, cvss=str(cvss_score) if cvss_score else "0.0", published=cve_data.get("date_of_disclosure", ""), modified=cve_data.get("last_modification_date", ""), description=cve_data.get("description", "No description available"), cvss_vector=cve_data.get("cvss_v4_vector", "") if cve_data.get("cvss_v4_vector", "") else cve_data.get("cvss_v3_vector", ""), dbot_score=dbot_score, relationships=relationships, tags=cve_data.get("tags", ""), stix_id=cve_id, ) return cve_indicator, relationships def build_domain_output( client: Client, score_calculator: ScoreCalculator, domain: str, raw_response: dict, extended_data: bool ) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) positive_engines = last_analysis_stats.get("malicious", 0) detection_engines = sum(last_analysis_stats.values()) whois = get_whois(attributes.get("whois", "")) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=domain, entity_a_type=FeedIndicatorType.Domain, relationships_response=relationships_response, reliability=client.reliability, ) domain_indicator = _get_domain_indicator(client, score_calculator, domain, raw_response) if not extended_data: data = decrease_data_size(data) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.Domain", outputs_key_field="id", indicator=domain_indicator, readable_output=tableToMarkdown( f"Domain data of {domain}", { **data, **attributes, **whois, "last_modified": epoch_to_timestamp(attributes.get("last_modification_date")), "positives": f"{positive_engines}/{detection_engines}", "gti_threat_score": attributes.get("gti_assessment", {}).get("threat_score", {}).get("value"), "gti_severity": attributes.get("gti_assessment", {}).get("severity", {}).get("value"), "gti_verdict": attributes.get("gti_assessment", {}).get("verdict", {}).get("value"), }, headers=[ "id", "Registrant Country", "Registrar", "last_modified", "reputation", "positives", "gti_threat_score", "gti_severity", "gti_verdict", ], removeNull=True, headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, relationships=relationships_list, ) def build_url_output( client: Client, score_calculator: ScoreCalculator, url: str, raw_response: dict, extended_data: bool ) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) positive_detections = last_analysis_stats.get("malicious", 0) detection_engines = sum(last_analysis_stats.values()) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=url, entity_a_type=FeedIndicatorType.URL, relationships_response=relationships_response, reliability=client.reliability, ) url_indicator = _get_url_indicator(client, score_calculator, url, raw_response) if not extended_data: data = decrease_data_size(data) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.URL", outputs_key_field="id", indicator=url_indicator, readable_output=tableToMarkdown( f'URL data of "{url}"', { **data, **attributes, "url": url, "last_modified": epoch_to_timestamp(attributes.get("last_modification_date")), "positives": f"{positive_detections}/{detection_engines}", "gti_threat_score": attributes.get("gti_assessment", {}).get("threat_score", {}).get("value"), "gti_severity": attributes.get("gti_assessment", {}).get("severity", {}).get("value"), "gti_verdict": attributes.get("gti_assessment", {}).get("verdict", {}).get("value"), }, headers=[ "url", "title", "has_content", "last_http_response_content_sha256", "last_modified", "reputation", "positives", "gti_threat_score", "gti_severity", "gti_verdict", ], removeNull=True, headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, relationships=relationships_list, ) def build_private_url_output(url: str, raw_response: dict) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) positive_detections = last_analysis_stats.get("malicious", 0) detection_engines = sum(last_analysis_stats.values()) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.URL", outputs_key_field="id", readable_output=tableToMarkdown( f'URL data of "{url}"', { **attributes, "positives": f"{positive_detections}/{detection_engines}", }, headers=[ "url", "title", "last_http_response_content_sha256", "positives", ], removeNull=True, headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, ) def build_ip_output( client: Client, score_calculator: ScoreCalculator, ip: str, raw_response: dict, extended_data: bool ) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) positive_engines = last_analysis_stats.get("malicious", 0) detection_engines = sum(last_analysis_stats.values()) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=ip, entity_a_type=FeedIndicatorType.IP, relationships_response=relationships_response, reliability=client.reliability, ) ip_indicator = _get_ip_indicator(client, score_calculator, ip, raw_response) if not extended_data: data = decrease_data_size(data) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.IP", outputs_key_field="id", indicator=ip_indicator, readable_output=tableToMarkdown( f"IP reputation of {ip}:", { **data, **attributes, "last_modified": epoch_to_timestamp(attributes.get("last_modification_date")), "positives": f"{positive_engines}/{detection_engines}", "gti_threat_score": attributes.get("gti_assessment", {}).get("threat_score", {}).get("value"), "gti_severity": attributes.get("gti_assessment", {}).get("severity", {}).get("value"), "gti_verdict": attributes.get("gti_assessment", {}).get("verdict", {}).get("value"), }, headers=[ "id", "network", "country", "as_owner", "last_modified", "reputation", "positives", "gti_threat_score", "gti_severity", "gti_verdict", ], headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, relationships=relationships_list, ) def build_file_output( client: Client, score_calculator: ScoreCalculator, file_hash: str, raw_response: dict, extended_data: bool ) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) last_analysis_stats = attributes.get("last_analysis_stats", {}) malicious = last_analysis_stats.get("malicious", 0) total = sum(last_analysis_stats.values()) relationships_response = data.get("relationships", {}) relationships_list = create_relationships( entity_a=file_hash, entity_a_type=FeedIndicatorType.File, relationships_response=relationships_response, reliability=client.reliability, ) file_indicator = _get_file_indicator(client, score_calculator, file_hash, raw_response) if not extended_data: data = decrease_data_size(data) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.File", outputs_key_field="id", indicator=file_indicator, readable_output=tableToMarkdown( f"Results of file hash {file_hash}", { **data, **attributes, "positives": f"{malicious}/{total}", "creation_date": epoch_to_timestamp(attributes.get("creation_date")), "last_modified": epoch_to_timestamp(attributes.get("last_modification_date", 0)), "gti_threat_score": attributes.get("gti_assessment", {}).get("threat_score", {}).get("value"), "gti_severity": attributes.get("gti_assessment", {}).get("severity", {}).get("value"), "gti_verdict": attributes.get("gti_assessment", {}).get("verdict", {}).get("value"), }, headers=[ "sha1", "sha256", "md5", "meaningful_name", "type_extension", "creation_date", "last_modified", "reputation", "positives", "gti_threat_score", "gti_severity", "gti_verdict", ], removeNull=True, headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, relationships=relationships_list, ) def build_cve_output(client: Client, score_calculator: ScoreCalculator, cve_id: str, raw_response: dict) -> CommandResults: """ Build CommandResults for CVE data from collections endpoint. Args: client: Client instance score_calculator: Score calculator instance cve_id: CVE identifier raw_response: Raw API response Returns: CommandResults with CVE information """ # Extract and process CVE data cve_data = _extract_cve_data(raw_response) # Create CVE indicator and relationships cve_indicator, relationships = _create_cve_indicator(client, score_calculator, cve_id, cve_data, raw_response) context_data = remove_empty_elements(raw_response.get("data", {})) # Prepare human-readable output hr_data = { "CVE ID": cve_id, "Description": cve_data.get("description", ""), "Executive Summary": cve_data.get("executive_summary", ""), "Risk Rating": cve_data.get("risk_rating", ""), "Priority": cve_data.get("priority", ""), "CVSS v3.x Score": cve_data.get("cvss_v3_score"), "CVSS v3.x Vector": cve_data.get("cvss_v3_vector"), "CVSS v4.x Score": cve_data.get("cvss_v4_score"), "CVSS v4.x Vector": cve_data.get("cvss_v4_vector"), "Exploitation State": cve_data.get("exploitation_state"), "Exploit Availability": cve_data.get("exploit_availability"), "Date Of Disclosure": cve_data.get("date_of_disclosure", ""), "Creation Date": cve_data.get("creation_date", ""), "Last Modified": cve_data.get("last_modification_date", ""), "Sources": cve_data.get("sources_count"), "Related Files": cve_data.get("files_count"), "Related Domains": cve_data.get("domains_count"), "Related IPs": cve_data.get("ip_addresses_count"), "Related URLs": cve_data.get("urls_count"), } hr_for_cve = tableToMarkdown( f"CVE Information: {cve_id}", hr_data, removeNull=True, headers=[ "CVE ID", "Risk Rating", "Priority", "Exploitation State", "Exploit Availability", "CVSS v3.x Score", "CVSS v4.x Score", "CVSS v3.x Vector", "CVSS v4.x Vector", "Date Of Disclosure", "Creation Date", "Last Modified", "Sources", "Description", "Related Files", "Related Domains", "Related IPs", "Related URLs", "Executive Summary", ], ) return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.CVE", outputs_key_field="id", indicator=cve_indicator, readable_output=hr_for_cve, outputs=context_data, raw_response=raw_response, relationships=relationships, ) def build_private_file_output(file_hash: str, raw_response: dict) -> CommandResults: data = raw_response.get("data", {}) attributes = data.get("attributes", {}) threat_severity = attributes.get("threat_severity", {}) threat_severity_level = threat_severity.get("threat_severity_level", "") threat_severity_data = threat_severity.get("threat_severity_data", {}) popular_threat_category = threat_severity_data.get("popular_threat_category", "") threat_verdict = attributes.get("threat_verdict", "") return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.File", outputs_key_field="id", readable_output=tableToMarkdown( f"Results of file hash {file_hash}", { **attributes, "threat_severity_level": SEVERITY_LEVELS.get(threat_severity_level, threat_severity_level), "popular_threat_category": popular_threat_category, "threat_verdict": VERDICTS.get(threat_verdict, threat_verdict), }, headers=[ "sha1", "sha256", "md5", "meaningful_name", "type_extension", "threat_severity_level", "popular_threat_category", "threat_verdict", ], removeNull=True, headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, ) def get_whois(whois_string: str) -> defaultdict: """Gets a WHOIS string and returns a parsed dict of the WHOIS String. Args: whois_string: whois from domain api call Returns: A parsed whois Examples: >>> get_whois('key1:value\\nkey2:value2') defaultdict({'key1': 'value', 'key2': 'value2'}) """ whois: defaultdict = defaultdict(lambda: None) for line in whois_string.splitlines(): key: str value: str try: key, value = line.split(sep=":", maxsplit=1) except ValueError: demisto.debug(f"Could not unpack Whois string: {line}. Skipping") continue key = key.strip() value = value.strip() if key in whois: if not isinstance(whois[key], list): whois[key] = [whois[key]] whois[key].append(value) else: whois[key] = value return whois def get_file_context(entry_id: str) -> dict: """Gets a File object from context. Args: entry_id: The entry ID of the file Returns: File object contains Name, Hashes and more information """ context = demisto.dt(demisto.context(), f'File(val.EntryID === "{entry_id}")') if not context: return {} if isinstance(context, list): return context[0] return context def validate_cve_values(cve_ids: list[str]) -> tuple[list[str], list[str]]: """ Validate CVE format and return valid/invalid CVE lists. Args: cve_ids: List of CVE identifiers to validate Returns: Tuple of (valid_cves, invalid_cves) """ valid_cves = [] invalid_cves = [] # CVE format: CVE-YYYY-NNNNN (where YYYY is year, NNNNN is 4+ digits) cve_pattern = re.compile(r"^CVE-\d{4}-\d{4,}$", re.IGNORECASE) for cve_id in cve_ids: normalized_cve = cve_id.upper().strip() if cve_pattern.match(normalized_cve): valid_cves.append(normalized_cve) else: invalid_cves.append(cve_id) return valid_cves, invalid_cves def raise_if_ip_not_valid(ip: str): """Raises an error if ip is not valid Args: ip: ip address Raises: ValueError: If IP is not valid Examples: >>> raise_if_ip_not_valid('not ip at all') Traceback (most recent call last): ... ValueError: IP "not ip at all" is not valid >>> raise_if_ip_not_valid('8.8.8.8') """ if not is_ip_valid(ip, accept_v6_ips=True): raise ValueError(f'IP "{ip}" is not valid') def raise_if_hash_not_valid(file_hash: str): """Raises an error if file_hash is not valid Args: file_hash: file hash Raises: ValueError: if hash is not of type SHA-256, SHA-1 or MD5 Examples: >>> raise_if_hash_not_valid('not a hash') Traceback (most recent call last): ... ValueError: Hash "not a hash" is not of type SHA-256, SHA-1 or MD5 >>> raise_if_hash_not_valid('7e641f6b9706d860baf09fe418b6cc87') """ if get_hash_type(file_hash) not in ("sha256", "sha1", "md5"): raise ValueError(f'Hash "{file_hash}" is not of type SHA-256, SHA-1 or MD5') def encode_url_to_base64(url: str) -> str: """Gets a string (in this case, url but it can not be) and return it as base64 without padding ('=') Args: url: A string to encode Returns: Base64 encoded string with no padding Examples: >>> encode_url_to_base64('https://example.com') 'aHR0cHM6Ly9leGFtcGxlLmNvbQ' """ return base64.urlsafe_b64encode(url.encode()).decode().strip("=") # endregion # region Reputation commands def ip_command( client: Client, score_calculator: ScoreCalculator, args: dict, relationships: str, disable_private_ip_lookup: bool ) -> List[CommandResults]: """ 1 API Call for regular """ ips = argToList(args["ip"]) results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() override_private_lookup = argToBoolean(args.get("override_private_lookup", False)) for ip in ips: raise_if_ip_not_valid(ip) if disable_private_ip_lookup and ipaddress.ip_address(ip).is_private and not override_private_lookup: results.append(build_skipped_enrichment_ip_output(client, ip)) execution_metrics.success += 1 continue try: raw_response = client.ip(ip, relationships) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_ip_output(client, ip)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_ip_output(client, ip)) continue except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process IP: "{ip}"\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_ip_output(client, ip, str(exc))) continue execution_metrics.success += 1 results.append( build_ip_output(client, score_calculator, ip, raw_response, argToBoolean(args.get("extended_data", False))) ) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def file_command(client: Client, score_calculator: ScoreCalculator, args: dict, relationships: str) -> List[CommandResults]: """ 1 API Call """ files = argToList(args["file"]) extended_data = argToBoolean(args.get("extended_data", False)) results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() for file in files: try: raise_if_hash_not_valid(file) raw_response = client.file(file, relationships) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_file_output(client, file)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_file_output(client, file)) continue results.append(build_file_output(client, score_calculator, file, raw_response, extended_data)) execution_metrics.success += 1 except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process file: "{file}"\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_file_output(client, file, str(exc))) continue if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def private_file_command(client: Client, args: dict) -> List[CommandResults]: """ 1 API Call """ files = argToList(args["file"]) results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() for file in files: try: raise_if_hash_not_valid(file) raw_response = client.private_file(file) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_file_output(client, file)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_file_output(client, file)) continue results.append(build_private_file_output(file, raw_response)) execution_metrics.success += 1 except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process private file: "{file}"\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_file_output(client, file, str(exc))) continue if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def url_command(client: Client, score_calculator: ScoreCalculator, args: dict, relationships: str) -> List[CommandResults]: """ 1 API Call for regular """ urls = argToList(args["url"]) extended_data = argToBoolean(args.get("extended_data", False)) results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() for url in urls: try: raw_response = client.url(url, relationships) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_url_output(client, url)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_url_output(client, url)) continue except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process URL: "{url}".\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_url_output(client, url, str(exc))) continue execution_metrics.success += 1 results.append(build_url_output(client, score_calculator, url, raw_response, extended_data)) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def cve_command(client: Client, score_calculator: ScoreCalculator, args: dict) -> List[CommandResults]: """ Get CVE information from Google Threat Intelligence collections endpoint. Args: client: Client instance args: Command arguments containing 'cve' parameter Returns: List of CommandResults with CVE information """ cve_ids = argToList(args.get("cve", [])) cve_ids = [cve_id.strip() for cve_id in cve_ids if cve_id.strip()] results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() # Validate CVE format (CVE-YYYY-NNNNN) valid_cves, invalid_cves = validate_cve_values(cve_ids) if invalid_cves: return_warning( "The following CVEs were found invalid: {}".format(", ".join(invalid_cves)), exit=len(invalid_cves) == len(cve_ids) ) for cve_id in valid_cves: # Normalize CVE ID to uppercase cve_id = cve_id.upper().strip() try: raw_response = client.cve(cve_id) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_cve_output(client, cve_id)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_cve_output(client, cve_id)) continue except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process CVE: "{cve_id}".\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_cve_output(client, cve_id, str(exc))) continue execution_metrics.success += 1 results.append(build_cve_output(client, score_calculator, cve_id, raw_response)) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def private_url_command(client: Client, args: dict) -> List[CommandResults]: """ 1 API Call """ urls = argToList(args["url"]) results: List[CommandResults] = [] execution_metrics = ExecutionMetrics() for url in urls: try: raw_response = client.private_url(url) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_url_output(client, url)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_url_output(client, url)) continue except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process private URL: "{url}".\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_url_output(client, url, str(exc))) continue execution_metrics.success += 1 results.append(build_private_url_output(url, raw_response)) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def domain_command(client: Client, score_calculator: ScoreCalculator, args: dict, relationships: str) -> List[CommandResults]: """ 1 API Call for regular """ execution_metrics = ExecutionMetrics() domains = argToList(args["domain"]) results: List[CommandResults] = [] for domain in domains: try: raw_response = client.domain(domain, relationships) if raw_response.get("error", {}).get("code") == "QuotaExceededError": execution_metrics.quota_error += 1 results.append(build_quota_exceeded_domain_output(client, domain)) continue if raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_domain_output(client, domain)) continue except Exception as exc: # If anything happens, just keep going demisto.debug(f'Could not process domain: "{domain}"\n {exc!s}') execution_metrics.general_error += 1 results.append(build_error_domain_output(client, domain, str(exc))) continue execution_metrics.success += 1 result = build_domain_output( client, score_calculator, domain, raw_response, argToBoolean(args.get("extended_data", False)) ) results.append(result) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results # endregion # region Scan commands def file_rescan_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ file_hash = args["file"] raise_if_hash_not_valid(file_hash) raw_response = client.file_rescan(file_hash) data = raw_response["data"] data["hash"] = file_hash context = { f"{INTEGRATION_ENTRY_CONTEXT}.Submission(val.id && val.id === obj.id)": data, "vtScanID": data.get("id"), # BC preservation } return CommandResults( readable_output=tableToMarkdown( f'File "{file_hash}" resubmitted.', data, removeNull=True, headerTransform=underscoreToCamelCase ), outputs=context, raw_response=raw_response, ) def get_working_id(id_: str, entry_id: str) -> str: """Sometimes new scanned files ID will be only a number. Should connect them with base64(MD5:_id). Fixes bug in Google Threat Intelligence API. Args: entry_id: the entry id connected to the file id_: id given from the API Returns: A working ID that we can use in other commands. """ if (isinstance(id_, str) and id_.isnumeric()) or isinstance(id_, int): demisto.debug(f"Got an integer id from file-scan. {id_=}, {entry_id=}\n") raise DemistoException( f"Got an int {id_=} as analysis report. This is a bug in Google Threat Intelligence API.\n" f"While Google Threat Intelligence team is fixing the problem, try to resend the file." ) return id_ def file_scan(client: Client, args: dict) -> List[CommandResults]: """ 1 API Call """ return upload_file(client, args) def private_file_scan(client: Client, args: dict) -> List[CommandResults]: """ 1 API Call """ return upload_file(client, args, True) def upload_file(client: Client, args: dict, private: bool = False) -> List[CommandResults]: """ 1 API Call """ entry_ids = argToList(args["entryID"]) upload_url = args.get("uploadURL") if len(entry_ids) > 1 and upload_url: raise DemistoException("You can supply only one entry ID with an upload URL.") results = [] for entry_id in entry_ids: try: file_obj = demisto.getFilePath(entry_id) file_path = file_obj["path"] if private: raw_response = client.private_file_scan(file_path) else: raw_response = client.file_scan(file_path, upload_url) data = raw_response.get("data", {}) # add current file as identifiers data.update(get_file_context(entry_id)) id_ = data.get("id") demisto.debug(f'Result from vt-scan-file {entry_id=} {id_=} {data.get("type")=}') id_ = get_working_id(id_, entry_id) data["id"] = id_ context = { f"{INTEGRATION_ENTRY_CONTEXT}.Submission(val.id && val.id === obj.id)": data, "vtScanID": id_, # BC preservation } results.append( CommandResults( readable_output=tableToMarkdown( f'The file has been submitted "{file_obj["name"]}"', data, headers=["id", "EntryID", "MD5", "SHA1", "SHA256"], removeNull=True, ), outputs=context, raw_response=raw_response, ) ) except Exception as exc: err = f"Could not process {entry_id=}.\n{exc!s}" demisto.debug(err) demisto.results({"Type": entryTypes["error"], "ContentsFormat": formats["text"], "Contents": err}) return results def file_scan_and_get_analysis(client: Client, score_calculator: ScoreCalculator, args: dict, file_relationships: str): """Calls to file-scan and gti-analysis-get.""" interval = int(args.get("interval_in_seconds", 60)) extended = argToBoolean(args.get("extended_data", False)) if not args.get("id"): command_results = file_scan(client, args) command_result = command_results[0] outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-file-scan-and-analysis-get", next_run_in_seconds=interval, args={ "entryID": args.get("entryID"), "id": outputs.get("vtScanID"), "file": outputs.get(f"{INTEGRATION_ENTRY_CONTEXT}.Submission(val.id && val.id === obj.id)", {}).get("SHA256"), "interval_in_seconds": interval, "extended_data": extended, }, timeout_in_seconds=6000, ) command_result.scheduled_command = scheduled_command return command_result command_result = get_analysis_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") if outputs.get("data", {}).get("attributes", {}).get("status") == "completed": return file_command(client, score_calculator, args, file_relationships) scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-file-scan-and-analysis-get", next_run_in_seconds=interval, args={ "entryID": args.get("entryID"), "id": outputs.get("id"), "file": args.get("file"), "interval_in_seconds": interval, "extended_data": extended, }, timeout_in_seconds=6000, ) return CommandResults(scheduled_command=scheduled_command) def private_file_scan_and_get_analysis(client: Client, args: dict): """Calls to gti-privatescanning-file-scan and gti-privatescanning-analysis-get.""" interval = int(args.get("interval_in_seconds", 60)) if not args.get("id"): command_results = private_file_scan(client, args) command_result = command_results[0] outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-private-file-scan-and-analysis-get", next_run_in_seconds=interval, args={ "entryID": args.get("entryID"), "id": outputs.get("vtScanID"), "interval_in_seconds": interval, }, timeout_in_seconds=6000, ) command_result.scheduled_command = scheduled_command return command_result command_result = private_get_analysis_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") if outputs.get("data", {}).get("attributes", {}).get("status") == "completed": return command_result scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-private-file-scan-and-analysis-get", next_run_in_seconds=interval, args={ "entryID": args.get("entryID"), "id": outputs.get("id"), "interval_in_seconds": interval, }, timeout_in_seconds=6000, ) return CommandResults(scheduled_command=scheduled_command) def url_scan_and_get_analysis(client: Client, score_calculator: ScoreCalculator, args: dict, url_relationships: str): """Calls to url-scan and gti-analysis-get.""" interval = int(args.get("interval_in_seconds", 60)) extended = argToBoolean(args.get("extended_data", False)) if not args.get("id"): command_result = scan_url_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-url-scan-and-analysis-get", next_run_in_seconds=interval, args={ "url": args.get("url"), "id": outputs.get("vtScanID"), "interval_in_seconds": interval, "extended_data": extended, }, timeout_in_seconds=6000, ) command_result.scheduled_command = scheduled_command return command_result command_result = get_analysis_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") if outputs.get("data", {}).get("attributes", {}).get("status") == "completed": return url_command(client, score_calculator, args, url_relationships) scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-url-scan-and-analysis-get", next_run_in_seconds=interval, args={ "url": args.get("url"), "id": outputs.get("id"), "interval_in_seconds": interval, "extended_data": extended, }, timeout_in_seconds=6000, ) return CommandResults(scheduled_command=scheduled_command) def private_url_scan_and_get_analysis(client: Client, args: dict): """Calls to gti-privatescanning-url-scan and gti-privatescanning-analysis-get.""" interval = int(args.get("interval_in_seconds", 60)) if not args.get("id"): command_result = private_scan_url_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-private-url-scan-and-analysis-get", next_run_in_seconds=interval, args={ "url": args.get("url"), "id": outputs.get("vtScanID"), "interval_in_seconds": interval, }, timeout_in_seconds=6000, ) command_result.scheduled_command = scheduled_command return command_result command_result = private_get_analysis_command(client, args) outputs = command_result.outputs if not isinstance(outputs, dict): raise DemistoException("outputs is expected to be a dict") if outputs.get("data", {}).get("attributes", {}).get("status") == "completed": return command_result scheduled_command = ScheduledCommand( command=f"{COMMAND_PREFIX}-private-url-scan-and-analysis-get", next_run_in_seconds=interval, args={ "url": args.get("url"), "id": outputs.get("id"), "interval_in_seconds": interval, }, timeout_in_seconds=6000, ) return CommandResults(scheduled_command=scheduled_command) def get_upload_url(client: Client) -> CommandResults: """ 1 API Call """ raw_response = client.get_upload_url() upload_url = raw_response["data"] context = { f"{INTEGRATION_ENTRY_CONTEXT}.FileUploadURL": upload_url, "vtUploadURL": upload_url, # BC preservation } return CommandResults( readable_output=tableToMarkdown("New upload url acquired!", {"Upload url": upload_url}), outputs=context, raw_response=raw_response, ) def scan_url_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ return scan_url(client, args) def private_scan_url_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ return scan_url(client, args, True) def scan_url(client: Client, args: dict, private: bool = False) -> CommandResults: """ 1 API Call """ url = args["url"] raw_response: Dict[str, Any] = {} data: Dict[str, Any] = {} context: Dict[str, Any] = {} headers = ["id", "url"] try: if private: raw_response = client.private_url_scan(url) else: raw_response = client.url_scan(url) data = raw_response["data"] data["url"] = url context = { f"{INTEGRATION_ENTRY_CONTEXT}.Submission(val.id && val.id === obj.id)": data, "vtScanID": data.get("id"), # BC preservation } except DemistoException as e: error = e.res.json().get("error") # Invalid url, probably due to an unknown TLD if error["code"] == "InvalidArgumentError": data = {"url": url, "id": "", "error": error["message"]} headers.append("error") else: raise e return CommandResults( readable_output=tableToMarkdown("New url submission:", data, headers=headers), outputs=context, raw_response=raw_response ) # endregion # region Comments commands def get_comments_command(client: Client, args: dict) -> CommandResults: """ 1 API Call BC Break - No NotBefore argument added limit """ limit = arg_to_number_must_int(args.get("limit"), arg_name="limit", required=True) resource = args["resource"] if before := args.get("before"): before = parse(before) assert before is not None, f'Could not parse the before date "{before}"' before = before.replace(tzinfo=None) resource_type = args.get("resource_type") if not resource_type: try: raise_if_hash_not_valid(resource) resource_type = "file" except ValueError: resource_type = "url" resource_type = resource_type.lower() # Will find if there's one and only one True in the list. if resource_type == "ip": raise_if_ip_not_valid(resource) raw_response = client.get_ip_comments(resource, limit) elif resource_type == "url": raw_response = client.get_url_comments(resource, limit) elif resource_type in ("hash", "file"): raise_if_hash_not_valid(resource) raw_response = client.get_hash_comments(resource, limit) elif resource_type == "domain": raw_response = client.get_domain_comments(resource, limit) else: raise DemistoException(f'Could not find resource type of "{resource_type}"') data = raw_response.get("data", {}) context = {"indicator": resource, "comments": data} comments = [] for comment in data: attributes = comment.get("attributes", {}) votes = attributes.get("votes", {}) if date := parse(str(attributes.get("date"))): date = date.replace(tzinfo=None) if date and before and date > before: continue comments.append( { "Date": epoch_to_timestamp(attributes.get("date")), "Text": attributes.get("text"), "Positive Votes": votes.get("positive"), "Abuse Votes": votes.get("abuse"), "Negative Votes": votes.get("negative"), } ) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Comments", "id", readable_output=tableToMarkdown( f'Google Threat Intelligence comments of {resource_type}: "{resource}"', comments, headers=["Date", "Text", "Positive Votes", "Abuse Votes", "Negative Votes"], ), outputs=context, raw_response=raw_response, ) def add_comments_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ resource = args["resource"] comment = args["comment"] resource_type = args.get("resource_type") if not resource_type: try: raise_if_hash_not_valid(resource) resource_type = "file" except ValueError: resource_type = "url" resource_type = resource_type.lower() if resource_type == "ip": raise_if_ip_not_valid(resource) raw_response = client.add_comment_to_ip(resource, comment) elif resource_type == "url": raw_response = client.add_comment_to_url(resource, comment) elif resource_type == "domain": raw_response = client.add_comment_to_domain(resource, comment) elif resource_type == "file": raise_if_hash_not_valid(resource) raw_response = client.add_comment_to_file(resource, comment) else: raise DemistoException(f'Could not find resource type of "{resource_type}"') data = raw_response["data"] attributes = data.get("attributes", {}) votes = attributes.get("votes", {}) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Comments.comments", "id", readable_output=tableToMarkdown( "Comment has been added!", { "Date": epoch_to_timestamp(attributes.get("date")), "Text": attributes.get("text"), "Positive Votes": votes.get("positive"), "Abuse Votes": votes.get("abuse"), "Negative Votes": votes.get("negative"), }, headers=["Date", "Text", "Positive Votes", "Abuse Votes", "Negative Votes"], ), outputs=data, raw_response=raw_response, ) def get_comments_by_id_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ comment_id = args["id"] raw_response = client.get_comment_by_id(comment_id) data = raw_response["data"] attributes = data.get("attributes", {}) votes = attributes.get("votes", {}) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Comments.comments", "id", readable_output=tableToMarkdown( f"Comment of ID {comment_id}", { "Date": epoch_to_timestamp(attributes.get("date")), "Text": attributes.get("text"), "Positive Votes": votes.get("positive"), "Abuse Votes": votes.get("abuse"), "Negative Votes": votes.get("negative"), }, headers=["Date", "Text", "Positive Votes", "Abuse Votes", "Negative Votes"], ), outputs=data, raw_response=raw_response, ) # endregion def file_sandbox_report_command(client: Client, args: dict) -> List[CommandResults]: """ 1 API Call """ execution_metrics = ExecutionMetrics() results: List[CommandResults] = [] file_hash = args["file"] limit = arg_to_number(args["limit"], "limit", required=True) assert isinstance(limit, int) # mypy fix raise_if_hash_not_valid(file_hash) raw_response = client.file_sandbox_report(file_hash, limit) if "data" in raw_response: data = raw_response["data"] execution_metrics.quota_error += 1 results.append( CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.SandboxReport", "id", readable_output=tableToMarkdown( f"Sandbox Reports for file hash: {file_hash}", [{"id": item["id"], **item["attributes"], "link": item["links"]["self"]} for item in data], headers=["analysis_date", "last_modification_date", "sandbox_name", "link"], removeNull=True, headerTransform=underscoreToCamelCase, ), outputs=data, raw_response=raw_response, ) ) elif raw_response.get("error", {}).get("code") == "NotFoundError": results.append(build_unknown_file_output(client, file_hash)) else: execution_metrics.quota_error += 1 results.append(build_quota_exceeded_file_output(client, file_hash)) if execution_metrics.is_supported(): _metric_results = execution_metrics.metrics metric_results = cast(CommandResults, _metric_results) results.append(metric_results) return results def passive_dns_data(client: Client, args: dict) -> CommandResults: """ 1 API Call """ id = {} if "ip" in args: id["value"] = args["ip"] id["type"] = "ip" raise_if_ip_not_valid(id["value"]) elif "domain" in args: id["value"] = args["domain"] id["type"] = "domain" elif "id" in args: id["value"] = args["id"] if is_ip_valid(id["value"]): id["type"] = "ip" else: id["type"] = "domain" else: return CommandResults(readable_output="No IP address or domain was given.") limit = arg_to_number_must_int(args["limit"], arg_name="limit", required=True) try: raw_response = client.passive_dns_data(id, limit) except Exception: return CommandResults(readable_output=f'{"IP" if id["type"] == "ip" else "Domain"} {id["value"]} was not found.') data = raw_response["data"] return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.PassiveDNS", "id", readable_output=tableToMarkdown( f'Passive DNS data for {"IP" if id["type"] == "ip" else "domain"} {id["value"]}', [{"id": item["id"], **item["attributes"]} for item in data], headers=["id", "date", "host_name", "ip_address", "resolver"], removeNull=True, headerTransform=underscoreToCamelCase, ), outputs=data, raw_response=raw_response, ) def search_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ query = args["query"] limit = arg_to_number_must_int(args.get("limit"), "limit", required=True) raw_response = client.search(query, limit) data = raw_response.get("data", []) if not argToBoolean(args.get("extended_data", False)): data = decrease_data_size(data) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.SearchResults", "id", readable_output=tableToMarkdown( f"Search result of query {query}", [item.get("attributes") for item in data], removeNull=True, headerTransform=underscoreToCamelCase, ), outputs=data, raw_response=raw_response, ) def get_analysis_command(client: Client, args: dict) -> CommandResults: """ 1 API Call """ analysis_id = args["id"] raw_response = client.get_analysis(analysis_id) data = raw_response.get("data", {}) if not argToBoolean(args.get("extended_data", False)): data = decrease_data_size(data) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Analysis", "id", readable_output=tableToMarkdown( "Analysis results:", {**data.get("attributes", {}), "id": analysis_id}, headers=["id", "stats", "status"], headerTransform=underscoreToCamelCase, ), outputs={**raw_response, "id": analysis_id}, raw_response=raw_response, ) def private_get_analysis_command(client: Client, args: dict) -> CommandResults: """ 1-2 API Call """ analysis_id = args["id"] raw_response = client.get_private_analysis(analysis_id) data = raw_response.get("data", {}) attributes = data.get("attributes", {}) if sha256 := raw_response.get("meta", {}).get("file_info", {}).get("sha256"): attributes["sha256"] = sha256 if url := raw_response.get("meta", {}).get("url_info", {}).get("url"): attributes["url"] = url if attributes.get("status", "") == "completed": stats = {} item_response = client.get_private_item_from_analysis(analysis_id) item_attributes = item_response.get("data", {}).get("attributes", {}) # File attributes if threat_severity := item_attributes.get("threat_severity"): if severity_level := threat_severity.get("threat_severity_level"): stats["threat_severity_level"] = SEVERITY_LEVELS.get(severity_level, severity_level) if popular_threat_category := threat_severity.get("threat_severity_data", {}).get("popular_threat_category"): stats["popular_threat_category"] = popular_threat_category if verdict := item_attributes.get("threat_verdict"): stats["threat_verdict"] = VERDICTS.get(verdict, verdict) # URL attributes if (last_analysis_stats := item_attributes.get("last_analysis_stats")) and ( detection_engines := sum(last_analysis_stats.values()) ): positive_detections = last_analysis_stats.get("malicious", 0) stats["positives"] = f"{positive_detections}/{detection_engines}" attributes.update(stats) for field in ["title", "last_http_response_content_sha256"]: if value := item_attributes.get(field): attributes[field] = value return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Analysis", "id", readable_output=tableToMarkdown( "Analysis results:", {**attributes, "id": analysis_id}, headers=[ # Common headers "id", "status", # File attributes "sha256threat_severity_level", "popular_threat_category", "threat_verdict", # URL attributes "url", "title", "last_http_response_content_sha256", "positives", ], removeNull=True, headerTransform=string_to_table_header, ), outputs={**raw_response, "id": analysis_id}, raw_response=raw_response, ) def check_module(client: Client) -> str: """ 1 API Call """ client.get_ip_comments("8.8.8.8", 1) return "ok" def delete_comment(client: Client, args: dict) -> CommandResults: """Delete a comments""" id_ = args["id"] client.delete_comment(id_) return CommandResults(readable_output=f"Comment {id_} has been deleted!") def file_sigma_analysis_command(client: Client, args: dict) -> CommandResults: """Get last sigma analysis for a given file""" file_hash = args["file"] only_stats = argToBoolean(args.get("only_stats", False)) raw_response = client.file(file_hash) data = raw_response["data"] if "sigma_analysis_stats" not in data["attributes"] or "sigma_analysis_results" not in data["attributes"]: return CommandResults(readable_output=f"No Sigma analyses for file {file_hash} were found.") if only_stats: return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.SigmaAnalysis", "id", readable_output=tableToMarkdown( f"Summary of the last Sigma analysis for file {file_hash}:", { **data["attributes"]["sigma_analysis_stats"], "**TOTAL**": sum(data["attributes"]["sigma_analysis_stats"].values()), }, headers=["critical", "high", "medium", "low", "**TOTAL**"], removeNull=True, headerTransform=underscoreToCamelCase, ), outputs=data, raw_response=data["attributes"]["sigma_analysis_stats"], ) else: return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.SigmaAnalysis", "id", readable_output=tableToMarkdown( f"Matched rules for file {file_hash} in the last Sigma analysis:", data["attributes"]["sigma_analysis_results"], headers=[ "rule_level", "rule_description", "rule_source", "rule_title", "rule_id", "rule_author", "match_context", ], removeNull=True, headerTransform=underscoreToCamelCase, ), outputs=data, raw_response=data["attributes"]["sigma_analysis_results"], ) def get_assessment_command(client: Client, score_calculator: ScoreCalculator, args: dict) -> CommandResults: """Get Google Threat Intelligence assessment for a given resource.""" resource = args["resource"] resource_type = args.get("resource_type", "file").lower() if resource_type in ("hash", "file"): raise_if_hash_not_valid(resource) raw_response = client.file(resource) if raw_response.get("error", {}).get("code") == "QuotaExceededError": return build_quota_exceeded_file_output(client, resource) if raw_response.get("error", {}).get("code") == "NotFoundError": return build_unknown_file_output(client, resource) indicator = _get_file_indicator(client, score_calculator, resource, raw_response) elif resource_type == "ip": raise_if_ip_not_valid(resource) raw_response = client.ip(resource) if raw_response.get("error", {}).get("code") == "QuotaExceededError": return build_quota_exceeded_ip_output(client, resource) if raw_response.get("error", {}).get("code") == "NotFoundError": return build_unknown_ip_output(client, resource) indicator = _get_ip_indicator(client, score_calculator, resource, raw_response) elif resource_type == "url": raw_response = client.url(resource) if raw_response.get("error", {}).get("code") == "QuotaExceededError": return build_quota_exceeded_url_output(client, resource) if raw_response.get("error", {}).get("code") == "NotFoundError": return build_unknown_url_output(client, resource) indicator = _get_url_indicator(client, score_calculator, resource, raw_response) elif resource_type == "domain": raw_response = client.domain(resource) if raw_response.get("error", {}).get("code") == "QuotaExceededError": return build_quota_exceeded_domain_output(client, resource) if raw_response.get("error", {}).get("code") == "NotFoundError": return build_unknown_domain_output(client, resource) indicator = _get_domain_indicator(client, score_calculator, resource, raw_response) else: raise DemistoException(f'Could not find resource type of "{resource_type}"') data = raw_response.get("data", {}) data.pop("relationships", None) gti_assessment = data.get("attributes", {}).get("gti_assessment", {}) if data: if gti_assessment: data["attributes"] = {"gti_assessment": gti_assessment} else: data.pop("attributes", None) return CommandResults( f"{INTEGRATION_ENTRY_CONTEXT}.Assessment", "id", indicator=indicator, readable_output=tableToMarkdown( f'Google Threat Intelligence assessment of {resource_type}: "{resource}"', { "threat_score": gti_assessment.get("threat_score", {}).get("value"), "severity": gti_assessment.get("severity", {}).get("value"), "verdict": gti_assessment.get("verdict", {}).get("value"), }, headers=[ "threat_score", "severity", "verdict", ], headerTransform=string_to_table_header, ), outputs=data, raw_response=raw_response, ) def _get_curated_collections_command(client: Client, args: dict, collection_type: str) -> CommandResults: """Get Google Threat Intelligence collections for a given resource.""" resource = args["resource"] resource_type = args.get("resource_type", "file").lower() raw_response = client.curated_collections(resource, resource_type, collection_type) data = raw_response.get("data", []) collections = [] for collection in data: attributes = collection.get("attributes", {}) targeted_regions = { item.get("country_iso2") for item in attributes.get("targeted_regions_hierarchy", []) if item.get("country_iso2") } targeted_industries = { item.get("industry_group") for item in attributes.get("targeted_industries_tree", []) if item.get("industry_group") } collections.append( { "name": attributes.get("name"), "last_modification_date": epoch_to_timestamp(attributes.get("last_modification_date")), "targeted_regions": ", ".join(targeted_regions), "targeted_industries": ", ".join(targeted_industries), "link": f'https://www.virustotal.com/gui/collection/{collection["id"]}', } ) type_str = collection_type.replace("-", " ") type_context = type_str.title().replace(" ", "") type_title = f"{type_str[:-1]}ies" if type_str.endswith("y") else f"{type_str}s" return CommandResults( outputs_prefix=f"{INTEGRATION_ENTRY_CONTEXT}.{type_context}", outputs_key_field="id", readable_output=tableToMarkdown( f'Curated {type_title} of {resource_type}: "{resource}"', collections, headers=[ "name", "last_modification_date", "targeted_regions", "targeted_industries", "link", ], headerTransform=string_to_table_header, ), outputs={ "id": resource, "collections": data, }, raw_response=raw_response, ) def get_curated_campaigns_command(client: Client, args: dict) -> CommandResults: """Get Google Threat Intelligence campaigns for a given resource.""" return _get_curated_collections_command(client, args, "campaign") def get_curated_malware_families_command(client: Client, args: dict) -> CommandResults: """Get Google Threat Intelligence malware families for a given resource.""" return _get_curated_collections_command(client, args, "malware-family") def get_curated_threat_actors_command(client: Client, args: dict) -> CommandResults: """Get Google Threat Intelligence threat actors for a given resource.""" return _get_curated_collections_command(client, args, "threat-actor") def arg_to_relationships(arg): """Get an argument and return the relationship list.""" return (",".join(argToList(arg))).replace("* ", "").replace(" ", "_") def main(params: dict, args: dict, command: str): results: Union[CommandResults, str, List[CommandResults]] handle_proxy() client = Client(params) score_calculator = ScoreCalculator(params) ip_relationships = arg_to_relationships(params.get("ip_relationships")) url_relationships = arg_to_relationships(params.get("url_relationships")) domain_relationships = arg_to_relationships(params.get("domain_relationships")) file_relationships = arg_to_relationships(params.get("file_relationships")) disable_private_ip_lookup = argToBoolean(params.get("disable_private_ip_lookup", False)) demisto.debug(f"Command called {command}") if command == "test-module": results = check_module(client) elif command == "file": results = file_command(client, score_calculator, args, file_relationships) elif command == "ip": results = ip_command(client, score_calculator, args, ip_relationships, disable_private_ip_lookup) elif command == "url": results = url_command(client, score_calculator, args, url_relationships) elif command == "domain": results = domain_command(client, score_calculator, args, domain_relationships) elif command == "cve": results = cve_command(client, score_calculator, args) elif command == f"{COMMAND_PREFIX}-file-sandbox-report": results = file_sandbox_report_command(client, args) elif command == f"{COMMAND_PREFIX}-passive-dns-data": results = passive_dns_data(client, args) elif command == f"{COMMAND_PREFIX}-comments-get": results = get_comments_command(client, args) elif command == f"{COMMAND_PREFIX}-comments-add": results = add_comments_command(client, args) elif command == f"{COMMAND_PREFIX}-comments-get-by-id": results = get_comments_by_id_command(client, args) elif command == f"{COMMAND_PREFIX}-comments-delete": results = delete_comment(client, args) elif command == "url-scan": results = scan_url_command(client, args) elif command == "file-scan": results = file_scan(client, args) elif command == "file-rescan": results = file_rescan_command(client, args) elif command == f"{COMMAND_PREFIX}-file-scan-upload-url": results = get_upload_url(client) elif command == f"{COMMAND_PREFIX}-search": results = search_command(client, args) elif command == f"{COMMAND_PREFIX}-analysis-get": results = get_analysis_command(client, args) elif command == f"{COMMAND_PREFIX}-file-sigma-analysis": results = file_sigma_analysis_command(client, args) elif command == f"{COMMAND_PREFIX}-privatescanning-file": results = private_file_command(client, args) elif command == f"{COMMAND_PREFIX}-privatescanning-file-scan": results = private_file_scan(client, args) elif command == f"{COMMAND_PREFIX}-privatescanning-url": results = private_url_command(client, args) elif command == f"{COMMAND_PREFIX}-privatescanning-url-scan": results = private_scan_url_command(client, args) elif command == f"{COMMAND_PREFIX}-privatescanning-analysis-get": results = private_get_analysis_command(client, args) elif command == f"{COMMAND_PREFIX}-assessment-get": results = get_assessment_command(client, score_calculator, args) elif command == f"{COMMAND_PREFIX}-file-scan-and-analysis-get": results = file_scan_and_get_analysis(client, score_calculator, args, file_relationships) elif command == f"{COMMAND_PREFIX}-private-file-scan-and-analysis-get": results = private_file_scan_and_get_analysis(client, args) elif command == f"{COMMAND_PREFIX}-url-scan-and-analysis-get": results = url_scan_and_get_analysis(client, score_calculator, args, url_relationships) elif command == f"{COMMAND_PREFIX}-private-url-scan-and-analysis-get": results = private_url_scan_and_get_analysis(client, args) elif command == f"{COMMAND_PREFIX}-curated-campaigns-get": results = get_curated_campaigns_command(client, args) elif command == f"{COMMAND_PREFIX}-curated-malware-families-get": results = get_curated_malware_families_command(client, args) elif command == f"{COMMAND_PREFIX}-curated-threat-actors-get": results = get_curated_threat_actors_command(client, args) else: raise NotImplementedError(f"Command {command} not implemented") return_results(results) if __name__ in ("builtins", "__builtin__", "__main__"): try: main(demisto.params(), demisto.args(), demisto.command()) except Exception as exception: return_error(exception)