Threat Grid Deprecated
Deprecated. Use Cisco Secure Malware Analytics (Threat Grid) v2 instead.
Forensics & Malware Analysis · Cisco Secure Malware Analytics
Details
| ID | Threat Grid |
|---|---|
| Provider | Cisco Systems |
| Category | Forensics & Malware Analysis |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.10.9.42476 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
redOverview
Use the Cisco Threat Grid integration to manage and query threat feeds and samples.
This integration was integrated and tested with Cisco Threat Grid v3.5.10.
Threat Grid Playbook
Use cases
Configure Threat Grid on Cortex XSOAR
- Navigate to Settings > Integrations > Servers & Services.
- Search for Threat Grid.
- Click Add instance to create and configure a new integration instance.
You should configure the following settings:
- Name: a textual name for the integration instance.
- Server URL (e.g. https://192.168.0.1)
- API token
- Trust any certificate (not secure)
- Use system proxy settings
- Click Test to validate the URLs, token, and connection.
Commands
You can execute these commands from the Cortex XSOAR 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.
- Get samples: threat-grid-get-samples
- Get a sample by sample ID: threat-grid-get-sample-by-id
- Get the states of samples by sample ID: threat-grid-get-sample-state-by-id
- Submit a sample for analysis: threat-grid-upload-sample
- Search submissions: threat-grid-search-submissions
- Get a sample analysis video by ID: threat-grid-get-video-by-id
- Get a detailed overview of a sample: threat-grid-get-analysis-by-id
- Get processes by ID: threat-grid-get-processes-by-id
- Get a PCAP file for a sample by sample ID: threat-grid-get-pcap-by-id
- Get warnings for a sample by sample ID: threat-grid-get-warnings-by-id
- Get a summary analysis for a sample by sample ID: threat-grid-get-summary-by-id
- Get a summary of threats detected during an analysis: threat-grid-get-threat-summary-by-id
- Get the HTML report for a sample by sample ID: threat-grid-get-html-report-by-id
- Download a sample as a ZIP file: threat-grid-download-sample-by-id
- Get a list of IOCs found during a sample run: threat-grid-get-analysis-iocs
- Get information for the logged in user: threat-grid-who-am-i
- Get the rate limit for a specified user: threat-grid-user-get-rate-limit
- Get a specific threat feed: threat-grid-get-specific-feed
- Convert a URL to a file for detonation: threat-grid-url-to-file
- Get rate limits for an organization: threat-grid-organization-get-rate-limit
- Search IP addresses: threat-grid-search-ips
- Get annotation data for an analysis: threat-grid-get-analysis-annotations
- Search samples: threat-grid-search-samples
- Search URLs: threat-grid-search-urls
- Get the states of samples: threat-grid-get-samples-state
- Get the threat feed for artifacts: threat-grid-feeds-artifacts
- Get the threat feed for a domain: threat-grid-feeds-domain
- Get the threat feed for an IP address: threat-grid-feeds-ip
- Get the threat feed for a network stream: threat-grid-feeds-network-stream
- Get the threat feed for a path: threat-grid-feeds-path
- Get the threat feed for a URL: threat-grid-feeds-url
- Get the artifacts for a sample ID by artifact ID: threat-grid-get-analysis-artifact
- Get artifacts for a sample ID: threat-grid-get-analysis-artifacts
- Get analysis data for an IOC: threat-grid-get-analysis-ioc
- Get metadata for an analysis: threat-grid-get-analysis-metadata
- Get data for a network stream: threat-grid-get-analysis-network-stream
- Get the analysis for a threat stream: threat-grid-get-analysis-network-streams
- Get data for a process ID in an analysis: threat-grid-get-analysis-process
- Get data for an analysis process: threat-grid-get-analysis-processes
- Submit URL for analysis: threat-grid-submit-urls
- Run advanced search using the ThreatGrid search query: threat-grid-advanced-search
1. Get samples
Get samples on the Threat Grid platform. Input parameters are combined with AND statements. Only finished samples can be searched. Finished samples have a status of succ or fail.
Base Command
threat-grid-get-samples
Input
| Argument Name | Description | Required |
|---|---|---|
| limit | Maximum number of results to return in the response | Optional |
| offset | The number of records to skip | Optional |
| sha256 | SHA-256 of the submitted sample (only matches samples, not their artifacts) | Optional |
| md5 | An MD5 checksum of the submitted sample (only matches samples, not their artifacts) | Optional |
| sha1 | SHA-1 of the submitted sample, only matches samples, not their artifacts | Optional |
| id | ID of a sample | Optional |
| ids | Comma-separated list of sample IDs | Optional |
| ioc | IOC name | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before that time (YYYY-MM-DD Thhmmss+) | -hhmm e.g. : 2012-04-19T04:00:55-0500 |
| after | A date/time (ISO 8601), restricting results to samples submitted after that time (YYYY-MM-DD Thhmmss+) | -hhmm e.g. : 2012-04-19T04:00:55-0500" |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID |
| ThreatGrid.Sample.Filename | The sample filename |
| ThreatGrid.Sample.State | The sample state |
| ThreatGrid.Sample.Status | The sample status |
| ThreatGrid.Sample.MD5 | The sample MD5 |
| ThreatGrid.Sample.SHA1 | The sample SHA-1 |
| ThreatGrid.Sample.SHA256 | The sample SHA-256 |
| ThreatGrid.Sample.OS | The sample OS |
| ThreatGrid.Sample.SubmittedAt | The sample submission time |
| ThreatGrid.Sample.StartedAt | The sample analysis starting time |
| ThreatGrid.Sample.CompletedAt | The sample completion time |
Command Example
!threat-grid-feeds-ip after=2018-01-18T00:00:00 before=2018-01-18T01:00:00 confidence=75 severity=75
Context Output
{
"ThreatGrid": {
"Sample": [
{
"Status": "job_done",
"SHA1": "f6ed96430b54a52740d3f7a0a246d1053ba7d779",
"CompletedAt": "2018-09-23T08:18:20Z",
"Filename": "8d3a3c399ac61a1e7ae6f6c68c67f1db2e88985066463a5ffb3dae0d552a64a5.exe",
"State": "succ",
"SubmittedAt": "2018-09-23T08:12:05Z",
"StartedAt": "2018-09-23T08:12:06Z",
"SHA256": "8d3a3c399ac61a1e7ae6f6c68c67f1db2e88985066463a5ffb3dae0d552a64a5",
"OS": "7601.18798.amd64fre.win7sp1_gdr.150316-1654",
"ID": "4bb1e6eed595513b2c07ba9bd4598f37",
"MD5": "c6bdbf3765854eef4981721947beba5f"
},
{
"Status": "job_done",
"SHA1": "6b7808dd69ff255e982f9940d067b356f030ff14",
"CompletedAt": "2018-09-23T08:18:28Z",
"Filename": "8a577adc1b387c0dfc445b4a6f9a5bb54de13018c960624c0dcf35145aa00b03.exe",
"State": "succ",
"SubmittedAt": "2018-09-23T08:12:07Z",
"StartedAt": "2018-09-23T08:12:08Z",
"SHA256": "8a577adc1b387c0dfc445b4a6f9a5bb54de13018c960624c0dcf35145aa00b03",
"OS": "7601.18798.amd64fre.win7sp1_gdr.150316-1654",
"ID": "b75b886bcd4b888c2c6a779736509b12",
"MD5": "eb6f2ad4dcba833fd4411301ed8ae40e"
}
]
}
}
Human Readable Output
2. Get a sample by sample ID
Get a Threat Grid sample by sample ID.
Base Command
threat-grid-get-sample-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID |
| ThreatGrid.Sample.Filename | The sample filename |
| ThreatGrid.Sample.State | The sample state |
| ThreatGrid.Sample.Status | The sample status |
| ThreatGrid.Sample.MD5 | The sample MD5 |
| ThreatGrid.Sample.SHA1 | The sample SHA-1 |
| ThreatGrid.Sample.SHA256 | The sample SHA-256 |
| ThreatGrid.Sample.OS | The sample OS |
| ThreatGrid.Sample.SubmittedAt | The sample submission time |
| ThreatGrid.Sample.StartedAt | The sample analysis starting time |
| ThreatGrid.Sample.CompletedAt | The sample completion time |
Command Example
!threat-grid-get-sample-by-id id=052de338e02c4e013a4e9f5da8a87d5b
Context Example
{
"ThreatGrid": {
"Sample": {
"Status": "filetype_not_supported",
"SHA1": "a253ac433faa9ac59a9f73c540355bfe2f9fe708",
"CompletedAt": "2018-07-07T10:11:06Z",
"Filename": "WR Package(1).rar",
"State": "fail",
"SubmittedAt": "2018-07-07T10:11:04Z",
"StartedAt": "2018-07-07T10:11:05Z",
"SHA256": "9aa6f1189fa01f852e595d4c847a76613aa157d14addbdeb2ac011f443c811d7",
"OS": null,
"ID": "052de338e02c4e013a4e9f5da8a87d5b",
"MD5": "69e51e9f3a5ffbf6970a754ebda56edd"
}
}
}
Human Readable Output
3. Get the states of samples by sample ID
Get threat grid sample state by id
Base Command
threat-grid-get-sample-state-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Optional |
| ids | Comma-separated list of sample IDs | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID, globally unique, and the canonical identifier of this sample analysis |
| ThreatGrid.Sample.State | The state of the sample, one of a stable set of strings (“wait", "prep", "run", "proc", "succ", "fail”) |
Command Example
!threat-grid-get-sample-state-by-id id=052de338e02c4e013a4e9f5da8a87d5b
Context Example
{
"ThreatGrid": {
"Sample": {
"State": "fail",
"ID": "052de338e02c4e013a4e9f5da8a87d5b"
}
}
}
Human Readable Output
4. Submit a sample for analysis
Submits a sample to Threat Grid for analysis.
Base Command
threat-grid-upload-sample
Input
| Argument Name | Description | Required |
|---|---|---|
| file-id | The sample file. Click the chain icon after you upload a file in Cortex XSOAR to find the file-id. | Required |
| filename | The original file name of the sample (string) | Required |
| vm | A string identifying a specific VM to use. Options: win7-x64: Windows 7 64bit, win7-x64-2: Windows 7 64bit Profile 2, win7-x64-jp: Windows 7 64bit Japanese (Not available on Threat Grid appliances), win7-x64-kr: Windows 7 64bit Korean (Only available on Threat Grid appliances licensed for this VM), win10: Windows 10 (Not available on Threat Grid appliances). NOTE: The standard (English) VMs default to UTF-8 encoding. To support Korean and Japanese character sets, such as S-JIS, submit to the appropriate VM. | Optional |
| private | If specified and set to a value other than “false”, the sample will be marked private | Optional |
| tags | Comma-separated list of tags applied to this sample | Optional |
| playbook | Name of a playbook to apply to this sample run. none: Explicitly disables playbooks, default: Default Playbook, alt_tab_programs: Conduct Active Window Change, open_word_embedded_object: Open Embedded Object in Word Document, press_enter: Dialogue OK, visit_site: Visit Website Using Internet Explorer, close_file: Close Active Window, run_dialog_box_ie: Click Run on Internet Explorer Download Dialog Box, open_attachment_msg: Open Outlook Email Attachment, run_dialog_box_dde: Accept Microsoft Office Dialog Boxes to Open Dynamic Data Exchange Content. The current list of playbooks endpoints can be obtained by querying /api/v3/configuration/playbooks. | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID |
| ThreatGrid.Sample.Filename | The sample file name |
| ThreatGrid.Sample.State | The sample state |
| ThreatGrid.Sample.Status | The sample status |
| ThreatGrid.Sample.MD5 | The sample MD5 |
| ThreatGrid.Sample.SHA1 | The sample SHA-1 |
| ThreatGrid.Sample.SHA256 | The sample SHA-256 |
| ThreatGrid.Sample.OS | The sample OS |
| ThreatGrid.Sample.SubmittedAt | The sample submission time |
Command Example
!threat-grid-upload-sample file-id=98@16 filename=Suspicious_File_To_Be_Scanned
Context Example
{
"ThreatGrid": {
"Sample": {
"Status": "pending",
"SHA1": "bd762a2d655e174fd935cc8a5e928bea738d666a",
"CompletedAt": null,
"Filename": "Suspicious_File_To_Be_Scanned",
"State": "wait",
"SubmittedAt": "2018-10-24T12:52:52Z",
"StartedAt": null,
"SHA256": "71a0ea5ebcc449feb2ab8954c239b89d9d629c77011b30f330bb61af091d2ad6",
"OS": "",
"ID": "ec7cb57929fdf3f313f3b1238ff042ca",
"MD5": "653e9905e882f44015e1023dcde66451"
}
},
"File": {
"Info": "image/jpeg",
"SHA1": "bd762a2d655e174fd935cc8a5e928bea738d666a",
"Name": "Image from iOS.jpg",
"Extension": "jpg",
"Size": 5405984,
"EntryID": "98@16",
"SSDeep": "98304:tSfriWHhyAU04siL8QOTgOZLG9CG6/2N76EUs0ELRd7xs6f2UXCpofGZ4oOBsU0:8W6B4siQtTR1GU/2No+fd2X/9J",
"SHA256": "71a0ea5ebcc449feb2ab8954c239b89d9d629c77011b30f330bb61af091d2ad6",
"Type": "JPEG image data, JFIF standard 1.01, aspect ratio, density 72x72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=2, orientation=upper-left], baseline, precision 8, 4032x3024, frames 3\n",
"MD5": "653e9905e882f44015e1023dcde66451"
}
}
Human Readable Output
5. Search submissions
Search Threat Grid submissions.
Base Command
threat-grid-search-submissions
Input
| Argument Name | Description | Required |
|---|---|---|
| q | Query text | Optional |
| user-only | Only display submissions created by the current user, as determined by the value of api_key | Optional |
| org-only | Only display submissions created by the current user's organization, as determined by the value of api_key. | Optional |
| term | Restrict matches to a subset of submission fields. The value of 'term' is a comma-delimited list of strings which select groups of fields | Optional |
| before | Return submissions created before specified time. Value is a time string, either ISO-8601, or free-form (see the Chronic documentation) | Optional |
| after | Return submissions created after specified time. Value is a time string, either ISO-8601, or free-form (see the Chronic documentation) | Optional |
| state | Restrict match to submissions in specific state or states. Value is a comma-delimited string containing one or more of the values ("wait", "proc", "succ", "fail") | Optional |
| advanced | Interpret 'q' as an advanced elasticsearch query, allowing matches by specific field, for example: https:// ... /search/submissions?q=sha256:1b4468 ... &advanced=true | Optional |
| sort_by | Sorts by "timestamp", "submitted_at", "analyzed_at", "filename", "type", "state", "threat" or "threat_score", or "login | Optional |
| sort_order | desc or asc | Optional |
| limit | Restrict the number of records returned | Optional |
| offset | Return matching submissions starting at the given offset | Optional |
| highlight | Provide a 'matches' field in results, indicating which fields were matched | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID |
| ThreatGrid.Sample.Filename | The name of the sample file |
| ThreatGrid.Sample.State | The state of the sample |
| ThreatGrid.Sample.Status | The status of the sample |
| ThreatGrid.Sample.MD5 | The MD5 of the sample |
| ThreatGrid.Sample.SHA1 | The SHA-1 of the sample |
| ThreatGrid.Sample.SHA256 | The SHA-256 of the sample |
| ThreatGrid.Sample.SubmittedAt | Time of submission for the sample |
| ThreatGrid.Sample.ThreatScore | The threat score of the sample |
Command Example
!threat-grid-search-submissions limit=2
Context Example
{
"ThreatGrid": {
"Sample": [
{
"Status": "job_done",
"SHA1": "e823f52975e7b2dff0c5873973682dd5c2eb2464",
"CompletedAt": null,
"ThreatScore": 64,
"Filename": "url_as_file",
"State": "succ",
"SubmittedAt": "2018-07-04T10:25:53Z",
"StartedAt": null,
"SHA256": "da6de9ab720e1c763290fdad040113881e7d7443780283ff71970d3e160aa374",
"OS": null,
"ID": "47a9ca675ba509457bfd8cbe2a5b2189",
"MD5": "08db479ddee306addef0946194374795"
},
{
"Status": "job_done",
"SHA1": "e823f52975e7b2dff0c5873973682dd5c2eb2464",
"CompletedAt": null,
"ThreatScore": 64,
"Filename": "url_as_file",
"State": "succ",
"SubmittedAt": "2018-07-03T20:29:04Z",
"StartedAt": null,
"SHA256": "da6de9ab720e1c763290fdad040113881e7d7443780283ff71970d3e160aa374",
"OS": null,
"ID": "18bbd9bd6bf3be6a2f842b72cc19668f",
"MD5": "08db479ddee306addef0946194374795"
}
]
}
}
Human Readable Output
6. Get a sample analysis video by ID
Get the sample analysis video by ID.
Base Command
threat-grid-get-video-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.Id | string | The sample ID |
Command Example
!threat-grid-get-video-by-id id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "9798717402a40970a2d043014d9a6170"
}
},
"File": {
"Info": "video/webm",
"SHA1": "28d2b83753b713e3fb40d896ca3cbff13735f8c0",
"Name": "9798717402a40970a2d043014d9a6170.webm",
"Extension": "webm",
"Size": 1038907,
"EntryID": "117@16",
"SSDeep": "24576:u5/QP+OM+62I73Hi6RQ7MM4uyeL+I2zcvu3AYApDl29d9xG:u/IM+6v3HpM4rI2L3jACLG",
"SHA256": "ce7c155cde9d2d637a8f0e48c5e9d183a7c9756bc02d6ee505bfcda19f01573e",
"Type": ", created: Thu Jul 11 00:22:26 1974, modified: Sun Jul 17 00:26:42 2033\n",
"MD5": "7aeb2b515af0c5e1c8cfca234377e44f"
}
}
Human Readable Output
7. Get a detailed overview of a sample
The detailed overview of dynamic and static analysis results for the sample.
Base Command
threat-grid-get-analysis-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| limit | Limits the results, default is 20. To return all results, set the value to "". | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The ID of the sample for which the report was downloaded |
| Demisto.File | File containing unfiltered result |
| ThreatGrid.Sample.VM.ID | The VM ID for the sample |
| ThreatGrid.Sample.VM.Name | The VM Name for the sample |
| ThreatGrid.Sample.StartedAt | Start time of the analysis |
| ThreatGrid.Sample.Runtime | Runtime of the analysis |
| ThreatGrid.Sample.FileName | File name of the sample |
| ThreatGrid.Sample.Size | Size of the sample |
| ThreatGrid.Sample.MD5 | The sample MD5 value |
| ThreatGrid.Sample.SHA1 | The sample's SHA-1 value |
| ThreatGrid.Sample.SHA256 | The sample's SHA-256 value |
| ThreatGrid.Sample.MagicType | Sample magic type |
| ThreatGrid.Sample.Type | Sample's file type |
| ThreatGrid.Sample.ThreatScore | The threat score of the sample |
| ThreatGrid.Sample.HeuristicScore | The sample's heuristic score |
| ThreatGrid.Sample.FilesDeleted | The files that were created during the analysis |
| ThreatGrid.Sample.FileCreated | The files that were created during the analysis |
| ThreatGrid.Sample.FilesModified | The files that were modified during the analysis |
| ThreatGrid.Sample.Directory | The directory of the sample |
| ThreatGrid.Sample.CMD | The command line execution of the sample |
| ThreatGrid.Sample.ProcessName | The process name of the sample |
| ThreatGrid.Sample.Destination | The destination IP of the sample |
| ThreatGrid.Sample.DestinationPort | The destination port of the sample |
| ThreatGrid.Sample.PacketSize | Packet size in bytes |
| ThreatGrid.Sample.VT.Hits | Sample malicious hits in VirusTotal |
| ThreatGrid.Sample.VT.Engines | Number of engines that scanned the Sample on VirusTotal |
| ThreatGrid.Artifact.Yara | Artifact ID (yara signature name |
| ThreatGrid.Artifact.Tags | Artifact tags |
| ThreatGrid.Artifact.FamilyName | Artifact family name |
| ThreatGrid.Artifact.ThreatName | Artifact threat name |
Command Example
!threat-grid-get-analysis-by-id id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "9798717402a40970a2d043014d9a6170"
}
},
"InfoFile": {
"Info": "application/json",
"Name": "9798717402a40970a2d043014d9a6170-analysis.json",
"Extension": "json",
"EntryID": "124@16",
"Type": "ASCII text, with very long lines\n",
"Size": 132549
}
Human Readable Output

8. Get processes by ID
Returns a JSON object that contains a timeline of all process activities as determined by the dynamic analysis engine.
Base Command
threat-grid-get-processes-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.Id | string | The ID of the sample that the PCAP needs to be downloaded for. |
Command Example
!threat-grid-get-processes-by-id id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "9798717402a40970a2d043014d9a6170"
}
},
"File": {
"Info": "application/json",
"SHA1": "365d2e8f7d25c24040a0ea92ae2f14a49cb3a683",
"Name": "9798717402a40970a2d043014d9a6170-processes.json",
"Extension": "json",
"Size": 526700,
"EntryID": "131@16",
"SSDeep": "1536:RWK0+6BL3y3bdvHruY3kvaRLERpXS2wsxWsw9I1O8PDHK1YR50l1n:RWK0+6BL3y3bdvHruY3kvaRLERpXS2w/",
"SHA256": "12f9c229f0eaa2629871db1f7f61e67fa8604ec5a6674378e14c7168f6b95201",
"Type": "ASCII text, with very long lines\n",
"MD5": "b586252a2a6b1681d07667a8c64daa70"
}
}
Human Readable Output
9. Get a PCAP file for a sample by sample ID
Get the tcpdump PCAP file for a specific sample ID, with all the network activity of the sample.
Base Command
threat-grid-get-pcap-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.Id | string | The ID of the sample that the PCAP needs to be downloaded for. |
Command Example
!threat-grid-get-pcap-by-id id=a6cc7ae4e3318e98d94e8a053dd72c47
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "a6cc7ae4e3318e98d94e8a053dd72c47"
}
},
"File": {
"Info": "application/json",
"SHA1": "21bcaf1f8cd8775225a44669f6aa41b9b926d00d",
"Name": "a6cc7ae4e3318e98d94e8a053dd72c47-pcap.json",
"Extension": "json",
"Size": 23804,
"EntryID": "138@16",
"SSDeep": "192:OH03L8c+0SDn9rLLqs6xeewPVtSRhe48CawloZ8XskD5ZdPQ:l+5LweewPHoeNCRloZ8ZD9PQ",
"SHA256": "23b70b0eb5e5d84b253173af6d1d4d955dd8521ff32ddbe3359ecb094d1563cb",
"Type": "tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65536)\n",
"MD5": "5e95685b998cc805183bc6ff17850594"
}
}
Human Readable Output
10. Get warnings for a sample by sample ID
Returns a JSON structure that describes warnings that occurred during the analysis.
Base Command
threat-grid-get-warnings-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.Id | string | The sample ID |
Command Example
!threat-grid-get-warnings-by-id id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "9798717402a40970a2d043014d9a6170"
}
},
"File": {
"Info": "application/json",
"SHA1": "eac159abe40125ad1a3233ffcc127f534df7f629",
"Name": "9798717402a40970a2d043014d9a6170-warnings.json",
"Extension": "json",
"Size": 40,
"EntryID": "145@16",
"SSDeep": "3:YEm4ZBg/VB6n:YEm4ZBg/VB6n",
"SHA256": "1518d6dc7f181113c884b693f15ea4872fd0f1e738ddb1210016829638cd4c8a",
"Type": "ASCII text, with no line terminators\n",
"MD5": "f90b597ba419030d7d4bc97b21f79c90"
}
}
Human Readable Output
11. Get a summary analysis for a sample by sample ID
Returns summary analysis information.
Base Command
threat-grid-get-summary-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.ID | string | The sample ID |
| ThreatGrid.Sample.AnalysisSummary.RegistryCount | number | The registry count of the sample |
| ThreatGrid.Sample.AnalysisSummary.FileName | string | The filename of the sample |
| ThreatGrid.Sample.AnalysisSummary.SHA256 | string | The SHA-256 hash of the sample |
| ThreatGrid.Sample.AnalysisSummary.SampleType | string | The sample type |
| ThreatGrid.Sample.AnalysisSummary.FirstSeen | date | The timestamp when the sample was first seen |
| ThreatGrid.Sample.AnalysisSummary.LastSeen | date | The timestamp when the sample was last seen |
Command Example
!threat-grid-get-summary-by-id id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"ArtifactsCount": {
"Extracted": 1,
"Disk": 3,
"Network": null,
"Memory": 1
},
"AnalysisSummary": {
"RegistryCount": 9,
"SampleType": "9798717402a40970a2d043014d9a6170",
"FileName": "Suspicious_File_To_Be_Scanned.pdf",
"LastSeen": "2018-08-08T10:59:45Z",
"SHA256": "ad5902780a08a34af6d6b1a654fdc6a66d08bf8e7bdaf0d5fc0d0b2ca250144f",
"FirstSeen": "2018-08-08T10:59:45Z"
},
"ID": "9798717402a40970a2d043014d9a6170"
}
}
}
Human Readable Output
12. Get a summary of threats detected during an analysis
Returns a summary of the threats detected during analysis
Base Command
threat-grid-get-threat-summary-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.ID | string | The sample ID |
| ThreatGrid.Sample.MaxSeverity | number | The sample maximum severity |
| ThreatGrid.Sample.Score | number | The sample score |
| ThreatGrid.Sample.Count | number | The sample count |
| ThreatGrid.Sample.MaxConfidence | number | The sample maximum confidence |
| DBotScore.Indicator | string | The indicator value |
| DBotScore.Score | number | The indicator's score |
| DBotScore.Vendor | string | The indicator's vendor |
| DBotScore.Type | string | The indicator's type |
| ThreatGrid.Sample.ThreatFeeds | unknown | The sample threat feeds |
Command Example
!threat-grid-get-threat-summary-by-id id=58e5e66b31484a8529b80a18a33e0814
Context Example
{
"DBotScore": {
"Vendor": "ThreatGrid",
"Indicator": "58e5e66b31484a8529b80a18a33e0814",
"Score": 1,
"Type": "Sample ID"
},
"ThreatGrid": {
"Sample": {
"Count": 0,
"ThreatFeeds": [],
"MaxSeverity": 0,
"Score": 0,
"MaxConfidence": 0,
"ID": "58e5e66b31484a8529b80a18a33e0814"
}
}
}
Human Readable Output
13. Get the HTML report for a sample by sample ID
Get the report.html file for a specific sample ID. This is a stand-alone file with a complete report on the sample run. It is designed to be emailed or printed.
Base Command
threat-grid-get-html-report-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.Sample.Id | string | The ID of the sample that the report was downloaded for |
Command Example
!threat-grid-get-html-report-by-id id=6712d1b712dda4aa63d6073477c367c4
Context Example
{
"ThreatGrid": {
"Sample": {
"Id": "6712d1b712dda4aa63d6073477c367c4"
}
},
"InfoFile": {
"Info": "text/html; charset=utf-8",
"Name": "6712d1b712dda4aa63d6073477c367c4-report.html",
"Extension": "html",
"EntryID": "175@16",
"Type": "HTML document text, UTF-8 Unicode text, with very long lines, with CRLF line terminators\n",
"Size": 771771
}
}
Human Readable Output
14. Download a sample as a ZIP file
Download a sample by using its ID. The downloaded file is an archive of the sample itself, in a zip format as a form of quarantine.
Base Command
threat-grid-download-sample-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The ID of the sample to download | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.DownloadedSamples.Id | string | The ID of the downloaded sample |
Command Example
!threat-grid-download-sample-by-id id=6712d1b712dda4aa63d6073477c367c4
Context Example
{
"ThreatGrid": {
"DownloadedSamples": {
"Id": "6712d1b712dda4aa63d6073477c367c4"
}
},
"File": {
"Info": "application/zip",
"SHA1": "804ac7075ec66262cb267ad56acdff2f507e28a7",
"Name": "6712d1b712dda4aa63d6073477c367c4-sample.zip",
"Extension": "zip",
"Size": 6972,
"EntryID": "184@16",
"SSDeep": "192:R56It4RdYQq8ViAAybtWGIEOV2H6ryqvA7SI0p:/6IKRdYXnyboVMuAk",
"SHA256": "97ae6411493dea29497d94db876af85958d23cdccff574b86be96ad15a4a004a",
"Type": "Zip archive data, at least v2.0 to extract\n",
"MD5": "6dec1a3d1e4df557c2dba87c16f75542"
}
}
Human Readable Output
15. Get a list of IOCs found during a sample run
Returns a JSON list of the Indicators of Compromise identified in this sample run.
Base Command
threat-grid-get-analysis-iocs
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| ioc | The IOC name you want to fetch details for | Optional |
| limit | Limit the number of indicators you would like to see. The list is sorted by indicator severity in descending order. | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.IOCs.Title | The title of the IOC |
| ThreatGrid.IOCs.Confidence | The confidence of the IOC |
| ThreatGrid.IOCs.Severity | The severity of the IOC |
| ThreatGrid.IOCs.IOC | The Threat Grid IOC |
| ThreatGrid.IOCs.IOCCategory | The IOC category of the IOC |
| DBotScore.Indicator | The indicator value |
| DBotScore.Vendor | The indicator vendor |
| DBotScore.Type | The indicator type |
| DBotScore.Score | The indicator score |
| ThreatGrid.IOCs.Data.IP | The IP of the IOC |
| ThreatGrid.IOCs.Data.URL | The URL of the IOC |
| ThreatGrid.IOCs.Data.Domain | The domain of the IOC |
| ThreatGrid.IOCs.Data.Path | The path of the IOC |
| ThreatGrid.IOCs.Data.SHA256 | SHA-256 value of the IOC |
| ThreatGrid.IOCs.Tags | IOC tags |
Command Example
!threat-grid-get-analysis-iocs id=a6cc7ae4e3318e98d94e8a053dd72c47
Context Example
{
"DBotScore": [
{
"Vendor": "ThreatGrid",
"Indicator": "antivirus-flagged-artifact",
"Score": 2,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "pe-uses-dot-net",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "dns-dynamic-domain",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "memory-execute-readwrite",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "modified-executable",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "netsh-firewall-generic",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "network-snort-malware",
"Score": 3,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "registry-autorun-key-data-dir",
"Score": 2,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "firewall-exception-user-dir",
"Score": 3,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "modified-file-in-user-dir",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "netsh-firewall-add",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "registry-autorun-key-modified",
"Score": 2,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "malware-known-trojan-av",
"Score": 3,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "feed-domain-rat",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "network-fast-flux-domain",
"Score": 1,
"Type": "IOC"
},
{
"Vendor": "ThreatGrid",
"Indicator": "artifact-flagged-anomaly",
"Score": 1,
"Type": "IOC"
}
],
"ThreatGrid": {
"IOCs": [
{
"Confidence": 80,
"Severity": 80,
"Tags": [
"file"
],
"IOCCategory": [
"forensics"
],
"Title": "Artifact Flagged by Antivirus",
"Data.Path": [
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe"
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "antivirus-flagged-artifact"
},
{
"Confidence": 60,
"Severity": 35,
"Tags": [
"artifact",
"library",
"PE"
],
"IOCCategory": [
"attribute"
],
"Title": "Executable Artifact Uses .NET",
"Data.Path": [
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe"
],
"Data.URL": [
null,
null,
null
],
"Data.SHA256": [
null,
null,
null
],
"IOC": "pe-uses-dot-net"
},
{
"Confidence": 60,
"Severity": 50,
"Tags": [
"evasion"
],
"IOCCategory": [
"network"
],
"Title": "Dynamic DNS Domain Detected",
"Data.Path": [
null,
null
],
"Data.URL": [
null,
null
],
"Data.SHA256": [
null,
null
],
"IOC": "dns-dynamic-domain"
},
{
"Confidence": 50,
"Severity": 50,
"Tags": [
"memory"
],
"IOCCategory": [
"evasion"
],
"Title": "Potential Code Injection Detected",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "memory-execute-readwrite"
},
{
"Confidence": 100,
"Severity": 60,
"Tags": [
"executable",
"file",
"process",
"PE"
],
"IOCCategory": [
"file",
"persistence"
],
"Title": "Process Modified an Executable File",
"Data.Path": [
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe"
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "modified-executable"
},
{
"Confidence": 100,
"Severity": 70,
"Tags": [
"process",
"firewall",
"bypass",
"networking"
],
"IOCCategory": [
"weakening"
],
"Title": "Netsh.exe Used to Alter Windows Firewall",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "netsh-firewall-generic"
},
{
"Confidence": 95,
"Severity": 95,
"Tags": [
"snort",
"malware"
],
"IOCCategory": [
"network"
],
"Title": "Network Stream Marked as Malware by Snort",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "network-snort-malware"
},
{
"Confidence": 100,
"Severity": 90,
"Tags": [
"process",
"autorun",
"registry",
"compound"
],
"IOCCategory": [
"persistence"
],
"Title": "Registry Persistence Mechanism Refers to an Executable in a User Data Directory",
"Data.Path": [
null,
null
],
"Data.URL": [
null,
null
],
"Data.SHA256": [
null,
null
],
"IOC": "registry-autorun-key-data-dir"
},
{
"Confidence": 95,
"Severity": 100,
"Tags": [
"file",
"trojan",
"artifact",
"compound"
],
"IOCCategory": [
"weakening"
],
"Title": "User Directory FireWall Exception",
"Data.Path": [
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe"
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "firewall-exception-user-dir"
},
{
"Confidence": 80,
"Severity": 70,
"Tags": [
"executable",
"file",
"process"
],
"IOCCategory": [
"file"
],
"Title": "Process Modified File in a User Directory",
"Data.Path": [
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe"
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "modified-file-in-user-dir"
},
{
"Confidence": 100,
"Severity": 70,
"Tags": [
"process",
"firewall",
"bypass",
"networking"
],
"IOCCategory": [
"weakening"
],
"Title": "Netsh.exe Used to Add Program to Firewall Allowed Program List",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "netsh-firewall-add"
},
{
"Confidence": 60,
"Severity": 80,
"Tags": [
"process",
"autorun",
"registry"
],
"IOCCategory": [
"persistence"
],
"Title": "Process Modified Autorun Registry Key Value",
"Data.Path": [
null,
null,
null
],
"Data.URL": [
null,
null,
null
],
"Data.SHA256": [
null,
null,
null
],
"IOC": "registry-autorun-key-modified"
},
{
"Confidence": 95,
"Severity": 100,
"Tags": [
"trojan",
"RAT"
],
"IOCCategory": [
"malware"
],
"Title": "Artifact Flagged as Known Trojan by Antivirus",
"Data.Path": [
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe"
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "malware-known-trojan-av"
},
{
"Confidence": 25,
"Severity": 25,
"Tags": [
"communications",
"command and control"
],
"IOCCategory": [
"network"
],
"Title": "RAT Queried Domain",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "feed-domain-rat"
},
{
"Confidence": 20,
"Severity": 35,
"Tags": [
"network",
"ttl",
"dns",
"fast flux",
"command and control"
],
"IOCCategory": [
"network"
],
"Title": "DNS Response Contains Low Time to Live (TTL) Value",
"Data.Path": [
null
],
"Data.URL": [
null
],
"Data.SHA256": [
null
],
"IOC": "network-fast-flux-domain"
},
{
"Confidence": 80,
"Severity": 60,
"Tags": [
"anomaly",
"static"
],
"IOCCategory": [
"forensics"
],
"Title": "Static Analysis Flagged Artifact As Anomalous",
"Data.Path": [
"\\TEMP\\2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe",
"\\Users\\Administrator\\AppData\\Roaming\\Mmas.exe",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d.exe"
],
"Data.URL": [
null,
null,
null
],
"Data.SHA256": [
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d",
"2c0146af31a67ef3f8193761d710751641e67690df2599990e44af201dd71a1d"
],
"IOC": "artifact-flagged-anomaly"
}
]
}
}
Human Readable Output
16. Get information for the logged in user
Return information for the logged in user.
Base Command
threat-grid-who-am-i
Input
There is no input for this command.
Context Output
| Path | Description |
|---|---|
| ThreatGrid.User.Email | Email of the logged in user |
| ThreatGrid.User.Login | Login ID of the logged in user |
| ThreatGrid.User.Name | Name of the logged in user |
| ThreatGrid.User.OrganizationId | The Organization ID of the logged in user |
| ThreatGrid.User.Role | Role of the logged in user |
Command Example
!threat-grid-who-am-i
Context Example
{
"ThreatGrid": {
"User": {
"Organization": 42,
"Login": "String",
"Role": "org-admin",
"Email": "String",
"Name": "String"
}
}
}
Human Readable Output
17. Get the rate limit for a specified user
Get rate limit for a specific user name. ThreatGrid employs a simple rate limiting method for sample submissions by specifying the number of samples which can be submitted within some variable time period by a user. Multiple rate limits can be employed to form overlapping submission limits. For example, 20 submissions per hour AND 400 per day.
Base Command
threat-grid-user-get-rate-limit
Input
| Argument Name | Description | Required |
|---|---|---|
| login | User login name | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.User.RateLimit.Minutes | number | Array of array(s) representing submission(s) per minute(s) or the string"nil" to clear the value. Example: [[5, 1440]] which represents 5 samples per day. This field represent the minutes. |
| ThreatGrid.User.RateLimit.Samples | number | Array of array(s) representing submission(s) per minute(s) or the string"nil" to clear the value. Example: [[5, 1440]] which represents 5 samples per day. This field represent the number of samples allowed. |
| ThreatGrid.User.RateLimit.SubmissionWaitSeconds | number | The number of seconds to wait for a submission to get uploaded on the platform. |
| ThreatGrid.User.RateLimit.SubmissionsAvailable | number | The number of submissions available for the specified username |
Command Example
!threat-grid-user-get-rate-limit login="user_name"
Context Example
{
"ThreatGrid": {
"User": {
"RateLimit": [
{
"SubmissionWaitSeconds": 0,
"SubmissionsAvailable": null
}
]
}
}
}
Human Readable Output
18. Get a specific threat feed
Gets a specific threat feed.
Base Command
threat-grid-get-specific-feed
Input
| Argument Name | Description | Required |
|---|---|---|
| feed-name | The feed name | Required |
| feed-period | Feed daily date (YYYY-MM-DD) | Optional |
| output-type | The output type | Optional |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-specific-feed feed-name=rat-dns output-type=csv
Human Readable Output
19. Convert a URL to a file for detonation
Convert a URL into a file for Threat Grid file detonation.
Base Command
threat-grid-url-to-file
Input
| Argument Name | Description | Required |
|---|---|---|
| urls | Comma-separated list of URLs to convert | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-url-to-file urls=www.google.com
Human Readable Output
20. Get rate limits for an organization
Get rate limits applied to an organization. ThreatGrid employs a simple rate limiting method for sample submissions by specifying the number of samples which can be submitted within some variable time period by an entire organization and/or per a license basis. Multiple rate limits can be employed to form overlapping submission limits. For example, 20 submissions per hour AND 400 per day.
Base Command
threat-grid-organization-get-rate-limit
Input
| Argument Name | Description | Required |
|---|---|---|
| adminLogin | The admin user login name to be used for getting the rate limits | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| ThreatGrid.User.RateLimit.Minutes | number | Array of array(s) representing submission(s) per minute(s) or the string"nil" to clear the value. Example: [[5, 1440]], which represents 5 samples per day. This field represent the minutes. |
| ThreatGrid.User.RateLimit.Samples | number | Array of array(s) representing submission(s) per minute(s) or the string"nil" to clear the value. Example: [[5, 1440]], which represents 5 samples per day. This field represent the number of samples allowed. |
| ThreatGrid.User.RateLimit.SubmissionWaitSeconds | number | The number of seconds to wait for a submission to be uploaded on the platform |
| ThreatGrid.User.RateLimit.SubmissionsAvailable | number | The number of submissions available for the entire organization |
Command Example
!threat-grid-organization-get-rate-limit adminLogin="admin"
Context Example
{
"ThreatGrid": {
"User": {
"RateLimit": [
{
"SubmissionsAvailable": 47,
"SubmissionWaitSeconds": 0,
"Minutes": 1440,
"Samples": 50
}
]
}
}
}
Human Readable Output
21. Search IP addresses
Search IPs.
Base Command
threat-grid-search-ips
Input
| Argument Name | Description | Required |
|---|---|---|
| network_dst | Destination IP | Optional |
| network_src | Source IP | Optional |
| artifact | Artifact SHA-256 | Optional |
| domain | Domain name | Optional |
| url | URL | Optional |
| asn | IP asn | Optional |
| geo_location | IP geo-location information | Optional |
| cidr | IP/CIDR | Optional |
| ioc | IOC name | Optional |
| tag | Tag name | Optional |
Context Output
There is no context output for this command.
Command Example
!threat-grid-search-ips tag=malicious
Human Readable Output
22. Get annotation data for an analysis
Returns data about the annotations of the analysis.
Base Command
threat-grid-get-analysis-annotations
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP | IP address present in the annotation |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.Asn | Autonomous system number of the IP |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.City | IP city |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.Country | IP country |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.Org | IP Org |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.Region | IP region |
| ThreatGrid.AnalysisResults.Sample.Id.Annotations.IP.Timestamp | IP timestamp |
Command Example
!threat-grid-get-analysis-annotations id=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"AnalysisResults": {
"Sample": {
"Id": {
"Annotations": [
{
"IP": "192.168.1.11",
"IP.Asn": null,
"IP.Region": null,
"IP.Timestamp": 1533726370,
"IP.City": null,
"IP.Country": null,
"IP.Org": null
},
{
"IP": "255.255.255.255",
"IP.Asn": null,
"IP.Region": null,
"IP.Timestamp": 1533726370,
"IP.City": null,
"IP.Country": null,
"IP.Org": null
},
{
"IP": "0.0.0.0",
"IP.Asn": null,
"IP.Region": null,
"IP.Timestamp": 1533726370,
"IP.City": null,
"IP.Country": null,
"IP.Org": null
},
{
"IP": "192.168.1.1",
"IP.Asn": null,
"IP.Region": null,
"IP.Timestamp": 1533726370,
"IP.City": null,
"IP.Country": null,
"IP.Org": null
},
{
"IP": "192.168.1.255",
"IP.Asn": null,
"IP.Region": null,
"IP.Timestamp": 1533726370,
"IP.City": null,
"IP.Country": null,
"IP.Org": null
}
]
}
}
}
}
}
Human Readable Output
23. Search samples
Searches samples.
Base Command
threat-grid-search-samples
Input
| Argument Name | Description | Required |
|---|---|---|
| ioc | IOC name | Optional |
| checksum | Checksum (SHA-256, MD5, or SHA-1) | Optional |
| checksum_sample | Checksum of sample | Optional |
| path | Path name | Optional |
| path_sample | Sample path name | Optional |
| path_artifact | Artifact name | Optional |
| path_deleted | search by path names that were deleted | Optional |
| url | search by url | Optional |
| registry_key | search by registry key accessed | Optional |
| domain | search by domain name | Optional |
| domain_dns_lookup | search by domain name used for DNS lookups | Optional |
| domain_http_request | search by domain name used in HTTP request | Optional |
| ip | search by ip address | Optional |
| ip_dns_lookup | search by IP address returned in DNS lookup | Optional |
| ip_src | search by network stream source IP address | Optional |
| ip_dst | search by network stream destination IP address | Optional |
| tag | search by sample tag | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Samples.Result | Result ID |
| ThreatGrid.Samples.Details | Detail of sample |
Command Example
!threat-grid-search-samples checksum=d3c852ed16a7e4a4cde88266c060ee064ed047a8a43685ae52ce6c82f40e5b3f
Context Example
{
"ThreatGrid": {
"Sample": {
"Details": "/api/v2/samples/b9218ef55a1bc6d50456f32dc5e31fba",
"Result": "b9218ef55a1bc6d50456f32dc5e31fba"
}
}
}
Human Readable Output
24. Search URLs
Search URLs.
Base Command
threat-grid-search-urls
Input
| Argument Name | Description | Required |
|---|---|---|
| url | URL pattern | Optional |
| sibling | URL pattern prefix | Optional |
| neighbor | Hostname of URL | Optional |
| sha256 | SHA-56 of URL | Optional |
| md5 | MD5 of URL | Optional |
| sha1 | SHA-1 of URL | Optional |
| protocol | Protocol name | Optional |
| host | Hostname | Optional |
| port | Port number | Optional |
| path | Path name | Optional |
| query | Query | Optional |
| reference | Fragment identifier | Optional |
| ip | IP address of network stream | Optional |
| artifact | Artifact downloaded | Optional |
| tag | URL tag | Optional |
Context Output
There is no context output for this command.
Command Example
!threat-grid-search-urls ip=1.1.1.3
25. Get the states of samples
Returns Threat Grid samples state.
Base Command
threat-grid-get-samples-state
Input
| Argument Name | Description | Required |
|---|---|---|
| ids | Comma-separated list of sample IDs | Optional |
Context Output
| Path | Description |
|---|---|
| ThreatGrid.Sample.ID | The sample ID, globally unique, and the canonical identifier of this sample analysis |
| ThreatGrid.Sample.State | The state of the sample, one of a stable set of strings “wait", "prep", "run", "proc", "succ", "fail” |
Command Example
!threat-grid-get-samples-state ids=9798717402a40970a2d043014d9a6170
Context Example
{
"ThreatGrid": {
"Sample": {
"State": "succ",
"ID": "9798717402a40970a2d043014d9a6170"
}
}
}
Human Readable Output
26. Get the threat feed for artifacts
Get the threat feed for artifacts.
Base Command
threat-grid-feeds-artifacts
Input
| Argument Name | Description | Required |
|---|---|---|
| sha256 | Restrict returned records with this SHA-256 | Optional |
| sha1 | Restrict returned records with this SHA-1 | Optional |
| md5 | Restrict returned records with this MD5 | Optional |
| path | Restrict returned records to this path or path fragment. | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, defaults to 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, defaults to 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Command Example
!threat-grid-feeds-artifacts after=2018-01-18T00:00:00 before=2018-01-18T00:02:07 confidence=75 severity=75
Human Readable Output
27. Get the threat feed for a domain
Get the threat feed for a domain.
Base Command
threat-grid-feeds-domain
Input
| Argument Name | Description | Required |
|---|---|---|
| domain | Restrict returned records to this domain or hostname | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, defaults to 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, defaults to 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Command Example
!threat-grid-feeds-domain after=2018-01-18T00:00:00 before=2018-01-18T00:10:00 confidence=75 severity=75
Human Readable Output
28. Get the threat feed for an IP address
Returns the threat feed for an IP address.
Base Command
threat-grid-feeds-ip
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | Restrict returned records to this IP or CIDR block | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, defaults to 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, defaults to 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Command Example
!threat-grid-feeds-ip after=2018-01-18T00:00:00 before=2018-01-18T01:00:00 confidence=75 severity=75
Human Readable Output
29. Get the threat feed for a network stream
Get network stream threat feed
Base Command
threat-grid-feeds-network-stream
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | Restrict returned records to this IP address | Optional |
| port | Restrict returned records to this port number | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, defaults is 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, defaults is 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Command Example
!threat-grid-feeds-network-stream after=2018-01-18T00:00:00 before=2018-01-18T00:02:10 confidence=75 severity=75
Human Readable Output
30. Get the threat feed for a path
Returns the threat feed for a path.
Base Command
threat-grid-feeds-path
Input
| Argument Name | Description | Required |
|---|---|---|
| path | Restrict returned records to this path or path fragment | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, defaults to 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, defaults to 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Context Output
There is no context output for this command.
Command Example
!threat-grid-feeds-path after=2018-01-18T00:00:00 before=2018-01-18T00:03:00 confidence=75 severity=75
Human Readable Output
31. Get the threat feed for URL
Returns the threat feed for a URL.
Base Command
threat-grid-feeds-url
Input
| Argument Name | Description | Required |
|---|---|---|
| url | Restrict returned records to this URL or URL fragment | Optional |
| before | A date/time (ISO 8601), restricting results to samples submitted before it | Optional |
| after | A date/time (ISO 8601), restricting results to samples submitted after it | Optional |
| confidence | Restrict to IOCs with this confidence score or higher, default is 80 | Optional |
| severity | Restrict to IOCs with this severity score or higher, default is 80 | Optional |
| ioc | Restrict returned records to events of this type | Optional |
| org-only | If “true”, will only match against samples submitted by your organization | Optional |
| user-only | If “true”, will only match against samples you submitted | Optional |
| sample | A comma-separated list of sample IDs. Restrict results to these samples. | Optional |
Context Output
There is no context output for this command.
Command Example
!threat-grid-feeds-url after=2018-01-18T00:00:00 before=2018-01-18T00:05:00 confidence=75 severity=75
Human Readable Output
32. Get the artifact for a sample ID by artifact ID
Returns the sample ID artifact with artifact id
Base Command
threat-grid-get-analysis-artifact
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| aid | The artifact ID requested | Required |
Command Example
!threat-grid-get-analysis-artifact id=a6cc7ae4e3318e98d94e8a053dd72c47 aid=1
Human Readable Output
33. Get artifacts for a sample ID
Returns the sample id artifacts
Base Command
threat-grid-get-analysis-artifacts
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-analysis-artifacts id=a6cc7ae4e3318e98d94e8a053dd72c47
Human Readable Output
34. Get analysis data for an IOC
Returns data for the specified IOC.
Base Command
threat-grid-get-analysis-ioc
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| ioc | The requested IOC | Required |
Command Example
!threat-grid-get-analysis-ioc id=8ee72188b95b7d8f4e1a6c4842e98566 ioc=network-communications-http-get-url
Human Readable Output
35. Get metadata for an analysis
Returns metadata about the analysis.
Base Command
threat-grid-get-analysis-metadata
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Command Example
!threat-grid-get-analysis-metadata id=58e5e66b31484a8529b80a18a33e0814
Human Readable Output
36. Get data for a network stream
Returns data regarding a specific network stream
Base Command
threat-grid-get-analysis-network-stream
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| nsid | The network stream ID | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-analysis-network-stream id=a6cc7ae4e3318e98d94e8a053dd72c47 nsid=1
Human Readable Output
37. Get the analysis for a network stream
Returns the network stream analysis.
Base Command
threat-grid-get-analysis-network-streams
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-analysis-network-streams id=a6cc7ae4e3318e98d94e8a053dd72c47
Human Readable Output
38. Get data for a process ID in an analysis
Returns data regarding the specific process ID in the analysis.
Base Command
threat-grid-get-analysis-process
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
| pid | The requested process ID | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-analysis-process id=9798717402a40970a2d043014d9a6170 pid=4
Human Readable Output
39. Get data for an analysis process
Returns data regarding the analysis processes.
Base Command
threat-grid-get-analysis-processes
Input
| Argument Name | Description | Required |
|---|---|---|
| id | The sample ID | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-get-analysis-processes id=9798717402a40970a2d043014d9a6170
Human Readable Output
40. Submit URLs for analysis
Submit the URL for Threat analysis processes.
Base Command
threat-grid-submit-urls
Input
| Argument Name | Description | Required |
|---|---|---|
| url | The URL to submit to ThreatGrid | Required |
Context Output
There is no context output for this command.
Command Example
threat-grid-submit-urls url="www.example.com"
41. Advanced search for URLs/Samples already submitted for analysis
Perform advanced search on ThreatGrid
Base Command
threat-grid-advanced-search
Input
| Argument Name | Description | Required |
|---|---|---|
| query | ThreatGrid search query to run | Required |
Context Output
There is no context output for this command.
Command Example
!threat-grid-advanced-search query="{
\"query\": \"query get_sample($q_json:
String) {sample(, q_json: $q_json,limit: 3) {submitted_at id submitted_file_type status threat_score state login url}}\",\"variables\": {\"q_json\": \"{\\\"op\\\": \\\"and\\\",\\\"clauses\\\": [{\\\"op\\\": \\\"attr\\\",\\\"attr\\\": \\\"submitted_file_name\\\",\\\"comp_op\\\": \\\"eq\\\",\\\"value\\\": \\\"www.example.com_.url\\\"}]}\"}}"
Configuration parameters
server— Server URL (e.g. https://192.168.0.1) (required)token— API token (required)insecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (43)
-
threat-grid-advanced-searchDeprecatedAdvanced search that allows searching URLS, Submissions, Samples etc...
-
threat-grid-detonate-fileDeprecatedDetonates URL address through Threat Grid
-
threat-grid-download-artifactDeprecatedDownload an artifact by using its ID.
-
threat-grid-download-sample-by-idDeprecatedDownload a sample by using its ID. The downloaded file is an archive of the sample itself, in a zip format as a form of quarantine.
-
threat-grid-feeds-artifactsDeprecatedGet artifacts threat feed
-
threat-grid-feeds-domainDeprecatedGet domain threat feed
-
threat-grid-feeds-ipDeprecatedGet ips threat feed
-
threat-grid-feeds-network-streamDeprecatedGet network stream threat feed
-
threat-grid-feeds-pathDeprecatedGet path threat feed
-
threat-grid-feeds-urlDeprecatedGet url threat feed
-
threat-grid-get-analysis-annotationsDeprecatedReturns data regarding the annotations of the anlysis
-
threat-grid-get-analysis-artifactDeprecatedReturns the sample id artifact with artifact id
-
threat-grid-get-analysis-artifactsDeprecatedReturns the sample id artifacts
-
threat-grid-get-analysis-by-idDeprecatedThe detailed overview of dynamic and static analysis results for the sample
-
threat-grid-get-analysis-iocDeprecatedReturns data regarding the specified Indicator of Compromise
-
threat-grid-get-analysis-iocsDeprecatedReturns a JSON list of the Indicators of Compromise identified in this sample run
-
threat-grid-get-analysis-metadataDeprecatedReturns metadata about the analysis
-
threat-grid-get-analysis-network-streamDeprecatedReturns data regarding a specific network stream
-
threat-grid-get-analysis-network-streamsDeprecatedReturns the network stream analysis
-
threat-grid-get-analysis-processDeprecatedReturns data regarding the specifiic process id in the analysis
-
threat-grid-get-analysis-processesDeprecatedReturns data regarding the analysis processes
-
threat-grid-get-html-report-by-idDeprecatedGet the report.html file for a specific Sample ID. This is a stand-alone file with a complete report on the sample run. It is designed to be emailed or printed.
-
threat-grid-get-pcap-by-idDeprecatedGet the tcpdump PCAP file for a specific Sample ID, with all the network activity of the sample
-
threat-grid-get-processes-by-idDeprecatedGet a JSON object which contains a timeline of all process activities as determined by the dynamic analysis engine.
-
threat-grid-get-sample-by-idDeprecatedGet threat grid sample by id
-
threat-grid-get-sample-state-by-idDeprecatedGet threat grid sample state by id
-
threat-grid-get-samplesDeprecatedSearch samples on the Threat Grid platform. Input parameters are ANDed together. Only finished samples can be searched (that is, the ones that are having a status of succ or fail.)
-
threat-grid-get-samples-stateDeprecatedGet threat grid samples state
-
threat-grid-get-specific-feedDeprecatedGets a specific threat feed
-
threat-grid-get-summary-by-idDeprecatedReturns summary analysis information
-
threat-grid-get-threat-summary-by-idDeprecatedReturns a summary of the threats detected during analysis
-
threat-grid-get-video-by-idDeprecatedGet the sample analysis video by id
-
threat-grid-get-warnings-by-idDeprecatedGets a JSON structure describing any warnings that occured during the analysis
-
threat-grid-organization-get-rate-limitDeprecatedGet rate limits applied to an organization. ThreatGrid employs a simple rate limiting method for sample submissions by specifying the number of samples which can be submitted within some variable time period by an entire organization and/or per a license basis. Multiple rate limits can be employed to form overlapping submission limits. For example, 20 submissions per hour AND 400 per day.
-
threat-grid-search-ipsDeprecatedSearch IPs. Please provide a single argument (only one) to use this command, as the API supports 1 filter at a time.
-
threat-grid-search-samplesDeprecatedSearch Samples. Please provide a single argument (only one) to use this command, as the API supports 1 filter at a time.
-
threat-grid-search-submissionsDeprecatedSearch threat grid submissions
-
threat-grid-search-urlsDeprecatedSearch urls. Please provide a single argument (only one) to use this command, as the API supports 1 filter at a time.
-
threat-grid-submit-urlsDeprecatedSubmit urls for analysis.
-
threat-grid-upload-sampleDeprecatedSubmits a sample to threat grid for analysis
-
threat-grid-url-to-fileDeprecatedConvert a URL into a file for Threat Grid file detonation.
-
threat-grid-user-get-rate-limitDeprecatedGet rate limit for a specific user name. ThreatGrid employs a simple rate limiting method for sample submissions by specifying the number of samples which can be submitted within some variable time period by a user. Multiple rate limits can be employed to form overlapping submission limits. For example, 20 submissions per hour AND 400 per day.
-
threat-grid-who-am-iDeprecatedGet logged in user
import demistomock as demisto # noqa: F401 from CommonServerPython import * # noqa: F401 import requests import urllib3 urllib3.disable_warnings() if not demisto.getParam('proxy'): del os.environ['HTTP_PROXY'] del os.environ['HTTPS_PROXY'] del os.environ['http_proxy'] del os.environ['https_proxy'] URL = demisto.getParam('server') if URL[-1] != '/': URL += '/' API_KEY = str(demisto.getParam('token')) SUB_API = 'api/v2/' USER_API = 'api/v3/' VALIDATE_CERT = not demisto.params().get('insecure', True) ''' Header names maps ''' # Format: {'Key': [correspondng headers]} SAMPLE_ANALYSIS_HEADERS_MAP = { 'File': [ 'FileName', 'Type', 'Size', 'MD5', 'SHA1', 'SHA256', 'MagicType' ], 'Domain': [ 'Name', 'Status' ], 'Network': [ 'Ts_Begin', 'Destination', 'DestinationPort', 'Transport', 'Packets', 'PacketSize' ], 'Regitry Keys Created': [ 'name', 'options', 'access' ], 'Regitry Keys Deleted': [ 'name' ], 'Regitry Keys Modified': [ 'name', 'options', 'access' ], 'Sample': [ 'ID', 'ThreatScore', 'HeuristicScore', 'ProcessName', 'CMD', 'Directory', 'Memory', 'Children' ], 'Enviornment Details': [ 'VM ID', 'VM Name', 'StartedAt', 'EndedAt', 'Runtime' ], 'VT': [ 'Hits', 'Engines' ] } def req(method, path, params={'api_key': API_KEY}, body=None): """ Send the request to ThreatGrid and return the JSON response """ if body is not None: headers = { 'Accept': 'application/json', 'Content-Type': 'application/json' } r = requests.request(method, URL + path, headers=headers, params=params, data=body, verify=VALIDATE_CERT) if r.status_code != (requests.codes['created'] or requests.codes['ok']): return_error('Error in API call to Threat Grid service %s - %s' % (path, r.text)) return r else: r = requests.request(method, URL + path, params=params, verify=VALIDATE_CERT) if r.status_code != requests.codes.ok: return_error('Error in API call to Threat Grid service %s - %s' % (path, r.text)) return r def handle_filters(): """ Handle filters associated with samples """ params = {'api_key': API_KEY} for k in demisto.args(): if demisto.getArg(k): params[k] = demisto.getArg(k) return params def get_with_limit(obj, path, limit=None): """ Get from path with optional limit """ res = demisto.get(obj, path) try: if limit: if len(res) > limit: if isinstance(res, dict): return {k: res[k] for k in list(res.keys())[:limit]} elif isinstance(res, list): return res[:limit] # If res has no len, or if not a list or a dictionary return res except Exception: return res return res def sample_to_readable(k): """ Convert sample request to data dictionary """ return { 'ID': demisto.get(k, 'id'), 'Filename': demisto.get(k, 'filename'), 'State': demisto.get(k, 'state'), 'Status': demisto.get(k, 'status'), 'MD5': demisto.get(k, 'md5'), 'SHA1': demisto.get(k, 'sha1'), 'SHA256': demisto.get(k, 'sha256'), 'OS': demisto.get(k, 'os'), 'SubmittedAt': demisto.get(k, 'submitted_at'), 'StartedAt': demisto.get(k, 'started_at'), 'CompletedAt': demisto.get(k, 'completed_at') } def download_sample(): """ Download a sample given the sample id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/sample.zip') ec = {'ThreatGrid.DownloadedSamples.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Download - \n' + 'Your download request has been completed successfully for ' + sample_id, 'Contents': ec, 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-sample.zip', r.content) ]) def get_samples(): """ Get samples matching the provided filters. """ r = req('GET', SUB_API + 'samples', params=handle_filters()) samples = [] for k in demisto.get(r.json(), 'data.items'): samples.append(sample_to_readable(k)) md = tableToMarkdown('ThreatGrid - List of Samples', samples, [ 'ID', 'Filename', 'State', 'Status', 'MD5', 'SHA1', 'SHA256', 'OS', 'SubmittedAt', 'StartedAt', 'CompletedAt' ]) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': samples}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r.json() }) def get_sample_by_id(): """ Get information about a sample given its id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id) sample = sample_to_readable(r.json().get('data')) md = tableToMarkdown('ThreatGrid - Sample', [sample], [ 'ID', 'Filename', 'State', 'Status', 'MD5', 'SHA1', 'SHA256', 'OS', 'SubmittedAt', 'StartedAt', 'CompletedAt' ]) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': sample}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r.json() }) def get_sample_state_helper(sample_ids): """ Helper for getting sample state """ samples = [] requests = [] for sample_id in sample_ids: r = req('GET', SUB_API + 'samples/' + sample_id + '/state') samples.append({ 'ID': sample_id, 'State': demisto.get(r.json(), 'data.state') }) requests.append(r.json()) return {'samples': samples, 'requests': requests} def get_sample_state_by_id(): """ Get the state of a sample given its id """ ids = [] # type: list if demisto.getArg('ids'): ids += argToList(demisto.getArg('ids')) if demisto.getArg('id'): ids.append(demisto.getArg('id')) response = get_sample_state_helper(ids) md = tableToMarkdown('ThreatGrid - Sample state', response['samples'], ['ID', 'State']) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': response['samples']}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': response['requests'] }) def upload_sample(): """ Upload a sample """ args = {} for k in demisto.args(): if demisto.getArg(k) and k != 'file-id': args[k] = demisto.getArg(k) args['api_key'] = API_KEY fileData = demisto.getFilePath(demisto.getArg('file-id')) filename = demisto.getArg('filename').replace('"', '').replace('\n', '') with open(fileData['path'], 'rb') as f: r = requests.request('POST', URL + SUB_API + 'samples', files={'sample': (filename, f)}, data=args, verify=VALIDATE_CERT) if r.status_code != requests.codes.ok: if r.status_code == 503: return_error('Sample upload failed. File was already uploaded.') return_error('Error in API call to Threat Grid service %s - %s' % ('samples', r.text)) sample = sample_to_readable(r.json().get('data')) md = tableToMarkdown('ThreatGrid - Sample Upload', [sample], [ 'ID', 'Filename', 'State', 'Status', 'MD5', 'SHA1', 'SHA256', 'OS', 'SubmittedAt' ]) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': sample}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r.json() }) return sample.get('ID') def get_html_report_by_id(): """ Download the html report for a sample given the id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/report.html') ec = {'ThreatGrid.Sample.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Run HTML Report -\n' + 'Your sample run HTML report download request has been completed successfully for ' + sample_id, 'Contents': r.text, 'ContentsFormat': formats['html'] }, fileResult(sample_id + '-report.html', r.content, file_type=entryTypes['entryInfoFile']) ]) def get_pcap_by_id(): """ Download the pcap for a sample given the id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/network.pcap') ec = {'ThreatGrid.Sample.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Run PCAP File -\n' + 'Your sample run PCAP file download request has been completed successfully for ' + sample_id, 'Contents': ec, 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-pcap.json', r.content) ]) def get_processes_by_id(): """ Download processes file for a sample given the id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/processes.json') ec = {'ThreatGrid.Sample.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Run Processes File -\n' + 'Your sample run processes file download request has been completed successfully for ' + sample_id, 'Contents': r.json(), 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-processes.json', r.content) ]) def get_summary_by_id(): """ Get analysis summary information for a sample given the id """ sample_id = demisto.getArg('id') request = req('GET', SUB_API + 'samples/' + sample_id + '/summary') r = request.json() sample = {'ID': sample_id, 'AnalysisSummary': [], 'ArtifactsCount': []} # Search submissions request for extra information sub_request = req('GET', SUB_API + 'search/submissions', params={'api_key': API_KEY, 'q': demisto.get(r, 'data.sha256')}) sub_r = sub_request.json() sub_r_first_item = demisto.get(sub_r, 'data.items')[0] sample['AnalysisSummary'] = { 'RegistryCount': demisto.get(r, 'data.registry_count'), 'FileName': demisto.get(r, 'data.filename'), 'SHA256': demisto.get(r, 'data.sha256'), 'SampleType': demisto.get(sub_r_first_item, 'item.analysis.metadata.submitted_file.type'), 'FirstSeen': demisto.get(r, 'data.first_seen'), 'LastSeen': demisto.get(r, 'data.last_seen'), } sample['ArtifactsCount'] = { 'Network': demisto.get(r, 'data.artifacts.network'), 'Disk': demisto.get(r, 'data.artifacts.disk'), 'Memory': demisto.get(r, 'data.artifacts.memory'), 'Extracted': demisto.get(r, 'data.artifacts.extracted') } md = tableToMarkdown('ThreatGrid - Sample Summary for ' + sample_id, [sample['AnalysisSummary']], ['RegistryCount', 'FileName', 'SHA256', 'SampleType', 'FirstSeen', 'LastSeen']) md += tableToMarkdown('ThreatGrid - Sample Artifacts', [sample['ArtifactsCount']], ['Network', 'Disk', 'Memory', 'Extracted']) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': sample}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r }) def calc_score(score): """ Convert threatgrid score to dbot score """ if not score: return 0 dbot_score = 1 if score >= 95: dbot_score = 3 elif score >= 75: dbot_score = 2 return dbot_score def get_threat_summary_by_id(): """ Get threat summary information for a sample given the id """ sample_id = demisto.getArg('id') request = req('GET', SUB_API + 'samples/' + sample_id + '/threat') r = request.json() sample = { 'ID': sample_id, 'MaxSeverity': demisto.get(r, 'data.max-severity'), 'Score': demisto.get(r, 'data.score'), 'Count': demisto.get(r, 'data.count'), 'MaxConfidence': demisto.get(r, 'data.max-confidence'), 'ThreatFeeds': demisto.get(r, 'data.bis') } dbot = { 'Vendor': 'ThreatGrid', 'Type': 'Sample ID', 'Indicator': sample['ID'], 'Score': calc_score(sample['Score']) } md = tableToMarkdown('ThreatGrid - Threat Summary', [sample], ['ID', 'MaxSeverity', 'Score', 'Count', 'MaxConfidence']) mdTableList = [] for threatfeed in sample['ThreatFeeds']: mdTableList.append({'Threat Feed': threatfeed}) md += tableToMarkdown('Threat Feeds', mdTableList, ['Threat Feed']) md += tableToMarkdown('DBot', [dbot], ['Indicator', 'Score', 'Type', 'Vendor']) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': sample, 'DBotScore': dbot}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r }) def get_video_by_id(): """ Download the video for a sample given the id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/video.webm') ec = {'ThreatGrid.Sample.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Run Video File -\n' + 'Your sample run video file download request has been completed successfully for ' + sample_id, 'Contents': ec, 'ContentsFormat': formats['json'] }, fileResult(sample_id + '.webm', r.content) ]) def get_warnings_by_id(): """ Download the warnings for a sample given the id """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/warnings.json') ec = {'ThreatGrid.Sample.Id': sample_id} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': '### ThreatGrid Sample Run Warnings -\n' + 'Your sample run warnings file download request has been completed successfully for ' + sample_id, 'Contents': ec, 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-warnings.json', r.content) ]) def user_get_rate_limit(): """ Get rate limit for a specified user """ login = demisto.getArg('login') request = req('GET', USER_API + 'users/' + login + '/rate-limit') r = request.json() rate_limit = { 'SubmissionWaitSeconds': demisto.get(r, 'data.user.submission-wait-seconds'), 'SubmissionsAvailable': demisto.get(r, 'data.user.submissions-available') } demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.User.RateLimit': rate_limit}, 'HumanReadable': tableToMarkdown('ThreatGrid - User Rate Limit', [rate_limit], [ 'SubmissionWaitSeconds', 'SubmissionsAvailable' ]), 'ContentsFormat': formats['json'], 'Contents': r }) def organization_get_rate_limit(): """ Get rate limit for a specified organization """ login = demisto.getArg('adminLogin') request = req('GET', USER_API + 'users/' + login + '/rate-limit') r = request.json() rate_limits = [ { 'Minutes': demisto.get(rate_limit, 'minutes'), 'Samples': demisto.get(rate_limit, 'samples'), 'SubmissionWaitSeconds': demisto.get(rate_limit, 'submission-wait-seconds'), 'SubmissionsAvailable': demisto.get(rate_limit, 'submissions-available') } for rate_limit in demisto.get(r, 'data.organization.submission-rate-limit') ] demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.User.RateLimit': rate_limits}, 'HumanReadable': tableToMarkdown('ThreatGrid - Organization Rate Limit', rate_limits, [ 'Minutes', 'Samples', 'SubmissionWaitSeconds', 'SubmissionsAvailable' ]), 'ContentsFormat': formats['json'], 'Contents': r }) def who_am_i(): """ Get information about the current session's user """ request = req('GET', USER_API + 'session/whoami') r = request.json() user = { 'Email': demisto.get(r, 'data.email'), 'Login': demisto.get(r, 'data.login'), 'Name': demisto.get(r, 'data.name'), 'Organization': demisto.get(r, 'data.organization_id'), 'Role': demisto.get(r, 'data.role') } demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.User': user}, 'HumanReadable': tableToMarkdown('ThreatGrid - Current Session User', [user], [ 'Email', 'Login', 'Name', 'Organization', 'Role' ]), 'ContentsFormat': formats['json'], 'Contents': user }) def get_analysis_annotations(): """ Get analysis annotations for a given sample """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/analysis/annotations') annotations = [] context_path = 'ThreatGrid.AnalysisResults.Sample.Id.Annotations' ec = {context_path: []} # type: ignore ips = demisto.get(r.json(), 'data.items.network') # type: ignore if ips: for k in ips: annotation = { 'IP': k, 'IP.Asn': ips[k].get('asn'), 'IP.City': ips[k].get('city'), 'IP.Country': ips[k].get('country'), 'IP.Org': ips[k].get('org'), 'IP.Region': ips[k].get('region'), 'IP.Timestamp': ips[k].get('ts') } annotations.append(annotation) ec[context_path].append(annotation) demisto.results({ 'Type': entryTypes['note'], 'ContentsFormat': formats['json'], 'Contents': r.json(), 'EntryContext': ec, 'HumanReadable': tableToMarkdown('ThreatGrid - Analysis Annotations', annotations, [ 'IP', 'IP.Asn', 'IP.City', 'IP.Country', 'IP.Org', 'IP.Region', 'IP.Timestamp' ]) }) def get_analysis_by_id(): """ Download the analysis for a given sample """ sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/analysis.json') ec, hr = extract_data_from_analysis_json(json.loads(r.content), sample_id, demisto.getArg('limit')) demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': hr, 'Contents': r.json(), 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-analysis.json', r.content, file_type=entryTypes['entryInfoFile']) ]) def extract_data_from_analysis_json(analysis_json, sample_id, limit): """ Extracts relevant data from an analysis json """ ec = {} hr = {} sample_key = 'ThreatGrid.Sample(val.ID === obj.ID)' sample_process = extract_sample_process_from_analysis_processes(demisto.get(analysis_json, 'dynamic.processes')) or {} ec[sample_key] = create_sample_ec_from_analysis_json(analysis_json, sample_id, sample_process, limit) hr['Sample'] = create_sample_hr_from_analysis_json(ec[sample_key], analysis_json, sample_process, limit) hr['File'] = ec[sample_key]["File"] = create_file_ec_from_analysis_json(analysis_json) handle_artifact_from_analysis_json(ec, hr, analysis_json, limit) hr_str = create_analysis_json_human_readable(hr) return ec, hr_str def handle_artifact_from_analysis_json(ec, hr, analysis_json, limit): ''' Populates ec and hr with artifact data from analysis json ''' hr['Artifact'] = {} for artifact in get_with_limit(analysis_json, 'artifacts', limit).values(): id = None yaras = demisto.get(artifact, 'antivirus.yara') if yaras: for yara in filter(lambda yara: 'id' in yara, yaras): id = yara['id'] break if id: artifact_key = 'ThreatGrid.Artifact(val.ID === obj.{0})'.format(id) artifact_hr_key = 'Artifact(ID = {0})'.format(id) tags = set() for yara in filter(lambda yara: 'tags' in yara, yaras): if yara['tags']: for tag in yara['tags']: tags.add(tag) # converting to list for tableToMarkdown tags = list(tags) hr['Artifact'][artifact_hr_key] = ec[artifact_key] = { 'ID': id, 'Tags': tags, 'FamilyName': demisto.get(artifact, 'antivirus.reversing_labs.classification.family_name'), 'ThreatName': demisto.get(artifact, 'antivirus.reversing_labs.threat_name') } def create_analysis_json_human_readable(hr): hr_str = tableToMarkdown('Files scanned:', hr['File'], SAMPLE_ANALYSIS_HEADERS_MAP['File']) tmp_hr_str = '' for k in hr['Sample'].copy(): if isinstance(hr['Sample'][k], dict) or (isinstance(hr['Sample'][k], list) and len(hr['Sample'][k]) > 0 and k in SAMPLE_ANALYSIS_HEADERS_MAP): tmp_hr_str = tmp_hr_str + tableToMarkdown('{0}:'.format(str(k)), hr['Sample'][k], SAMPLE_ANALYSIS_HEADERS_MAP[k]) del hr['Sample'][k] return_sting = hr_str + tableToMarkdown('Sample analysis:', hr['Sample'], SAMPLE_ANALYSIS_HEADERS_MAP['Sample']) return_sting = return_sting + tmp_hr_str + tableToMarkdown('Artifact analysis:', hr['Artifact']) return return_sting def extract_sample_process_from_analysis_processes(processes): """ Extracts the relevant process (i.e. sample process) from the processes """ if processes: for process in processes.values(): if demisto.get(process, 'analyzed_because') == "Is target sample.": return process return None def create_sample_ec_from_analysis_json(analysis_json, sample_id, sample_process, limit): """ Creates a dictionary corresponding to required field from the analysis_json """ # Handling special case escape character directory = demisto.get(sample_process, 'startup_info.current_directory') if directory: directory = directory[:len(directory) - 1] domain_with_limit = get_with_limit(analysis_json, 'domains', limit) or {} return { 'ID': sample_id, 'VM': {'ID': demisto.get(analysis_json, 'metadata.sandcastle_env.vm_id'), 'Name': demisto.get(analysis_json, 'metadata.sandcastle_env.display_name')}, 'StartedAt': demisto.get(analysis_json, 'metadata.sandcastle_env.analysis_start'), 'EndedAt': demisto.get(analysis_json, 'metadata.sandcastle_env.analysis_end'), 'Runtime': demisto.get(analysis_json, 'metadata.sandcastle_env.run_time'), 'HeuristicScore': demisto.get(analysis_json, 'threat.heuristic_score'), 'ThreatScore': get_with_limit(analysis_json, 'threat.threat_score', limit), 'FilesDeleted': get_with_limit(sample_process, 'files_deleted', limit), 'FilesCreated': get_with_limit(sample_process, 'files_created', limit), 'FilesModified': get_with_limit(sample_process, 'files_modified', limit), 'Directory': directory, 'CMD': demisto.get(sample_process, 'startup_info.command_line'), 'ProcessName': demisto.get(sample_process, 'process_name'), 'Stream': extract_network_from_analysis_networks(get_with_limit(analysis_json, 'network', limit), full_extraction=False), 'VT': extract_vt_from_analysis_artifact(demisto.get(analysis_json, 'artifacts')), 'Domain': [{'Name': str(key), 'Status': str(val.get('status'))} for key, val in domain_with_limit.items()] } def create_sample_hr_from_analysis_json(sample_ec, analysis_json, sample_process, limit): """ Creates a human readable dictionary corresponding to required field from the analysis_json """ res = dict(sample_ec) children = get_with_limit(sample_process, 'children', limit) memory = demisto.get(sample_process, 'memory') res.update( { 'Mutants Created': get_with_limit(sample_process, 'mutants_created', limit), 'Regitry Keys Deleted': get_with_limit(sample_process, 'registry_keys_deleted', limit), 'Regisrty Keys Modified': get_with_limit(sample_process, 'registry_keys_modified', limit), 'Regitry Keys Created': get_with_limit(sample_process, 'registry_keys_created', limit), 'Threads': get_with_limit(sample_process, 'threads', limit), 'Children': len(children) if children else 0, 'Memory': len(memory) if memory and demisto.get(sample_process, 'new') == 'true' else 0, 'Network': extract_network_from_analysis_networks(get_with_limit(analysis_json, 'network', limit), full_extraction=True), 'Enviornment Details': { 'VM ID': sample_ec['VM']['ID'], 'VM Name': sample_ec['VM']['Name'], 'StartedAt': sample_ec['StartedAt'], 'EndedAt': sample_ec['EndedAt'], 'Runtime': sample_ec['Runtime'] } } ) # name of stream changes to network for human readable del res['Stream'] del res['VM'] del res['StartedAt'] del res['EndedAt'] del res['Runtime'] return res def extract_network_from_analysis_networks(networks, full_extraction=False): """ Extract network representation from the networks arg """ res = [] if networks: for network_item in networks.values(): res_item = { 'Destination': str(demisto.get(network_item, 'dst')), 'DestinationPort': demisto.get(network_item, 'dst_port'), 'PacketSize': demisto.get(network_item, 'bytes_orig') } if full_extraction: res_item['Transport'] = str(demisto.get(network_item, 'transport')) res_item['Ts_Begin'] = demisto.get(network_item, 'ts_begin') res_item['Packets'] = demisto.get(network_item, 'packets') res.append(res_item) return res def extract_vt_from_analysis_artifact(artifacts): """ Extract virusTotal representation from the artifacts arg """ if artifacts: for artifact in artifacts.values(): if demisto.get(artifact, 'antivirus.virustotal'): vt = demisto.get(artifact, 'antivirus.virustotal') return { 'Hits': demisto.get(vt, 'hits'), 'Engines': demisto.get(vt, 'engines') } def create_file_ec_from_analysis_json(analysis_json): """ Creates a file entry array from the analysis json """ malware_descs = demisto.get(analysis_json, 'metadata.malware_desc') res = [] for desc in malware_descs: res.append( { 'FileName': demisto.get(desc, 'filename'), 'Size': demisto.get(desc, 'size'), 'MD5': demisto.get(desc, 'md5'), 'SHA1': demisto.get(desc, 'sha1'), 'SHA256': demisto.get(desc, 'sha256'), 'MagicType': demisto.get(desc, 'magic'), 'Type': demisto.get(desc, 'type'), }) return res def ioc_to_readable(ioc): ioc_key_to_path_dict = { 'Title': 'title', 'Confidence': 'confidence', 'Severity': 'severity', 'IOC': 'ioc', 'Tags': 'tags', 'IOCCategory': 'category' } ioc_data_keys_set = { 'URL', 'Path', 'SHA256', 'IP' } res = {} # add ioc_key_to_path_dict values to result for k, v in ioc_key_to_path_dict.items(): val = demisto.get(ioc, v) if val: res[k] = val # add ioc_data_keys_set values to result.Data res['Data'] = {} for key in ioc_data_keys_set: res['Data'][key] = [] if demisto.get(ioc, 'data'): for item in demisto.get(ioc, 'data'): for key in ioc_data_keys_set: if demisto.get(item, key): res['Data'][key].append(demisto.get(item, key)) return res def get_analysis_iocs(): """ Get data about analysis iocs for a given sample or ioc """ sample_id = demisto.getArg('id') ioc = demisto.getArg('ioc') url = SUB_API + 'samples/' + sample_id + '/analysis/iocs' if ioc: url += '/' + ioc params = {'api_key': API_KEY} if demisto.getArg('limit'): params['limit'] = demisto.getArg('limit') r = req('GET', url, params=params) iocs = [] # type: ignore dbots = [] # type: ignore items = demisto.get(r.json(), 'data.items') # type: ignore if not items: append_to_analysis_iocs_arrays(iocs, dbots, demisto.get(r.json(), 'data')) else: for k in items: append_to_analysis_iocs_arrays(iocs, dbots, k) md = tableToMarkdown('ThreatGrid Behavioral Indicators for sample: ' + demisto.getArg('id'), iocs, ['Title', 'Confidence', 'Severity', 'IOC', 'Tags', 'IOCCategory', 'Data']) md += tableToMarkdown('DBot', dbots, ['Indicator', 'Score', 'Type', 'Vendor']) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.IOCs': iocs, 'DBotScore': dbots}, 'HumanReadable': md, 'ContentsFormat': formats['json'], 'Contents': r.json() }) def append_to_analysis_iocs_arrays(iocs, dbots, k): """ Helper for appending analysis item to ioc an dbot arrays """ if k and k.get('ioc'): iocs.append(ioc_to_readable(k)) dbots.append({ 'Vendor': 'Threat Grid', 'Type': 'IOC', 'Indicator': k.get('ioc'), 'Score': calc_score(k.get('severity')) }) def apply_search_filters(): """ Helper for applying search filters """ params = {'api_key': API_KEY} for k in demisto.args(): if demisto.getArg(k): params['term'] = k params['query'] = demisto.getArg(k) break return params def search_ips(): """ Search ips with the given filters """ r = req('GET', SUB_API + 'search/ips', params=apply_search_filters()) ips = [] for ip in demisto.get(r.json(), 'data.items'): ips.append({ 'Result': demisto.get(ip, 'result'), 'Details': demisto.get(ip, 'details') }) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.IPs': ips}, 'HumanReadable': tableToMarkdown('ThreatGrid - IP Search', ips, ['Result', 'Details']), 'ContentsFormat': formats['json'], 'Contents': r.json() }) def search_urls(): """ Search urls with the given filters """ r = req('GET', SUB_API + 'search/urls', params=apply_search_filters()) urls = [] for url in demisto.get(r.json(), 'data.items'): urls.append({ 'Result': demisto.get(url, 'result'), 'Details': demisto.get(url, 'details') }) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.URLs': urls}, 'HumanReadable': tableToMarkdown('ThreatGrid - URL Search', urls, ['Result', 'Details']), 'ContentsFormat': formats['json'], 'Contents': r.json() }) def submit_urls(args): """ Submit urls for analysis """ params = { 'api_key': API_KEY, 'url': args.get('url') } markdown = '' r = req('POST', SUB_API + 'samples', params=params) res = r.json()['data'] markdown += tableToMarkdown('Threat Grid - URL Submission', res) results = CommandResults( readable_output=markdown, outputs_prefix='Threatgrid.SearchResult', outputs_key_field='Info', outputs=res ) return results def advanced_search(args): """ Search Submissions, URLs, Samples with with query """ final_results = [] body = args.get('query') r = req('POST', USER_API + 'search', body=body) markdown = '' if r.json()['data']['sample']: for record in r.json().get('data', {}).get('sample'): final_results.append(record) markdown += tableToMarkdown('Threat Grid submission results', final_results) results = CommandResults( readable_output=markdown, outputs_prefix='Threatgrid.SearchResult', outputs_key_field='Info', outputs=final_results ) return results else: return (CommandResults(readable_output='No results found')) def search_samples(): """ Search samples with the given filters """ r = req('GET', SUB_API + 'search/samples', params=apply_search_filters()) samples = [] for sample in demisto.get(r.json(), 'data.items'): samples.append({ 'ID': demisto.get(sample, 'result'), 'Details': demisto.get(sample, 'details') }) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample': samples}, 'HumanReadable': tableToMarkdown('ThreatGrid - Sample Search', samples, ['Result', 'Details']), 'ContentsFormat': formats['json'], 'Contents': r.json() }) def search_submissions(): """ Search submissions with the given filters """ r = req('GET', SUB_API + 'search/submissions', params=handle_filters()) submissions = [] for submission in demisto.get(r.json(), 'data.items'): sample = sample_to_readable(demisto.get(submission, 'item')) sample['ID'] = demisto.get(submission, 'item.sample') sample['ThreatScore'] = demisto.get(submission, 'item.analysis.threat_score') submissions.append(sample) demisto.results({ 'Type': entryTypes['note'], 'EntryContext': {'ThreatGrid.Sample(val.ID == obj.ID)': submissions}, 'HumanReadable': tableToMarkdown('ThreatGrid - Submission Search', submissions, ['ID', 'Filename', 'State', 'Status', 'MD5', 'SHA1', 'SHA256', 'SubmittedAt', 'ThreatScore']), 'ContentsFormat': formats['json'], 'Contents': r.json() }) def url_to_file(): """ Convert a url to file for detonation """ urls = argToList(demisto.getArg('urls')) files = [] for i in range(len(urls)): fileEntry = fileResult('url_' + str(i + 1), '[InternetShortcut]\nURL=' + str(urls[i])) files.append(fileEntry) demisto.results(files) def get_specific_feed(): """ Get specific feed """ feed_name = demisto.getArg('feed-name') feed_period = '_' + demisto.getArg('feed-period') if demisto.getArg('feed-period') else '' output_type = demisto.getArg('output-type') r = req('GET', USER_API + 'feeds/' + feed_name + feed_period + '.' + output_type) demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': {}, 'HumanReadable': '### ThreatGrid Specific Feed File -\n' + 'Your specific feed file download request has been completed successfully for ' + feed_name, 'Contents': {}, 'ContentsFormat': formats['json'] }, fileResult(feed_name + output_type, r.content) ]) def feeds_helper(name): name_conversion = { 'domain': 'domains', 'ip': 'ips', 'network-stream': 'network_streams', 'registry-key': 'registry_keys', 'url': 'urls', 'path': 'paths' } requested_feed = name_conversion[name] if name in name_conversion else name url = SUB_API + 'iocs/feeds/' + requested_feed r = req('GET', url, params=handle_filters()) content = json.loads(r.content.decode('utf-8')) if isinstance(r.content, bytes) else r.content, demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': {}, 'HumanReadable': 'Your feeds ' + name + ' file download request has been completed successfully', 'Contents': content, 'ContentsFormat': formats['json'] }, fileResult(url, r.content) ]) def get_analysis_artifact(): aid = demisto.getArg('aid') sample_id = demisto.getArg('id') url = SUB_API + 'samples/' + sample_id + '/analysis/artifacts' if aid: url += '/' + aid r = req('GET', url) ec = {'ThreatGrid.Sample(val.ID === {0})'.format(sample_id): r.json()} demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': ec, 'HumanReadable': None, 'Contents': r.json(), 'ContentsFormat': formats['json'] } ]) def get_analysis_metadata(): sample_id = demisto.getArg('id') r = req('GET', SUB_API + 'samples/' + sample_id + '/analysis/metadata') demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': {}, 'HumanReadable': None, 'Contents': r.json(), 'ContentsFormat': formats['json'] } ]) def get_analysis_network_stream(): sample_id = demisto.getArg('id') nsid = demisto.getArg('nsid') url = SUB_API + 'samples/' + sample_id + '/analysis/artifacts' if nsid: url += '/' + nsid r = req('GET', url) demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': {}, 'HumanReadable': None, 'Contents': r.json(), 'ContentsFormat': formats['json'] } ]) def get_analysis_process(): sample_id = demisto.getArg('id') pid = demisto.getArg('pid') url = SUB_API + 'samples/' + sample_id + '/analysis/processes' if pid: url += '/' + pid r = req('GET', url) demisto.results([ { 'Type': entryTypes['note'], 'EntryContext': {}, 'HumanReadable': None, 'Contents': r.json(), 'ContentsFormat': formats['json'] }, fileResult(sample_id + '-sample.zip', r.content) ]) def main(): args = demisto.args() if demisto.command() == 'test-module': req('GET', USER_API + 'session/whoami') demisto.results('ok') elif demisto.command() == 'threat-grid-download-sample-by-id': download_sample() elif demisto.command() == 'threat-grid-get-samples': get_samples() elif demisto.command() == 'threat-grid-get-sample-by-id': get_sample_by_id() elif demisto.command() == 'threat-grid-get-sample-state-by-id' or demisto.command() == 'threat-grid-get-samples-state': get_sample_state_by_id() elif demisto.command() == 'threat-grid-upload-sample': upload_sample() elif demisto.command() == 'threat-grid-get-html-report-by-id': get_html_report_by_id() elif demisto.command() == 'threat-grid-get-pcap-by-id': get_pcap_by_id() elif demisto.command() == 'threat-grid-get-processes-by-id': get_processes_by_id() elif demisto.command() == 'threat-grid-get-summary-by-id': get_summary_by_id() elif demisto.command() == 'threat-grid-get-threat-summary-by-id': get_threat_summary_by_id() elif demisto.command() == 'threat-grid-get-video-by-id': get_video_by_id() elif demisto.command() == 'threat-grid-get-warnings-by-id': get_warnings_by_id() elif demisto.command() == 'threat-grid-user-get-rate-limit': user_get_rate_limit() elif demisto.command() == 'threat-grid-organization-get-rate-limit': organization_get_rate_limit() elif demisto.command() == 'threat-grid-who-am-i': who_am_i() elif demisto.command() == 'threat-grid-get-analysis-annotations': get_analysis_annotations() elif demisto.command() == 'threat-grid-get-analysis-by-id': get_analysis_by_id() elif demisto.command() == 'threat-grid-get-analysis-iocs' or demisto.command() == 'threat-grid-get-analysis-ioc': get_analysis_iocs() elif demisto.command() == 'threat-grid-url-to-file': url_to_file() elif demisto.command() == 'threat-grid-search-samples': search_samples() elif demisto.command() == 'threat-grid-search-ips': search_ips() elif demisto.command() == 'threat-grid-search-urls': search_urls() elif demisto.command() == 'threat-grid-advanced-search': return_results(advanced_search(args)) elif demisto.command() == 'threat-grid-submit-urls': return_results(submit_urls(args)) elif demisto.command() == 'threat-grid-search-submissions': search_submissions() elif demisto.command() == 'threat-grid-get-specific-feed': get_specific_feed() elif demisto.command() in ['threat-grid-feeds-artifacts', 'threat-grid-feeds-domain', 'threat-grid-feeds-ip', 'threat-grid-feeds-network-stream', 'threat-grid-feeds-registry-key', 'threat-grid-feeds-url', 'threat-grid-feeds-path']: feeds_helper(demisto.command()[18:]) elif demisto.command() == 'threat-grid-get-analysis-artifact' or \ demisto.command() == 'threat-grid-get-analysis-artifacts': get_analysis_artifact() elif demisto.command() == 'threat-grid-get-analysis-metadata': get_analysis_metadata() elif demisto.command() == 'threat-grid-get-analysis-network-stream' or \ demisto.command() == 'threat-grid-get-analysis-network-streams': get_analysis_network_stream() elif demisto.command() == 'threat-grid-get-analysis-process' or \ demisto.command() == 'threat-grid-get-analysis-processes': get_analysis_process() elif demisto.command() in ['threat-grid-download-artifact', 'threat-grid-detonate-file']: return_error('Error: The API for this command is no longer supported') else: return_error('Unrecognized command: ' + demisto.command()) if __name__ in ["__builtin__", "builtins"]: main()




































